Ticket #5461: 5461-r8225.diff
File 5461-r8225.diff, 166.1 KB (added by , 16 years ago) |
---|
-
django/test/simple.py
3 3 from django.db.models import get_app, get_apps 4 4 from django.test import _doctest as doctest 5 5 from django.test.utils import setup_test_environment, teardown_test_environment 6 from django.test.utils import create_test_db, destroy_test_db7 6 from django.test.testcases import OutputChecker, DocTestRunner 8 7 9 8 # The module name for tests outside models.py … … 139 138 suite.addTest(test) 140 139 141 140 old_name = settings.DATABASE_NAME 142 create_test_db(verbosity, autoclobber=not interactive) 141 from django.db import connection 142 connection.creation.create_test_db(verbosity, autoclobber=not interactive) 143 143 result = unittest.TextTestRunner(verbosity=verbosity).run(suite) 144 destroy_test_db(old_name, verbosity)144 connection.creation.destroy_test_db(old_name, verbosity) 145 145 146 146 teardown_test_environment() 147 147 -
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 from django.core.management import call_command6 5 from django.test import signals 7 6 from django.template import Template 8 7 from django.utils.translation import deactivate 9 8 10 # The prefix to put on the default database name when creating11 # the test database.12 TEST_DATABASE_PREFIX = 'test_'13 14 9 def instrumented_test_render(self, context): 15 10 """ 16 11 An instrumented Template render method, providing a signal … … 70 65 71 66 del mail.outbox 72 67 73 def _set_autocommit(connection):74 "Make sure a connection is in autocommit mode."75 if hasattr(connection.connection, "autocommit"):76 if callable(connection.connection.autocommit):77 connection.connection.autocommit(True)78 else:79 connection.connection.autocommit = True80 elif hasattr(connection.connection, "set_isolation_level"):81 connection.connection.set_isolation_level(0)82 83 def get_mysql_create_suffix():84 suffix = []85 if settings.TEST_DATABASE_CHARSET:86 suffix.append('CHARACTER SET %s' % settings.TEST_DATABASE_CHARSET)87 if settings.TEST_DATABASE_COLLATION:88 suffix.append('COLLATE %s' % settings.TEST_DATABASE_COLLATION)89 return ' '.join(suffix)90 91 def get_postgresql_create_suffix():92 assert settings.TEST_DATABASE_COLLATION is None, "PostgreSQL does not support collation setting at database creation time."93 if settings.TEST_DATABASE_CHARSET:94 return "WITH ENCODING '%s'" % settings.TEST_DATABASE_CHARSET95 return ''96 97 def create_test_db(verbosity=1, autoclobber=False):98 """99 Creates a test database, prompting the user for confirmation if the100 database already exists. Returns the name of the test database created.101 """102 # If the database backend wants to create the test DB itself, let it103 creation_module = get_creation_module()104 if hasattr(creation_module, "create_test_db"):105 creation_module.create_test_db(settings, connection, verbosity, autoclobber)106 return107 108 if verbosity >= 1:109 print "Creating test database..."110 # If we're using SQLite, it's more convenient to test against an111 # in-memory database. Using the TEST_DATABASE_NAME setting you can still choose112 # to run on a physical database.113 if settings.DATABASE_ENGINE == "sqlite3":114 if settings.TEST_DATABASE_NAME and settings.TEST_DATABASE_NAME != ":memory:":115 TEST_DATABASE_NAME = settings.TEST_DATABASE_NAME116 # Erase the old test database117 if verbosity >= 1:118 print "Destroying old test database..."119 if os.access(TEST_DATABASE_NAME, os.F_OK):120 if not autoclobber:121 confirm = raw_input("Type 'yes' if you would like to try deleting the test database '%s', or 'no' to cancel: " % TEST_DATABASE_NAME)122 if autoclobber or confirm == 'yes':123 try:124 if verbosity >= 1:125 print "Destroying old test database..."126 os.remove(TEST_DATABASE_NAME)127 except Exception, e:128 sys.stderr.write("Got an error deleting the old test database: %s\n" % e)129 sys.exit(2)130 else:131 print "Tests cancelled."132 sys.exit(1)133 if verbosity >= 1:134 print "Creating test database..."135 else:136 TEST_DATABASE_NAME = ":memory:"137 else:138 suffix = {139 'postgresql': get_postgresql_create_suffix,140 'postgresql_psycopg2': get_postgresql_create_suffix,141 'mysql': get_mysql_create_suffix,142 }.get(settings.DATABASE_ENGINE, lambda: '')()143 if settings.TEST_DATABASE_NAME:144 TEST_DATABASE_NAME = settings.TEST_DATABASE_NAME145 else:146 TEST_DATABASE_NAME = TEST_DATABASE_PREFIX + settings.DATABASE_NAME147 148 qn = connection.ops.quote_name149 150 # Create the test database and connect to it. We need to autocommit151 # if the database supports it because PostgreSQL doesn't allow152 # CREATE/DROP DATABASE statements within transactions.153 cursor = connection.cursor()154 _set_autocommit(connection)155 try:156 cursor.execute("CREATE DATABASE %s %s" % (qn(TEST_DATABASE_NAME), suffix))157 except Exception, e:158 sys.stderr.write("Got an error creating the test database: %s\n" % e)159 if not autoclobber:160 confirm = raw_input("Type 'yes' if you would like to try deleting the test database '%s', or 'no' to cancel: " % TEST_DATABASE_NAME)161 if autoclobber or confirm == 'yes':162 try:163 if verbosity >= 1:164 print "Destroying old test database..."165 cursor.execute("DROP DATABASE %s" % qn(TEST_DATABASE_NAME))166 if verbosity >= 1:167 print "Creating test database..."168 cursor.execute("CREATE DATABASE %s %s" % (qn(TEST_DATABASE_NAME), suffix))169 except Exception, e:170 sys.stderr.write("Got an error recreating the test database: %s\n" % e)171 sys.exit(2)172 else:173 print "Tests cancelled."174 sys.exit(1)175 176 connection.close()177 settings.DATABASE_NAME = TEST_DATABASE_NAME178 179 call_command('syncdb', verbosity=verbosity, interactive=False)180 181 if settings.CACHE_BACKEND.startswith('db://'):182 cache_name = settings.CACHE_BACKEND[len('db://'):]183 call_command('createcachetable', cache_name)184 185 # Get a cursor (even though we don't need one yet). This has186 # the side effect of initializing the test database.187 cursor = connection.cursor()188 189 return TEST_DATABASE_NAME190 191 def destroy_test_db(old_database_name, verbosity=1):192 # If the database wants to drop the test DB itself, let it193 creation_module = get_creation_module()194 if hasattr(creation_module, "destroy_test_db"):195 creation_module.destroy_test_db(settings, connection, old_database_name, verbosity)196 return197 198 if verbosity >= 1:199 print "Destroying test database..."200 connection.close()201 TEST_DATABASE_NAME = settings.DATABASE_NAME202 settings.DATABASE_NAME = old_database_name203 if settings.DATABASE_ENGINE == "sqlite3":204 if TEST_DATABASE_NAME and TEST_DATABASE_NAME != ":memory:":205 # Remove the SQLite database file206 os.remove(TEST_DATABASE_NAME)207 else:208 # Remove the test database to clean up after209 # ourselves. Connect to the previous database (not the test database)210 # to do so, because it's not allowed to delete a database while being211 # connected to it.212 cursor = connection.cursor()213 _set_autocommit(connection)214 time.sleep(1) # To avoid "database is being accessed by other users" errors.215 cursor.execute("DROP DATABASE %s" % connection.ops.quote_name(TEST_DATABASE_NAME))216 connection.close() -
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 … … 145 145 # as the TextField Django field type, which means XMLField's 146 146 # get_internal_type() returns 'TextField'. 147 147 # 148 # But the limitation of the get_internal_type() / DATA_TYPESapproach148 # But the limitation of the get_internal_type() / data_types approach 149 149 # is that it cannot handle database column types that aren't already 150 150 # mapped to one of the built-in Django field types. In this case, you 151 151 # can implement db_type() instead of get_internal_type() to specify 152 152 # exactly which wacky database column type you want to use. 153 153 data = DictWrapper(self.__dict__, connection.ops.quote_name, "qn_") 154 154 try: 155 return get_creation_module().DATA_TYPES[self.get_internal_type()] % data155 return connection.creation.data_types[self.get_internal_type()] % data 156 156 except KeyError: 157 157 return None 158 158 -
django/db/__init__.py
14 14 # backends that ships with Django, so look there first. 15 15 _import_path = 'django.db.backends.' 16 16 backend = __import__('%s%s.base' % (_import_path, settings.DATABASE_ENGINE), {}, {}, ['']) 17 creation = __import__('%s%s.creation' % (_import_path, settings.DATABASE_ENGINE), {}, {}, [''])18 17 except ImportError, e: 19 18 # If the import failed, we might be looking for a database backend 20 19 # distributed external to Django. So we'll try that next. 21 20 try: 22 21 _import_path = '' 23 22 backend = __import__('%s.base' % settings.DATABASE_ENGINE, {}, {}, ['']) 24 creation = __import__('%s.creation' % settings.DATABASE_ENGINE, {}, {}, [''])25 23 except ImportError, e_user: 26 24 # The database backend wasn't found. Display a helpful error message 27 25 # listing all possible (built-in) database backends. … … 29 27 available_backends = [f for f in os.listdir(backend_dir) if not f.startswith('_') and not f.startswith('.') and not f.endswith('.py') and not f.endswith('.pyc')] 30 28 available_backends.sort() 31 29 if settings.DATABASE_ENGINE not in available_backends: 32 raise ImproperlyConfigured, "%r isn't an available database backend. Available options are: %s " % \33 (settings.DATABASE_ENGINE, ", ".join(map(repr, available_backends )))30 raise ImproperlyConfigured, "%r isn't an available database backend. Available options are: %s\nError was: %s" % \ 31 (settings.DATABASE_ENGINE, ", ".join(map(repr, available_backends, e_user))) 34 32 else: 35 33 raise # If there's some other error, this must be an error in Django itself. 36 34 37 def _import_database_module(import_path='', module_name=''):38 """Lazily import a database module when requested."""39 return __import__('%s%s.%s' % (import_path, settings.DATABASE_ENGINE, module_name), {}, {}, [''])40 41 # We don't want to import the introspect module unless someone asks for it, so42 # lazily load it on demmand.43 get_introspection_module = curry(_import_database_module, _import_path, 'introspection')44 45 def get_creation_module():46 return creation47 48 # We want runshell() to work the same way, but we have to treat it a49 # little differently (since it just runs instead of returning a module like50 # the above) and wrap the lazily-loaded runshell() method.51 runshell = lambda: _import_database_module(_import_path, "client").runshell()52 53 35 # Convenient aliases for backend bits. 54 36 connection = backend.DatabaseWrapper(**settings.DATABASE_OPTIONS) 55 37 DatabaseError = backend.DatabaseError -
django/db/backends/postgresql/base.py
4 4 Requires psycopg 1: http://initd.org/projects/psycopg1 5 5 """ 6 6 7 from django.db.backends import BaseDatabaseFeatures 8 from django.db.backends import BaseDatabaseValidation 9 from django.db.backends import BaseDatabaseWrapper 10 from django.db.backends import util 11 from django.db.backends.postgresql.client import DatabaseClient 12 from django.db.backends.postgresql.creation import DatabaseCreation 13 from django.db.backends.postgresql.introspection import DatabaseIntrospection 14 from django.db.backends.postgresql.operations import DatabaseOperations 7 15 from django.utils.encoding import smart_str, smart_unicode 8 from django.db.backends import BaseDatabaseWrapper, BaseDatabaseFeatures, util 9 from django.db.backends.postgresql.operations import DatabaseOperations 16 10 17 try: 11 18 import psycopg as Database 12 19 except ImportError, e: … … 62 69 class DatabaseFeatures(BaseDatabaseFeatures): 63 70 pass # This backend uses all the defaults. 64 71 72 class DatabaseValidation(BaseDatabaseValidation): 73 pass 74 65 75 class DatabaseWrapper(BaseDatabaseWrapper): 66 features = DatabaseFeatures()67 ops = DatabaseOperations()68 76 operators = { 69 77 'exact': '= %s', 70 78 'iexact': 'ILIKE %s', … … 82 90 'iendswith': 'ILIKE %s', 83 91 } 84 92 93 def __init__(self, *args, **kwargs): 94 super(DatabaseWrapper, self).__init__(*args, **kwargs) 95 96 self.features = DatabaseFeatures() 97 self.ops = DatabaseOperations() 98 self.client = DatabaseClient() 99 self.creation = DatabaseCreation(self) 100 self.introspection = DatabaseIntrospection(self) 101 self.validation = DatabaseValidation() 102 85 103 def _cursor(self, settings): 86 104 set_tz = False 87 105 if self.connection is None: -
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 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()] 4 31 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()] 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" % self.connection.ops.quote_name(table_name)) 35 return cursor.description 15 36 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 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 20 57 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 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 41 86 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.conf import settings 2 from django.db.backends.creation import BaseDatabaseCreation 3 4 class DatabaseCreation(BaseDatabaseCreation): 5 # This dictionary maps Field objects to their associated PostgreSQL column 6 # types, as strings. Column-type strings can contain format strings; they'll 7 # be interpolated against the values of Field.__dict__ before being output. 8 # If a column type is set to None, it won't be included in the output. 9 data_types = { 10 'AutoField': 'serial', 11 'BooleanField': 'boolean', 12 'CharField': 'varchar(%(max_length)s)', 13 'CommaSeparatedIntegerField': 'varchar(%(max_length)s)', 14 'DateField': 'date', 15 'DateTimeField': 'timestamp with time zone', 16 'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)', 17 'FileField': 'varchar(%(max_length)s)', 18 'FilePathField': 'varchar(%(max_length)s)', 19 'FloatField': 'double precision', 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 } 33 34 def _creation_suffix(self): 35 assert settings.TEST_DATABASE_COLLATION is None, "PostgreSQL does not support collation setting at database creation time." 36 if settings.TEST_DATABASE_CHARSET: 37 return "WITH ENCODING '%s'" % settings.TEST_DATABASE_CHARSET 38 return '' -
django/db/backends/sqlite3/base.py
6 6 Python 2.5 and later use the sqlite3 module in the standard library. 7 7 """ 8 8 9 from django.db.backends import BaseDatabaseWrapper, BaseDatabaseFeatures, BaseDatabaseOperations, util 9 from django.db.backends import BaseDatabaseWrapper 10 from django.db.backends import BaseDatabaseFeatures 11 from django.db.backends import BaseDatabaseOperations 12 from django.db.backends import BaseDatabaseValidation 13 from django.db.backends import util 14 from django.db.backends.sqlite3.client import DatabaseClient 15 from django.db.backends.sqlite3.creation import DatabaseCreation 16 from django.db.backends.sqlite3.introspection import DatabaseIntrospection 17 10 18 try: 11 19 try: 12 20 from sqlite3 import dbapi2 as Database … … 39 47 Database.register_adapter(decimal.Decimal, util.rev_typecast_decimal) 40 48 41 49 class DatabaseFeatures(BaseDatabaseFeatures): 42 supports_constraints = False43 50 # SQLite cannot handle us only partially reading from a cursor's result set 44 51 # and then writing the same rows to the database in another cursor. This 45 52 # setting ensures we always read result sets fully into memory all in one … … 89 96 second = '%s-12-31 23:59:59.999999' 90 97 return [first % value, second % value] 91 98 99 class DatabaseValidation(BaseDatabaseValidation): 100 pass 92 101 93 102 class DatabaseWrapper(BaseDatabaseWrapper): 94 features = DatabaseFeatures() 95 ops = DatabaseOperations() 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. 99 106 # See http://www.sqlite.org/lang_expr.html for an explanation. … … 114 121 'iendswith': "LIKE %s ESCAPE '\\'", 115 122 } 116 123 124 def __init__(self, *args, **kwargs): 125 super(DatabaseWrapper, self).__init__(*args, **kwargs) 126 127 self.features = DatabaseFeatures() 128 self.ops = DatabaseOperations() 129 self.client = DatabaseClient() 130 self.creation = DatabaseCreation(self) 131 self.introspection = DatabaseIntrospection(self) 132 self.validation = DatabaseValidation() 133 117 134 def _cursor(self, settings): 118 135 if self.connection is None: 119 136 if not settings.DATABASE_NAME: -
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 get_table_list(self, cursor): 39 "Returns a list of table names in the current database." 40 # Skip the sqlite_sequence system table used for autoincrement key 41 # generation. 42 cursor.execute(""" 43 SELECT name FROM sqlite_master 44 WHERE type='table' AND NOT name='sqlite_sequence' 45 ORDER BY name""") 46 return [row[0] for row in cursor.fetchall()] 47 48 def get_table_description(self, cursor, table_name): 49 "Returns a description of the table, with the DB-API cursor.description interface." 50 return [(info['name'], info['type'], None, None, None, None, 51 info['null_ok']) for info in self._table_info(cursor, table_name)] 52 53 def get_relations(self, cursor, table_name): 54 raise NotImplementedError 55 56 def get_indexes(self, cursor, table_name): 57 """ 58 Returns a dictionary of fieldname -> infodict for the given table, 59 where each infodict is in the format: 60 {'primary_key': boolean representing whether it's the primary key, 61 'unique': boolean representing whether it's a unique index} 62 """ 63 indexes = {} 64 for info in self._table_info(cursor, table_name): 65 indexes[info['name']] = {'primary_key': info['pk'] != 0, 66 'unique': False} 67 cursor.execute('PRAGMA index_list(%s)' % self.ops.quote_name(table_name)) 68 # seq, name, unique 69 for index, unique in [(field[1], field[2]) for field in cursor.fetchall()]: 70 if not unique: 71 continue 72 cursor.execute('PRAGMA index_info(%s)' % self.ops.quote_name(index)) 73 info = cursor.fetchall() 74 # Skip indexes across multiple fields 75 if len(info) != 1: 76 continue 77 name = info[0][2] # seqno, cid, name 78 indexes[name]['unique'] = True 79 return indexes 80 81 def _table_info(self, cursor, name): 82 cursor.execute('PRAGMA table_info(%s)' % self.ops.quote_name(name)) 83 # cid, name, type, notnull, dflt_value, pk 84 return [{'name': field[1], 85 'type': field[2], 86 'null_ok': not field[3], 87 'pk': field[5] # undocumented 88 } for field in cursor.fetchall()] 89 -
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 import os 2 import sys 3 from django.conf import settings 4 from django.db.backends.creation import BaseDatabaseCreation 5 6 class DatabaseCreation(BaseDatabaseCreation): 7 # SQLite doesn't actually support most of these types, but it "does the right 8 # thing" given more verbose field definitions, so leave them as is so that 9 # schema inspection is more useful. 10 data_types = { 11 'AutoField': 'integer', 12 'BooleanField': 'bool', 13 'CharField': 'varchar(%(max_length)s)', 14 'CommaSeparatedIntegerField': 'varchar(%(max_length)s)', 15 'DateField': 'date', 16 'DateTimeField': 'datetime', 17 'DecimalField': 'decimal', 18 'FileField': 'varchar(%(max_length)s)', 19 'FilePathField': 'varchar(%(max_length)s)', 20 'FloatField': 'real', 21 'IntegerField': 'integer', 22 'IPAddressField': 'char(15)', 23 'NullBooleanField': 'bool', 24 'OneToOneField': 'integer', 25 'PhoneNumberField': 'varchar(20)', 26 'PositiveIntegerField': 'integer unsigned', 27 'PositiveSmallIntegerField': 'smallint unsigned', 28 'SlugField': 'varchar(%(max_length)s)', 29 'SmallIntegerField': 'smallint', 30 'TextField': 'text', 31 'TimeField': 'time', 32 'USStateField': 'varchar(2)', 33 } 34 35 def sql_for_pending_references(self, model, style, pending_references): 36 "SQLite3 doesn't support constraints" 37 return [] 38 39 def sql_remove_table_constraints(self, model, references_to_delete): 40 "SQLite3 doesn't support constraints" 41 return [] 42 43 def _create_test_db(self, verbosity, autoclobber): 44 if settings.TEST_DATABASE_NAME and settings.TEST_DATABASE_NAME != ":memory:": 45 test_database_name = settings.TEST_DATABASE_NAME 46 # Erase the old test database 47 if verbosity >= 1: 48 print "Destroying old test database..." 49 if os.access(test_database_name, os.F_OK): 50 if not autoclobber: 51 confirm = raw_input("Type 'yes' if you would like to try deleting the test database '%s', or 'no' to cancel: " % test_database_name) 52 if autoclobber or confirm == 'yes': 53 try: 54 if verbosity >= 1: 55 print "Destroying old test database..." 56 os.remove(test_database_name) 57 except Exception, e: 58 sys.stderr.write("Got an error deleting the old test database: %s\n" % e) 59 sys.exit(2) 60 else: 61 print "Tests cancelled." 62 sys.exit(1) 63 if verbosity >= 1: 64 print "Creating test database..." 65 else: 66 test_database_name = ":memory:" 67 return test_database_name 68 69 def _destroy_test_db(self, test_database_name, verbosity): 70 if test_database_name and test_database_name != ":memory:": 71 # Remove the SQLite database file 72 os.remove(test_database_name) 73 74 No newline at end of file -
django/db/backends/mysql/base.py
4 4 Requires MySQLdb: http://sourceforge.net/projects/mysql-python 5 5 """ 6 6 7 from django.db.backends import BaseDatabaseWrapper, BaseDatabaseFeatures, BaseDatabaseOperations, util 7 from django.db.backends import BaseDatabaseFeatures 8 from django.db.backends import BaseDatabaseOperations 9 from django.db.backends import BaseDatabaseWrapper 10 from django.db.backends import util 11 from django.db.backends.mysql.client import DatabaseClient 12 from django.db.backends.mysql.creation import DatabaseCreation 13 from django.db.backends.mysql.introspection import DatabaseIntrospection 14 from django.db.backends.mysql.validation import DatabaseValidation 15 8 16 try: 9 17 import MySQLdb as Database 10 18 except ImportError, e: … … 60 68 # TRADITIONAL will automatically cause most warnings to be treated as errors. 61 69 62 70 class DatabaseFeatures(BaseDatabaseFeatures): 63 inline_fk_references = False64 71 empty_fetchmany_value = () 65 72 update_can_self_select = False 66 73 … … 142 149 return [first % value, second % value] 143 150 144 151 class DatabaseWrapper(BaseDatabaseWrapper): 145 features = DatabaseFeatures() 146 ops = DatabaseOperations() 152 147 153 operators = { 148 154 'exact': '= BINARY %s', 149 155 'iexact': 'LIKE %s', … … 164 170 def __init__(self, **kwargs): 165 171 super(DatabaseWrapper, self).__init__(**kwargs) 166 172 self.server_version = None 173 174 self.features = DatabaseFeatures() 175 self.ops = DatabaseOperations() 176 self.client = DatabaseClient() 177 self.creation = DatabaseCreation(self) 178 self.introspection = DatabaseIntrospection(self) 179 self.validation = DatabaseValidation() 167 180 168 181 def _valid_connection(self): 169 182 if self.connection is not None: -
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.description30 def get_table_list(self, cursor): 31 "Returns a list of table names in the current database." 32 cursor.execute("SHOW TABLES") 33 return [row[0] for row in cursor.fetchall()] 18 34 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))]) 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.connection.ops.quote_name(table_name)) 38 return cursor.description 25 39 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()) 40 def _name_to_index(self, cursor, table_name): 41 """ 42 Returns a dictionary of {field_name: field_index} for the given table. 43 Indexes are 0-based. 44 """ 45 return dict([(d[0], i) for i, d in enumerate(self.get_table_description(cursor, table_name))]) 56 46 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) 47 def get_relations(self, cursor, table_name): 48 """ 49 Returns a dictionary of {field_index: (field_index_other_table, other_table)} 50 representing all relationships to the given table. Indexes are 0-based. 51 """ 52 my_field_dict = self._name_to_index(cursor, table_name) 53 constraints = [] 54 relations = {} 55 try: 56 # This should work for MySQL 5.0. 57 cursor.execute(""" 58 SELECT column_name, referenced_table_name, referenced_column_name 59 FROM information_schema.key_column_usage 60 WHERE table_name = %s 61 AND table_schema = DATABASE() 62 AND referenced_table_name IS NOT NULL 63 AND referenced_column_name IS NOT NULL""", [table_name]) 64 constraints.extend(cursor.fetchall()) 65 except (ProgrammingError, OperationalError): 66 # Fall back to "SHOW CREATE TABLE", for previous MySQL versions. 67 # Go through all constraints and save the equal matches. 68 cursor.execute("SHOW CREATE TABLE %s" % self.connection.ops.quote_name(table_name)) 69 for row in cursor.fetchall(): 70 pos = 0 71 while True: 72 match = foreign_key_re.search(row[1], pos) 73 if match == None: 74 break 75 pos = match.end() 76 constraints.append(match.groups()) 61 77 62 return relations 78 for my_fieldname, other_table, other_field in constraints: 79 other_field_index = self._name_to_index(cursor, other_table)[other_field] 80 my_field_index = my_field_dict[my_fieldname] 81 relations[my_field_index] = (other_field_index, other_table) 63 82 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 83 return relations 76 84 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 } 85 def get_indexes(self, cursor, table_name): 86 """ 87 Returns a dictionary of fieldname -> infodict for the given table, 88 where each infodict is in the format: 89 {'primary_key': boolean representing whether it's the primary key, 90 'unique': boolean representing whether it's a unique index} 91 """ 92 cursor.execute("SHOW INDEX FROM %s" % self.connection.ops.quote_name(table_name)) 93 indexes = {} 94 for row in cursor.fetchall(): 95 indexes[row[4]] = {'primary_key': (row[2] == 'PRIMARY'), 'unique': not bool(row[1])} 96 return indexes 97 -
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.conf import settings 2 from django.db.backends.creation import BaseDatabaseCreation 3 4 class DatabaseCreation(BaseDatabaseCreation): 5 # This dictionary maps Field objects to their associated MySQL column 6 # types, as strings. Column-type strings can contain format strings; they'll 7 # be interpolated against the values of Field.__dict__ before being output. 8 # If a column type is set to None, it won't be included in the output. 9 data_types = { 10 'AutoField': 'integer AUTO_INCREMENT', 11 'BooleanField': 'bool', 12 'CharField': 'varchar(%(max_length)s)', 13 'CommaSeparatedIntegerField': 'varchar(%(max_length)s)', 14 'DateField': 'date', 15 'DateTimeField': 'datetime', 16 'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)', 17 'FileField': 'varchar(%(max_length)s)', 18 'FilePathField': 'varchar(%(max_length)s)', 19 'FloatField': 'double precision', 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 } 33 34 def _creation_suffix(self): 35 suffix = [] 36 if settings.TEST_DATABASE_CHARSET: 37 suffix.append('CHARACTER SET %s' % settings.TEST_DATABASE_CHARSET) 38 if settings.TEST_DATABASE_COLLATION: 39 suffix.append('COLLATE %s' % settings.TEST_DATABASE_COLLATION) 40 return ' '.join(suffix) 41 42 def sql_for_inline_foreign_key_references(self, field, known_models, style): 43 "All inline references are pending under MySQL" 44 return [], True 45 46 def sql_for_inline_many_to_many_references(self, model, field, style): 47 from django.db import models 48 opts = model._meta 49 qn = self.connection.ops.quote_name 50 51 table_output = [ 52 ' %s %s %s,' % 53 (style.SQL_FIELD(qn(field.m2m_column_name())), 54 style.SQL_COLTYPE(models.ForeignKey(model).db_type()), 55 style.SQL_KEYWORD('NOT NULL')), 56 ' %s %s %s,' % 57 (style.SQL_FIELD(qn(field.m2m_reverse_name())), 58 style.SQL_COLTYPE(models.ForeignKey(field.rel.to).db_type()), 59 style.SQL_KEYWORD('NOT NULL')) 60 ] 61 deferred = [ 62 (field.m2m_db_table(), field.m2m_column_name(), opts.db_table, 63 opts.pk.column), 64 (field.m2m_db_table(), field.m2m_reverse_name(), 65 field.rel.to._meta.db_table, field.rel.to._meta.pk.column) 66 ] 67 return table_output, deferred 68 69 No newline at end of file -
django/db/backends/oracle/base.py
8 8 import datetime 9 9 import time 10 10 11 from django.db.backends import BaseDatabaseWrapper, BaseDatabaseFeatures, BaseDatabaseOperations, util 11 from django.db.backends import BaseDatabaseFeatures 12 from django.db.backends import BaseDatabaseOperations 13 from django.db.backends import BaseDatabaseWrapper 14 from django.db.backends import BaseDatabaseValidation 15 from django.db.backends import util 12 16 from django.db.backends.oracle import query 17 from django.db.backends.oracle.client import DatabaseClient 18 from django.db.backends.oracle.creation import DatabaseCreation 19 from django.db.backends.oracle.introspection import DatabaseIntrospection 13 20 from django.utils.encoding import smart_str, force_unicode 14 21 15 22 # Oracle takes client-side character set encoding from the environment. … … 24 31 IntegrityError = Database.IntegrityError 25 32 26 33 class DatabaseFeatures(BaseDatabaseFeatures): 27 allows_group_by_ordinal = False28 34 empty_fetchmany_value = () 29 35 needs_datetime_string_cast = False 30 supports_tablespaces = True31 uses_case_insensitive_names = True32 36 uses_custom_query_class = True 33 37 interprets_empty_strings_as_nulls = True 34 38 … … 194 198 return [first % value, second % value] 195 199 196 200 201 class DatabaseValidation(BaseDatabaseValidation): 202 pass 197 203 198 204 class DatabaseWrapper(BaseDatabaseWrapper): 199 features = DatabaseFeatures() 200 ops = DatabaseOperations() 205 201 206 operators = { 202 207 'exact': '= %s', 203 208 'iexact': '= UPPER(%s)', … … 214 219 } 215 220 oracle_version = None 216 221 222 def __init__(self, *args, **kwargs): 223 super(DatabaseWrapper, self).__init__(*args, **kwargs) 224 225 self.features = DatabaseFeatures() 226 self.ops = DatabaseOperations() 227 self.client = DatabaseClient() 228 self.creation = DatabaseCreation(self) 229 self.introspection = DatabaseIntrospection(self) 230 self.validation = DatabaseValidation() 231 217 232 def _valid_connection(self): 218 233 return self.connection is not None 219 234 -
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.description19 def get_table_list(self, cursor): 20 "Returns a list of table names in the current database." 21 cursor.execute("SELECT TABLE_NAME FROM USER_TABLES") 22 return [row[0].upper() for row in cursor.fetchall()] 17 23 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 def get_table_description(self, cursor, table_name): 25 "Returns a description of the table, with the DB-API cursor.description interface." 26 cursor.execute("SELECT * FROM %s WHERE ROWNUM < 2" % self.connection.ops.quote_name(table_name)) 27 return cursor.description 24 28 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]) 29 def table_name_converter(self, name): 30 "Table name comparison is case insensitive under Oracle" 31 return name.upper() 32 33 def _name_to_index(self, cursor, table_name): 34 """ 35 Returns a dictionary of {field_name: field_index} for the given table. 36 Indexes are 0-based. 37 """ 38 return dict([(d[0], i) for i, d in enumerate(self.get_table_description(cursor, table_name))]) 43 39 44 relations = {} 45 for row in cursor.fetchall(): 46 relations[row[0]] = (row[2], row[1]) 47 return relations 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 ta.column_id - 1, tb.table_name, tb.column_id - 1 47 FROM user_constraints, USER_CONS_COLUMNS ca, USER_CONS_COLUMNS cb, 48 user_tab_cols ta, user_tab_cols tb 49 WHERE user_constraints.table_name = %s AND 50 ta.table_name = %s AND 51 ta.column_name = ca.column_name AND 52 ca.table_name = %s AND 53 user_constraints.constraint_name = ca.constraint_name AND 54 user_constraints.r_constraint_name = cb.constraint_name AND 55 cb.table_name = tb.table_name AND 56 cb.column_name = tb.column_name AND 57 ca.position = cb.position""", [table_name, table_name, table_name]) 48 58 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 59 relations = {} 60 for row in cursor.fetchall(): 61 relations[row[0]] = (row[2], row[1]) 62 return relations 88 63 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 } 64 def get_indexes(self, 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 # This query retrieves each index on the given table, including the 72 # first associated field name 73 # "We were in the nick of time; you were in great peril!" 74 sql = """ 75 WITH primarycols AS ( 76 SELECT user_cons_columns.table_name, user_cons_columns.column_name, 1 AS PRIMARYCOL 77 FROM user_cons_columns, user_constraints 78 WHERE user_cons_columns.constraint_name = user_constraints.constraint_name AND 79 user_constraints.constraint_type = 'P' AND 80 user_cons_columns.table_name = %s), 81 uniquecols AS ( 82 SELECT user_ind_columns.table_name, user_ind_columns.column_name, 1 AS UNIQUECOL 83 FROM user_indexes, user_ind_columns 84 WHERE uniqueness = 'UNIQUE' AND 85 user_indexes.index_name = user_ind_columns.index_name AND 86 user_ind_columns.table_name = %s) 87 SELECT allcols.column_name, primarycols.primarycol, uniquecols.UNIQUECOL 88 FROM (SELECT column_name FROM primarycols UNION SELECT column_name FROM 89 uniquecols) allcols, 90 primarycols, uniquecols 91 WHERE allcols.column_name = primarycols.column_name (+) AND 92 allcols.column_name = uniquecols.column_name (+) 93 """ 94 cursor.execute(sql, [table_name, table_name]) 95 indexes = {} 96 for row in cursor.fetchall(): 97 # row[1] (idx.indkey) is stored in the DB as an array. It comes out as 98 # a string of space-separated integers. This designates the field 99 # indexes (1-based) of the fields that have indexes on the table. 100 # Here, we skip any indexes across multiple fields. 101 indexes[row[0]] = {'primary_key': row[1], 'unique': row[2]} 102 return indexes 103 -
django/db/backends/oracle/creation.py
1 1 import sys, time 2 from django.conf import settings 2 3 from django.core import management 4 from django.db.backends.creation import BaseDatabaseCreation 3 5 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 6 TEST_DATABASE_PREFIX = 'test_' 39 7 PASSWORD = 'Im_a_lumberjack' 40 REMEMBER = {}41 8 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) 9 class DatabaseCreation(BaseDatabaseCreation): 10 # This dictionary maps Field objects to their associated Oracle column 11 # types, as strings. Column-type strings can contain format strings; they'll 12 # be interpolated against the values of Field.__dict__ before being output. 13 # If a column type is set to None, it won't be included in the output. 14 # 15 # Any format strings starting with "qn_" are quoted before being used in the 16 # output (the "qn_" prefix is stripped before the lookup is performed. 48 17 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 } 18 data_types = { 19 'AutoField': 'NUMBER(11)', 20 'BooleanField': 'NUMBER(1) CHECK (%(qn_column)s IN (0,1))', 21 'CharField': 'NVARCHAR2(%(max_length)s)', 22 'CommaSeparatedIntegerField': 'VARCHAR2(%(max_length)s)', 23 'DateField': 'DATE', 24 'DateTimeField': 'TIMESTAMP', 25 'DecimalField': 'NUMBER(%(max_digits)s, %(decimal_places)s)', 26 'FileField': 'NVARCHAR2(%(max_length)s)', 27 'FilePathField': 'NVARCHAR2(%(max_length)s)', 28 'FloatField': 'DOUBLE PRECISION', 29 'IntegerField': 'NUMBER(11)', 30 'IPAddressField': 'VARCHAR2(15)', 31 'NullBooleanField': 'NUMBER(1) CHECK ((%(qn_column)s IN (0,1)) OR (%(qn_column)s IS NULL))', 32 'OneToOneField': 'NUMBER(11)', 33 'PhoneNumberField': 'VARCHAR2(20)', 34 'PositiveIntegerField': 'NUMBER(11) CHECK (%(qn_column)s >= 0)', 35 'PositiveSmallIntegerField': 'NUMBER(11) CHECK (%(qn_column)s >= 0)', 36 'SlugField': 'NVARCHAR2(50)', 37 'SmallIntegerField': 'NUMBER(11)', 38 'TextField': 'NCLOB', 39 'TimeField': 'TIMESTAMP', 40 'URLField': 'VARCHAR2(%(max_length)s)', 41 'USStateField': 'CHAR(2)', 42 } 43 44 def _create_test_db(self, verbosity, autoclobber): 45 TEST_DATABASE_NAME = self._test_database_name(settings) 46 TEST_DATABASE_USER = self._test_database_user(settings) 47 TEST_DATABASE_PASSWD = self._test_database_passwd(settings) 48 TEST_DATABASE_TBLSPACE = self._test_database_tblspace(settings) 49 TEST_DATABASE_TBLSPACE_TMP = self._test_database_tblspace_tmp(settings) 56 50 57 REMEMBER['user'] = settings.DATABASE_USER 58 REMEMBER['passwd'] = settings.DATABASE_PASSWORD 51 parameters = { 52 'dbname': TEST_DATABASE_NAME, 53 'user': TEST_DATABASE_USER, 54 'password': TEST_DATABASE_PASSWD, 55 'tblspace': TEST_DATABASE_TBLSPACE, 56 'tblspace_temp': TEST_DATABASE_TBLSPACE_TMP, 57 } 59 58 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) 59 self.remember['user'] = settings.DATABASE_USER 60 self.remember['passwd'] = settings.DATABASE_PASSWORD 84 61 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) 62 cursor = self.connection.cursor() 63 if self._test_database_create(settings): 64 if verbosity >= 1: 65 print 'Creating test database...' 66 try: 67 self._execute_test_db_creation(cursor, parameters, verbosity) 68 except Exception, e: 69 sys.stderr.write("Got an error creating the test database: %s\n" % e) 70 if not autoclobber: 71 confirm = raw_input("It appears the test database, %s, already exists. Type 'yes' to delete it, or 'no' to cancel: " % TEST_DATABASE_NAME) 72 if autoclobber or confirm == 'yes': 73 try: 74 if verbosity >= 1: 75 print "Destroying old test database..." 76 self._execute_test_db_destruction(cursor, parameters, verbosity) 77 if verbosity >= 1: 78 print "Creating test database..." 79 self._execute_test_db_creation(cursor, parameters, verbosity) 80 except Exception, e: 81 sys.stderr.write("Got an error recreating the test database: %s\n" % e) 82 sys.exit(2) 83 else: 84 print "Tests cancelled." 85 sys.exit(1) 108 86 109 connection.close() 110 settings.DATABASE_USER = TEST_DATABASE_USER 111 settings.DATABASE_PASSWORD = TEST_DATABASE_PASSWD 87 if self._test_user_create(settings): 88 if verbosity >= 1: 89 print "Creating test user..." 90 try: 91 self._create_test_user(cursor, parameters, verbosity) 92 except Exception, e: 93 sys.stderr.write("Got an error creating the test user: %s\n" % e) 94 if not autoclobber: 95 confirm = raw_input("It appears the test user, %s, already exists. Type 'yes' to delete it, or 'no' to cancel: " % TEST_DATABASE_USER) 96 if autoclobber or confirm == 'yes': 97 try: 98 if verbosity >= 1: 99 print "Destroying old test user..." 100 self._destroy_test_user(cursor, parameters, verbosity) 101 if verbosity >= 1: 102 print "Creating test user..." 103 self._create_test_user(cursor, parameters, verbosity) 104 except Exception, e: 105 sys.stderr.write("Got an error recreating the test user: %s\n" % e) 106 sys.exit(2) 107 else: 108 print "Tests cancelled." 109 sys.exit(1) 112 110 113 management.call_command('syncdb', verbosity=verbosity, interactive=False) 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 return TEST_DATABASE_NAME 115 116 def _destroy_test_db(self, test_database_name, verbosity=1): 117 """ 118 Destroy a test database, prompting the user for confirmation if the 119 database already exists. Returns the name of the test database created. 120 """ 121 TEST_DATABASE_NAME = self._test_database_name(settings) 122 TEST_DATABASE_USER = self._test_database_user(settings) 123 TEST_DATABASE_PASSWD = self._test_database_passwd(settings) 124 TEST_DATABASE_TBLSPACE = self._test_database_tblspace(settings) 125 TEST_DATABASE_TBLSPACE_TMP = self._test_database_tblspace_tmp(settings) 118 126 119 def destroy_test_db(settings, connection, old_database_name, verbosity=1): 120 connection.close()127 settings.DATABASE_USER = self.remember['user'] 128 settings.DATABASE_PASSWORD = self.remember['passwd'] 121 129 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) 130 parameters = { 131 'dbname': TEST_DATABASE_NAME, 132 'user': TEST_DATABASE_USER, 133 'password': TEST_DATABASE_PASSWD, 134 'tblspace': TEST_DATABASE_TBLSPACE, 135 'tblspace_temp': TEST_DATABASE_TBLSPACE_TMP, 136 } 127 137 128 settings.DATABASE_NAME = old_database_name 129 settings.DATABASE_USER = REMEMBER['user'] 130 settings.DATABASE_PASSWORD = REMEMBER['passwd'] 138 self.remember['user'] = settings.DATABASE_USER 139 self.remember['passwd'] = settings.DATABASE_PASSWORD 131 140 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 } 141 cursor = self.connection.cursor() 142 time.sleep(1) # To avoid "database is being accessed by other users" errors. 143 if self._test_user_create(settings): 144 if verbosity >= 1: 145 print 'Destroying test user...' 146 self._destroy_test_user(cursor, parameters, verbosity) 147 if self._test_database_create(settings): 148 if verbosity >= 1: 149 print 'Destroying test database tables...' 150 self._execute_test_db_destruction(cursor, parameters, verbosity) 151 self.connection.close() 139 152 140 REMEMBER['user'] = settings.DATABASE_USER 141 REMEMBER['passwd'] = settings.DATABASE_PASSWORD 153 def _execute_test_db_creation(cursor, parameters, verbosity): 154 if verbosity >= 2: 155 print "_create_test_db(): dbname = %s" % parameters['dbname'] 156 statements = [ 157 """CREATE TABLESPACE %(tblspace)s 158 DATAFILE '%(tblspace)s.dbf' SIZE 20M 159 REUSE AUTOEXTEND ON NEXT 10M MAXSIZE 100M 160 """, 161 """CREATE TEMPORARY TABLESPACE %(tblspace_temp)s 162 TEMPFILE '%(tblspace_temp)s.dbf' SIZE 20M 163 REUSE AUTOEXTEND ON NEXT 10M MAXSIZE 100M 164 """, 165 ] 166 _execute_statements(cursor, statements, parameters, verbosity) 142 167 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() 168 def _create_test_user(cursor, parameters, verbosity): 169 if verbosity >= 2: 170 print "_create_test_user(): username = %s" % parameters['user'] 171 statements = [ 172 """CREATE USER %(user)s 173 IDENTIFIED BY %(password)s 174 DEFAULT TABLESPACE %(tblspace)s 175 TEMPORARY TABLESPACE %(tblspace_temp)s 176 """, 177 """GRANT CONNECT, RESOURCE TO %(user)s""", 178 ] 179 _execute_statements(cursor, statements, parameters, verbosity) 154 180 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) 181 def _execute_test_db_destruction(cursor, parameters, verbosity): 182 if verbosity >= 2: 183 print "_execute_test_db_destruction(): dbname=%s" % parameters['dbname'] 184 statements = [ 185 'DROP TABLESPACE %(tblspace)s INCLUDING CONTENTS AND DATAFILES CASCADE CONSTRAINTS', 186 'DROP TABLESPACE %(tblspace_temp)s INCLUDING CONTENTS AND DATAFILES CASCADE CONSTRAINTS', 187 ] 188 _execute_statements(cursor, statements, parameters, verbosity) 169 189 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) 182 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', 190 def _destroy_test_user(cursor, parameters, verbosity): 191 if verbosity >= 2: 192 print "_destroy_test_user(): user=%s" % parameters['user'] 193 print "Be patient. This can take some time..." 194 statements = [ 195 'DROP USER %(user)s CASCADE', 189 196 ] 190 _execute_statements(cursor, statements, parameters, verbosity)197 _execute_statements(cursor, statements, parameters, verbosity) 191 198 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) 199 def _execute_statements(cursor, statements, parameters, verbosity): 200 for template in statements: 201 stmt = template % parameters 202 if verbosity >= 2: 203 print stmt 204 try: 205 cursor.execute(stmt) 206 except Exception, err: 207 sys.stderr.write("Failed (%s)\n" % (err)) 208 raise 200 209 201 def _execute_statements(cursor, statements, parameters, verbosity): 202 for template in statements: 203 stmt = template % parameters 204 if verbosity >= 2: 205 print stmt 210 def _test_database_name(settings): 211 name = TEST_DATABASE_PREFIX + settings.DATABASE_NAME 206 212 try: 207 cursor.execute(stmt) 208 except Exception, err: 209 sys.stderr.write("Failed (%s)\n" % (err)) 213 if settings.TEST_DATABASE_NAME: 214 name = settings.TEST_DATABASE_NAME 215 except AttributeError: 216 pass 217 except: 210 218 raise 219 return name 211 220 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 221 def _test_database_create(settings): 222 name = True 223 try: 224 if settings.TEST_DATABASE_CREATE: 225 name = True 226 else: 227 name = False 228 except AttributeError: 229 pass 230 except: 231 raise 232 return name 222 233 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 name234 def _test_user_create(settings): 235 name = True 236 try: 237 if settings.TEST_USER_CREATE: 238 name = True 239 else: 240 name = False 241 except AttributeError: 242 pass 243 except: 244 raise 245 return name 235 246 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 247 def _test_database_user(settings): 248 name = TEST_DATABASE_PREFIX + settings.DATABASE_NAME 249 try: 250 if settings.TEST_DATABASE_USER: 251 name = settings.TEST_DATABASE_USER 252 except AttributeError: 253 pass 254 except: 255 raise 256 return name 248 257 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 name258 def _test_database_passwd(settings): 259 name = PASSWORD 260 try: 261 if settings.TEST_DATABASE_PASSWD: 262 name = settings.TEST_DATABASE_PASSWD 263 except AttributeError: 264 pass 265 except: 266 raise 267 return name 259 268 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 name269 def _test_database_tblspace(settings): 270 name = TEST_DATABASE_PREFIX + settings.DATABASE_NAME 271 try: 272 if settings.TEST_DATABASE_TBLSPACE: 273 name = settings.TEST_DATABASE_TBLSPACE 274 except AttributeError: 275 pass 276 except: 277 raise 278 return name 270 279 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 280 def _test_database_tblspace_tmp(settings): 281 name = TEST_DATABASE_PREFIX + settings.DATABASE_NAME + '_temp' 282 try: 283 if settings.TEST_DATABASE_TBLSPACE_TMP: 284 name = settings.TEST_DATABASE_TBLSPACE_TMP 285 except AttributeError: 286 pass 287 except: 288 raise 289 return name -
django/db/backends/__init__.py
42 42 return util.CursorDebugWrapper(cursor, self) 43 43 44 44 class BaseDatabaseFeatures(object): 45 allows_group_by_ordinal = True46 inline_fk_references = True47 45 # True if django.db.backend.utils.typecast_timestamp is used on values 48 46 # returned from dates() calls. 49 47 needs_datetime_string_cast = True 50 supports_constraints = True51 supports_tablespaces = False52 uses_case_insensitive_names = False53 48 uses_custom_query_class = False 54 49 empty_fetchmany_value = [] 55 50 update_can_self_select = True … … 253 248 """ 254 249 return "BEGIN;" 255 250 256 def tablespace_sql(self, tablespace, inline=False):251 def sql_for_tablespace(self, tablespace, inline=False): 257 252 """ 258 Returns the tablespace SQL, or None if the backend doesn't use259 tablespaces.253 Returns the SQL that will be appended to tables or rows to define 254 a tablespace. Returns '' if the backend doesn't use tablespaces. 260 255 """ 261 return None262 256 return '' 257 263 258 def prep_for_like_query(self, x): 264 259 """Prepares a value for use in a LIKE query.""" 265 260 from django.utils.encoding import smart_unicode … … 325 320 """ 326 321 return self.year_lookup_bounds(value) 327 322 323 class BaseDatabaseIntrospection(object): 324 """ 325 This class encapsulates all backend-specific introspection utilities 326 """ 327 data_types_reverse = {} 328 329 def __init__(self, connection): 330 self.connection = connection 331 332 def table_name_converter(self, name): 333 """Apply a conversion to the name for the purposes of comparison. 334 335 The default table name converter is for case sensitive comparison. 336 """ 337 return name 338 339 def table_names(self): 340 "Returns a list of names of all tables that exist in the database." 341 cursor = self.connection.cursor() 342 return self.get_table_list(cursor) 343 344 def django_table_names(self, only_existing=False): 345 """ 346 Returns a list of all table names that have associated Django models and 347 are in INSTALLED_APPS. 348 349 If only_existing is True, the resulting list will only include the tables 350 that actually exist in the database. 351 """ 352 from django.db import models 353 tables = set() 354 for app in models.get_apps(): 355 for model in models.get_models(app): 356 tables.add(model._meta.db_table) 357 tables.update([f.m2m_db_table() for f in model._meta.local_many_to_many]) 358 if only_existing: 359 tables = [t for t in tables if t in self.table_names()] 360 return tables 361 362 def installed_models(self, tables): 363 "Returns a set of all models represented by the provided list of table names." 364 from django.db import models 365 all_models = [] 366 for app in models.get_apps(): 367 for model in models.get_models(app): 368 all_models.append(model) 369 return set([m for m in all_models 370 if self.table_name_converter(m._meta.db_table) in map(self.table_name_converter, tables) 371 ]) 372 373 def sequence_list(self): 374 "Returns a list of information about all DB sequences for all models in all apps." 375 from django.db import models 376 377 apps = models.get_apps() 378 sequence_list = [] 379 380 for app in apps: 381 for model in models.get_models(app): 382 for f in model._meta.local_fields: 383 if isinstance(f, models.AutoField): 384 sequence_list.append({'table': model._meta.db_table, 'column': f.column}) 385 break # Only one AutoField is allowed per model, so don't bother continuing. 386 387 for f in model._meta.local_many_to_many: 388 sequence_list.append({'table': f.m2m_db_table(), 'column': None}) 389 390 return sequence_list 391 392 393 class BaseDatabaseClient(object): 394 """ 395 This class encapsualtes all backend-specific methods for opening a 396 client shell 397 """ 398 def runshell(self): 399 raise NotImplementedError() 400 401 class BaseDatabaseValidation(object): 402 """ 403 This class encapsualtes all backend-specific model validation. 404 """ 405 def validate_field(self, errors, opts, f): 406 "By default, there is no backend-specific validation" 407 pass 408 -
django/db/backends/postgresql_psycopg2/base.py
4 4 Requires psycopg 2: http://initd.org/projects/psycopg2 5 5 """ 6 6 7 from django.db.backends import BaseDatabaseWrapper, BaseDatabaseFeatures 7 from django.db.backends import BaseDatabaseFeatures 8 from django.db.backends import BaseDatabaseValidation 9 from django.db.backends import BaseDatabaseWrapper 8 10 from django.db.backends.postgresql.operations import DatabaseOperations as PostgresqlDatabaseOperations 11 from django.db.backends.postgresql.client import DatabaseClient 12 from django.db.backends.postgresql.creation import DatabaseCreation 13 from django.db.backends.postgresql_psycopg2.introspection import DatabaseIntrospection 14 9 15 from django.utils.safestring import SafeUnicode 10 16 try: 11 17 import psycopg2 as Database … … 30 36 # http://www.initd.org/tracker/psycopg/wiki/psycopg2_documentation#postgresql-status-message-and-executed-query 31 37 return cursor.query 32 38 39 class DatabaseValidation(BaseDatabaseValidation): 40 pass 41 33 42 class DatabaseWrapper(BaseDatabaseWrapper): 34 features = DatabaseFeatures()35 ops = DatabaseOperations()36 43 operators = { 37 44 'exact': '= %s', 38 45 'iexact': 'ILIKE %s', … … 50 57 'iendswith': 'ILIKE %s', 51 58 } 52 59 60 def __init__(self, *args, **kwargs): 61 super(DatabaseWrapper, self).__init__(*args, **kwargs) 62 63 self.features = DatabaseFeatures() 64 self.ops = DatabaseOperations() 65 self.client = DatabaseClient() 66 self.creation = DatabaseCreation(self) 67 self.introspection = DatabaseIntrospection(self) 68 self.validation = DatabaseValidation() 69 53 70 def _cursor(self, settings): 54 71 set_tz = False 55 72 if self.connection is None: -
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
8 8 """ 9 9 10 10 from django.core.exceptions import ImproperlyConfigured 11 from django.db.backends import BaseDatabaseFeatures, BaseDatabaseOperations 11 from django.db.backends import BaseDatabaseClient 12 from django.db.backends import BaseDatabaseFeatures 13 from django.db.backends import BaseDatabaseIntrospection 14 from django.db.backends import BaseDatabaseOperations 15 from django.db.backends import BaseDatabaseValidation 16 from django.db.backends.creation import BaseDatabaseCreation 12 17 13 18 def complain(*args, **kwargs): 14 19 raise ImproperlyConfigured, "You haven't set the DATABASE_ENGINE setting yet." … … 25 30 class DatabaseOperations(BaseDatabaseOperations): 26 31 quote_name = complain 27 32 28 class DatabaseWrapper(object): 29 features = BaseDatabaseFeatures() 30 ops = DatabaseOperations() 33 class DatabaseClient(BaseDatabaseClient): 34 runshell = complain 35 36 class DatabaseCreation(BaseDatabaseCreation): 37 pass 38 39 class DatabaseIntrospection(BaseDatabaseIntrospection): 40 get_table_list = complain 41 get_table_description = complain 42 get_relations = complain 43 get_indexes = complain 44 45 class DatabaseValidation(BaseDatabaseValidation): 46 pass 47 48 class DatabaseWrapper(object): 31 49 operators = {} 32 50 cursor = complain 33 51 _commit = complain 34 52 _rollback = ignore 35 53 36 def __init__(self, * *kwargs):37 pass54 def __init__(self, *args, **kwargs): 55 super(DatabaseWrapper, self).__init__(*args, **kwargs) 38 56 57 self.features = BaseDatabaseFeatures() 58 self.ops = DatabaseOperations() 59 self.client = DatabaseClient() 60 self.creation = DatabaseCreation(self) 61 self.introspection = DatabaseIntrospection(self) 62 self.validation = DatabaseValidation() 63 39 64 def close(self): 40 65 pass -
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): 1 import sys 2 import time 3 4 from django.conf import settings 5 from django.core.management import call_command 6 7 # The prefix to put on the default database name when creating 8 # the test database. 9 TEST_DATABASE_PREFIX = 'test_' 10 11 class BaseDatabaseCreation(object): 2 12 """ 3 13 This class encapsulates all backend-specific differences that pertain to 4 14 database *creation*, such as the column types to use for particular Django 5 15 Fields. 6 16 """ 7 pass 17 data_types = {} 18 19 def __init__(self, connection): 20 self.connection = connection 21 22 def sql_create_model(self, model, style, known_models=set()): 23 """ 24 Returns the SQL required to create a single model, as a tuple of: 25 (list_of_sql, pending_references_dict) 26 """ 27 from django.db import models 28 29 opts = model._meta 30 final_output = [] 31 table_output = [] 32 pending_references = {} 33 qn = self.connection.ops.quote_name 34 for f in opts.local_fields: 35 col_type = f.db_type() 36 tablespace = f.db_tablespace or opts.db_tablespace 37 if col_type is None: 38 # Skip ManyToManyFields, because they're not represented as 39 # database columns in this table. 40 continue 41 # Make the definition (e.g. 'foo VARCHAR(30)') for this field. 42 field_output = [style.SQL_FIELD(qn(f.column)), 43 style.SQL_COLTYPE(col_type)] 44 field_output.append(style.SQL_KEYWORD('%sNULL' % (not f.null and 'NOT ' or ''))) 45 if f.primary_key: 46 field_output.append(style.SQL_KEYWORD('PRIMARY KEY')) 47 elif f.unique: 48 field_output.append(style.SQL_KEYWORD('UNIQUE')) 49 if tablespace and f.unique: 50 # We must specify the index tablespace inline, because we 51 # won't be generating a CREATE INDEX statement for this field. 52 field_output.append(self.connection.ops.tablespace_sql(tablespace, inline=True)) 53 if f.rel: 54 ref_output, pending = self.sql_for_inline_foreign_key_references(f, known_models, style) 55 if pending: 56 pr = pending_references.setdefault(f.rel.to, []).append((model, f)) 57 else: 58 field_output.extend(ref_output) 59 table_output.append(' '.join(field_output)) 60 if opts.order_with_respect_to: 61 table_output.append(style.SQL_FIELD(qn('_order')) + ' ' + \ 62 style.SQL_COLTYPE(models.IntegerField().db_type()) + ' ' + \ 63 style.SQL_KEYWORD('NULL')) 64 for field_constraints in opts.unique_together: 65 table_output.append(style.SQL_KEYWORD('UNIQUE') + ' (%s)' % \ 66 ", ".join([style.SQL_FIELD(qn(opts.get_field(f).column)) for f in field_constraints])) 67 68 full_statement = [style.SQL_KEYWORD('CREATE TABLE') + ' ' + style.SQL_TABLE(qn(opts.db_table)) + ' ('] 69 for i, line in enumerate(table_output): # Combine and add commas. 70 full_statement.append(' %s%s' % (line, i < len(table_output)-1 and ',' or '')) 71 full_statement.append(')') 72 if opts.db_tablespace: 73 full_statement.append(self.connection.ops.tablespace_sql(opts.db_tablespace)) 74 full_statement.append(';') 75 final_output.append('\n'.join(full_statement)) 76 77 if opts.has_auto_field: 78 # Add any extra SQL needed to support auto-incrementing primary keys. 79 auto_column = opts.auto_field.db_column or opts.auto_field.name 80 autoinc_sql = self.connection.ops.autoinc_sql(opts.db_table, auto_column) 81 if autoinc_sql: 82 for stmt in autoinc_sql: 83 final_output.append(stmt) 84 85 return final_output, pending_references 86 87 def sql_for_inline_foreign_key_references(self, field, known_models, style): 88 "Return the SQL snippet defining the foreign key reference for a field" 89 qn = self.connection.ops.quote_name 90 if field.rel.to in known_models: 91 output = [style.SQL_KEYWORD('REFERENCES') + ' ' + \ 92 style.SQL_TABLE(qn(field.rel.to._meta.db_table)) + ' (' + \ 93 style.SQL_FIELD(qn(field.rel.to._meta.get_field(field.rel.field_name).column)) + ')' + 94 self.connection.ops.deferrable_sql() 95 ] 96 pending = False 97 else: 98 # We haven't yet created the table to which this field 99 # is related, so save it for later. 100 output = [] 101 pending = True 102 103 return output, pending 104 105 def sql_for_pending_references(self, model, style, pending_references): 106 "Returns any ALTER TABLE statements to add constraints after the fact." 107 from django.db.backends.util import truncate_name 108 109 qn = self.connection.ops.quote_name 110 final_output = [] 111 opts = model._meta 112 if model in pending_references: 113 for rel_class, f in pending_references[model]: 114 rel_opts = rel_class._meta 115 r_table = rel_opts.db_table 116 r_col = f.column 117 table = opts.db_table 118 col = opts.get_field(f.rel.field_name).column 119 # For MySQL, r_name must be unique in the first 64 characters. 120 # So we are careful with character usage here. 121 r_name = '%s_refs_%s_%x' % (r_col, col, abs(hash((r_table, table)))) 122 final_output.append(style.SQL_KEYWORD('ALTER TABLE') + ' %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s)%s;' % \ 123 (qn(r_table), truncate_name(r_name, self.connection.ops.max_name_length()), 124 qn(r_col), qn(table), qn(col), 125 self.connection.ops.deferrable_sql())) 126 del pending_references[model] 127 return final_output 128 129 def many_to_many_sql_for_model(self, model, style): 130 "Return the CREATE TABLE statments for all the many-to-many tables defined on a model" 131 output = [] 132 for f in model._meta.local_many_to_many: 133 output.extend(self.sql_for_many_to_many_field(model, f, style)) 134 return output 135 136 def sql_for_many_to_many_field(self, model, f, style): 137 "Return the CREATE TABLE statements for a single m2m field" 138 from django.db import models 139 from django.db.backends.util import truncate_name 140 141 output = [] 142 if f.creates_table: 143 opts = model._meta 144 qn = self.connection.ops.quote_name 145 tablespace = f.db_tablespace or opts.db_tablespace 146 if tablespace: 147 sql = self.connection.ops.tablespace_sql(tablespace, inline=True) 148 if sql: 149 tablespace_sql = ' ' + sql 150 else: 151 tablespace_sql = '' 152 else: 153 tablespace_sql = '' 154 table_output = [style.SQL_KEYWORD('CREATE TABLE') + ' ' + \ 155 style.SQL_TABLE(qn(f.m2m_db_table())) + ' ('] 156 table_output.append(' %s %s %s%s,' % 157 (style.SQL_FIELD(qn('id')), 158 style.SQL_COLTYPE(models.AutoField(primary_key=True).db_type()), 159 style.SQL_KEYWORD('NOT NULL PRIMARY KEY'), 160 tablespace_sql)) 161 162 deferred = [] 163 inline_output, deferred = self.sql_for_inline_many_to_many_references(model, f, style) 164 table_output.extend(inline_output) 165 166 table_output.append(' %s (%s, %s)%s' % 167 (style.SQL_KEYWORD('UNIQUE'), 168 style.SQL_FIELD(qn(f.m2m_column_name())), 169 style.SQL_FIELD(qn(f.m2m_reverse_name())), 170 tablespace_sql)) 171 table_output.append(')') 172 if opts.db_tablespace: 173 # f.db_tablespace is only for indices, so ignore its value here. 174 table_output.append(self.connection.ops.tablespace_sql(opts.db_tablespace)) 175 table_output.append(';') 176 output.append('\n'.join(table_output)) 177 178 for r_table, r_col, table, col in deferred: 179 r_name = '%s_refs_%s_%x' % (r_col, col, 180 abs(hash((r_table, table)))) 181 output.append(style.SQL_KEYWORD('ALTER TABLE') + ' %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s)%s;' % 182 (qn(r_table), 183 truncate_name(r_name, self.connection.ops.max_name_length()), 184 qn(r_col), qn(table), qn(col), 185 self.connection.ops.deferrable_sql())) 186 187 # Add any extra SQL needed to support auto-incrementing PKs 188 autoinc_sql = self.connection.ops.autoinc_sql(f.m2m_db_table(), 'id') 189 if autoinc_sql: 190 for stmt in autoinc_sql: 191 output.append(stmt) 192 return output 193 194 def sql_for_inline_many_to_many_references(self, model, field, style): 195 "Create the references to other tables required by a many-to-many table" 196 from django.db import models 197 opts = model._meta 198 qn = self.connection.ops.quote_name 199 200 table_output = [ 201 ' %s %s %s %s (%s)%s,' % 202 (style.SQL_FIELD(qn(field.m2m_column_name())), 203 style.SQL_COLTYPE(models.ForeignKey(model).db_type()), 204 style.SQL_KEYWORD('NOT NULL REFERENCES'), 205 style.SQL_TABLE(qn(opts.db_table)), 206 style.SQL_FIELD(qn(opts.pk.column)), 207 self.connection.ops.deferrable_sql()), 208 ' %s %s %s %s (%s)%s,' % 209 (style.SQL_FIELD(qn(field.m2m_reverse_name())), 210 style.SQL_COLTYPE(models.ForeignKey(field.rel.to).db_type()), 211 style.SQL_KEYWORD('NOT NULL REFERENCES'), 212 style.SQL_TABLE(qn(field.rel.to._meta.db_table)), 213 style.SQL_FIELD(qn(field.rel.to._meta.pk.column)), 214 self.connection.ops.deferrable_sql()) 215 ] 216 deferred = [] 217 218 return table_output, deferred 219 220 def sql_indexes_for_model(self, model, style): 221 "Returns the CREATE INDEX SQL statements for a single model" 222 output = [] 223 for f in model._meta.local_fields: 224 output.extend(self.sql_indexes_for_field(model, f, style)) 225 return output 226 227 def sql_indexes_for_field(self, model, f, style): 228 "Return the CREATE INDEX SQL statements for a single model field" 229 if f.db_index and not f.unique: 230 qn = self.connection.ops.quote_name 231 tablespace = f.db_tablespace or model._meta.db_tablespace 232 if tablespace: 233 sql = self.connection.ops.tablespace_sql(tablespace) 234 if sql: 235 tablespace_sql = ' ' + sql 236 else: 237 tablespace_sql = '' 238 else: 239 tablespace_sql = '' 240 output = [style.SQL_KEYWORD('CREATE INDEX') + ' ' + 241 style.SQL_TABLE(qn('%s_%s' % (model._meta.db_table, f.column))) + ' ' + 242 style.SQL_KEYWORD('ON') + ' ' + 243 style.SQL_TABLE(qn(model._meta.db_table)) + ' ' + 244 "(%s)" % style.SQL_FIELD(qn(f.column)) + 245 "%s;" % tablespace_sql] 246 else: 247 output = [] 248 return output 249 250 def sql_destroy_model(self, model, references_to_delete, style): 251 "Return the DROP TABLE and restraint dropping statements for a single model" 252 # Drop the table now 253 qn = self.connection.ops.quote_name 254 output = ['%s %s;' % (style.SQL_KEYWORD('DROP TABLE'), 255 style.SQL_TABLE(qn(model._meta.db_table)))] 256 if model in references_to_delete: 257 output.extend(self.sql_remove_table_constraints(model, references_to_delete)) 258 259 if model._meta.has_auto_field: 260 ds = self.connection.ops.drop_sequence_sql(model._meta.db_table) 261 if ds: 262 output.append(ds) 263 return output 264 265 def sql_remove_table_constraints(self, model, references_to_delete): 266 output = [] 267 for rel_class, f in references_to_delete[model]: 268 table = rel_class._meta.db_table 269 col = f.column 270 r_table = model._meta.db_table 271 r_col = model._meta.get_field(f.rel.field_name).column 272 r_name = '%s_refs_%s_%x' % (col, r_col, abs(hash((table, r_table)))) 273 output.append('%s %s %s %s;' % \ 274 (style.SQL_KEYWORD('ALTER TABLE'), 275 style.SQL_TABLE(qn(table)), 276 style.SQL_KEYWORD(self.connection.ops.drop_foreignkey_sql()), 277 style.SQL_FIELD(truncate_name(r_name, self.connection.ops.max_name_length())))) 278 del references_to_delete[model] 279 return output 280 281 def sql_destroy_many_to_many(self, model, f, style): 282 "Returns the DROP TABLE statements for a single m2m field" 283 qn = self.connection.ops.quote_name 284 output = [] 285 if f.creates_table: 286 output.append("%s %s;" % (style.SQL_KEYWORD('DROP TABLE'), 287 style.SQL_TABLE(qn(f.m2m_db_table())))) 288 ds = self.connection.ops.drop_sequence_sql("%s_%s" % (model._meta.db_table, f.column)) 289 if ds: 290 output.append(ds) 291 return output 292 293 def create_test_db(self, verbosity=1, autoclobber=False): 294 """ 295 Creates a test database, prompting the user for confirmation if the 296 database already exists. Returns the name of the test database created. 297 """ 298 if verbosity >= 1: 299 print "Creating test database..." 300 301 test_database_name = self._create_test_db(verbosity, autoclobber) 302 303 self.connection.close() 304 settings.DATABASE_NAME = test_database_name 305 306 call_command('syncdb', verbosity=verbosity, interactive=False) 307 308 if settings.CACHE_BACKEND.startswith('db://'): 309 cache_name = settings.CACHE_BACKEND[len('db://'):] 310 call_command('createcachetable', cache_name) 311 312 # Get a cursor (even though we don't need one yet). This has 313 # the side effect of initializing the test database. 314 cursor = self.connection.cursor() 315 316 return test_database_name 317 318 def _create_test_db(self, verbosity, autoclobber): 319 "Internal implementation - creates the test db tables." 320 suffix = self._creation_suffix() 321 322 if settings.TEST_DATABASE_NAME: 323 test_database_name = settings.TEST_DATABASE_NAME 324 else: 325 test_database_name = TEST_DATABASE_PREFIX + settings.DATABASE_NAME 326 327 qn = self.connection.ops.quote_name 328 329 # Create the test database and connect to it. We need to autocommit 330 # if the database supports it because PostgreSQL doesn't allow 331 # CREATE/DROP DATABASE statements within transactions. 332 cursor = self.connection.cursor() 333 self._set_autocommit() 334 try: 335 cursor.execute("CREATE DATABASE %s %s" % (qn(test_database_name), suffix)) 336 except Exception, e: 337 sys.stderr.write("Got an error creating the test database: %s\n" % e) 338 if not autoclobber: 339 confirm = raw_input("Type 'yes' if you would like to try deleting the test database '%s', or 'no' to cancel: " % test_database_name) 340 if autoclobber or confirm == 'yes': 341 try: 342 if verbosity >= 1: 343 print "Destroying old test database..." 344 cursor.execute("DROP DATABASE %s" % qn(test_database_name)) 345 if verbosity >= 1: 346 print "Creating test database..." 347 cursor.execute("CREATE DATABASE %s %s" % (qn(test_database_name), suffix)) 348 except Exception, e: 349 sys.stderr.write("Got an error recreating the test database: %s\n" % e) 350 sys.exit(2) 351 else: 352 print "Tests cancelled." 353 sys.exit(1) 354 355 return test_database_name 356 357 def destroy_test_db(self, old_database_name, verbosity=1): 358 """ 359 Destroy a test database, prompting the user for confirmation if the 360 database already exists. Returns the name of the test database created. 361 """ 362 if verbosity >= 1: 363 print "Destroying test database..." 364 self.connection.close() 365 test_database_name = settings.DATABASE_NAME 366 settings.DATABASE_NAME = old_database_name 367 368 self._destroy_test_db(test_database_name, verbosity) 369 370 def _destroy_test_db(self, test_database_name, verbosity): 371 "Internal implementation - remove the test db tables." 372 # Remove the test database to clean up after 373 # ourselves. Connect to the previous database (not the test database) 374 # to do so, because it's not allowed to delete a database while being 375 # connected to it. 376 cursor = self.connection.cursor() 377 self._set_autocommit() 378 time.sleep(1) # To avoid "database is being accessed by other users" errors. 379 cursor.execute("DROP DATABASE %s" % self.connection.ops.quote_name(test_database_name)) 380 self.connection.close() 381 382 def _set_autocommit(self): 383 "Make sure a connection is in autocommit mode." 384 if hasattr(self.connection.connection, "autocommit"): 385 if callable(self.connection.connection.autocommit): 386 self.connection.connection.autocommit(True) 387 else: 388 self.connection.connection.autocommit = True 389 elif hasattr(self.connection.connection, "set_isolation_level"): 390 self.connection.connection.set_isolation_level(0) 391 392 def _creation_suffix(self): 393 "SQL to append to the end of the test table creation statements" 394 return '' 395 -
django/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_names, 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 custom_sql_for_model, emit_post_sync_signal 25 25 26 26 verbosity = int(options.get('verbosity', 1)) 27 27 interactive = options.get('interactive') … … 50 50 51 51 cursor = connection.cursor() 52 52 53 if connection.features.uses_case_insensitive_names:54 table_name_converter = lambda x: x.upper()55 else:56 table_name_converter = lambda x: x57 # Get a list of all existing database tables, so we know what needs to58 # be added.59 tables = [table_name_converter(name) for name in table_names()]60 61 53 # Get a list of already installed *models* so that references work right. 62 seen_models = installed_models(tables) 54 tables = connection.introspection.table_names() 55 seen_models = connection.introspection.installed_models(tables) 63 56 created_models = set() 64 57 pending_references = {} 65 58 … … 71 64 # Create the model's database table, if it doesn't already exist. 72 65 if verbosity >= 2: 73 66 print "Processing %s.%s model" % (app_name, model._meta.object_name) 74 if table_name_converter(model._meta.db_table) in tables:67 if connection.introspection.table_name_converter(model._meta.db_table) in tables: 75 68 continue 76 sql, references = sql_model_create(model, self.style, seen_models)69 sql, references = connection.creation.sql_create_model(model, self.style, seen_models) 77 70 seen_models.add(model) 78 71 created_models.add(model) 79 72 for refto, refs in references.items(): 80 73 pending_references.setdefault(refto, []).extend(refs) 81 74 if refto in seen_models: 82 sql.extend( sql_for_pending_references(refto, self.style, pending_references))83 sql.extend( sql_for_pending_references(model, self.style, pending_references))75 sql.extend(connection.creation.sql_for_pending_references(refto, self.style, pending_references)) 76 sql.extend(connection.creation.sql_for_pending_references(model, self.style, pending_references)) 84 77 if verbosity >= 1: 85 78 print "Creating table %s" % model._meta.db_table 86 79 for statement in sql: 87 80 cursor.execute(statement) 88 tables.append( table_name_converter(model._meta.db_table))81 tables.append(connection.introspection.table_name_converter(model._meta.db_table)) 89 82 90 83 # Create the m2m tables. This must be done after all tables have been created 91 84 # to ensure that all referred tables will exist. … … 94 87 model_list = models.get_models(app) 95 88 for model in model_list: 96 89 if model in created_models: 97 sql = many_to_many_sql_for_model(model, self.style)90 sql = connection.creation.many_to_many_sql_for_model(model, self.style) 98 91 if sql: 99 92 if verbosity >= 2: 100 93 print "Creating many-to-many tables for %s.%s model" % (app_name, model._meta.object_name) … … 140 133 app_name = app.__name__.split('.')[-2] 141 134 for model in models.get_models(app): 142 135 if model in created_models: 143 index_sql = sql_indexes_for_model(model, self.style)136 index_sql = connection.creation.sql_indexes_for_model(model, self.style) 144 137 if index_sql: 145 138 if verbosity >= 1: 146 139 print "Installing index for %s.%s model" % (app_name, model._meta.object_name) -
django/core/management/commands/testserver.py
18 18 19 19 def handle(self, *fixture_labels, **options): 20 20 from django.core.management import call_command 21 from django. test.utils import create_test_db21 from django.db import connection 22 22 23 23 verbosity = int(options.get('verbosity', 1)) 24 24 addrport = options.get('addrport') 25 25 26 26 # Create a test database. 27 db_name = c reate_test_db(verbosity=verbosity)27 db_name = connection.creation.create_test_db(verbosity=verbosity) 28 28 29 29 # Import the fixture data into the test database. 30 30 call_command('loaddata', *fixture_labels, **{'verbosity': verbosity}) -
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/validation.py
61 61 if f.db_index not in (None, True, False): 62 62 e.add(opts, '"%s": "db_index" should be either None, True or False.' % f.name) 63 63 64 # Check that max_length <= 255 if using older MySQL versions. 65 if settings.DATABASE_ENGINE == 'mysql': 66 db_version = connection.get_server_version() 67 if db_version < (5, 0, 3) and isinstance(f, (models.CharField, models.CommaSeparatedIntegerField, models.SlugField)) and f.max_length > 255: 68 e.add(opts, '"%s": %s cannot have a "max_length" greater than 255 when you are using a version of MySQL prior to 5.0.3 (you are using %s).' % (f.name, f.__class__.__name__, '.'.join([str(n) for n in db_version[:3]]))) 64 # Perform any backend-specific field validation. 65 connection.validation.validate_field(e, opts, f) 69 66 70 67 # Check to see if the related field will clash with any existing 71 68 # fields, m2m fields, m2m related objects or related objects -
django/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_names():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 set(get_introspection_module().get_table_list(cursor))15 16 def django_table_names(only_existing=False):17 """18 Returns a list of all table names that have associated Django models and19 are in INSTALLED_APPS.20 21 If only_existing is True, the resulting list will only include the tables22 that actually exist in the database.23 """24 from django.db import models25 tables = set()26 for app in models.get_apps():27 for model in models.get_models(app):28 tables.add(model._meta.db_table)29 tables.update([f.m2m_db_table() for f in model._meta.local_many_to_many])30 if only_existing:31 tables = [t for t in tables if t in table_names()]32 return tables33 34 def installed_models(table_list):35 "Returns a set of all models that are installed, given a list of existing table names."36 from django.db import connection, models37 all_models = []38 for app in models.get_apps():39 for model in models.get_models(app):40 all_models.append(model)41 if connection.features.uses_case_insensitive_names:42 converter = lambda x: x.upper()43 else:44 converter = lambda x: x45 return set([m for m in all_models if converter(m._meta.db_table) in map(converter, table_list)])46 47 def sequence_list():48 "Returns a list of information about all DB sequences for all models in all apps."49 from django.db import models50 51 apps = models.get_apps()52 sequence_list = []53 54 for app in apps:55 for model in models.get_models(app):56 for f in model._meta.local_fields:57 if isinstance(f, models.AutoField):58 sequence_list.append({'table': model._meta.db_table, 'column': f.column})59 break # Only one AutoField is allowed per model, so don't bother continuing.60 61 for f in model._meta.local_many_to_many:62 sequence_list.append({'table': f.m2m_db_table(), 'column': None})63 64 return sequence_list65 66 10 def sql_create(app, style): 67 11 "Returns a list of the CREATE TABLE SQL statements for the given app." 68 from django.db import models12 from django.db import connection, models 69 13 from django.conf import settings 70 14 71 15 if settings.DATABASE_ENGINE == 'dummy': … … 81 25 # we can be conservative). 82 26 app_models = models.get_models(app) 83 27 final_output = [] 84 known_models = set([model for model in installed_models(table_names()) if model not in app_models]) 28 tables = connection.introspection.table_names() 29 known_models = set([model for model in connection.introspection.installed_models(tables) if model not in app_models]) 85 30 pending_references = {} 86 31 87 32 for model in app_models: 88 output, references = sql_model_create(model, style, known_models)33 output, references = connection.creation.sql_create_model(model, style, known_models) 89 34 final_output.extend(output) 90 35 for refto, refs in references.items(): 91 36 pending_references.setdefault(refto, []).extend(refs) 92 37 if refto in known_models: 93 final_output.extend( sql_for_pending_references(refto, style, pending_references))94 final_output.extend( sql_for_pending_references(model, style, pending_references))38 final_output.extend(connection.creation.sql_for_pending_references(refto, style, pending_references)) 39 final_output.extend(connection.creation.sql_for_pending_references(model, style, pending_references)) 95 40 # Keep track of the fact that we've created the table for this model. 96 41 known_models.add(model) 97 42 98 43 # Create the many-to-many join tables. 99 44 for model in app_models: 100 final_output.extend( many_to_many_sql_for_model(model, style))45 final_output.extend(connection.creation.many_to_many_sql_for_model(model, style)) 101 46 102 47 # Handle references to tables that are from other apps 103 48 # but don't exist physically. … … 106 51 alter_sql = [] 107 52 for model in not_installed_models: 108 53 alter_sql.extend(['-- ' + sql for sql in 109 sql_for_pending_references(model, style, pending_references)])54 connection.creation.sql_for_pending_references(model, style, pending_references)]) 110 55 if alter_sql: 111 56 final_output.append('-- The following references should be added but depend on non-existent tables:') 112 57 final_output.extend(alter_sql) … … 115 60 116 61 def sql_delete(app, style): 117 62 "Returns a list of the DROP TABLE SQL statements for the given app." 118 from django.db import connection, models , get_introspection_module63 from django.db import connection, models 119 64 from django.db.backends.util import truncate_name 120 65 from django.contrib.contenttypes import generic 121 introspection = get_introspection_module()122 66 123 67 # This should work even if a connection isn't available 124 68 try: … … 128 72 129 73 # Figure out which tables already exist 130 74 if cursor: 131 table_names = introspection.get_table_list(cursor)75 table_names = connection.introspection.get_table_list(cursor) 132 76 else: 133 77 table_names = [] 134 if connection.features.uses_case_insensitive_names:135 table_name_converter = lambda x: x.upper()136 else:137 table_name_converter = lambda x: x138 78 139 79 output = [] 140 qn = connection.ops.quote_name141 80 142 81 # Output DROP TABLE statements for standard application tables. 143 82 to_delete = set() … … 145 84 references_to_delete = {} 146 85 app_models = models.get_models(app) 147 86 for model in app_models: 148 if cursor and table_name_converter(model._meta.db_table) in table_names:87 if cursor and connection.introspection.table_name_converter(model._meta.db_table) in table_names: 149 88 # The table exists, so it needs to be dropped 150 89 opts = model._meta 151 90 for f in opts.local_fields: … … 155 94 to_delete.add(model) 156 95 157 96 for model in app_models: 158 if cursor and table_name_converter(model._meta.db_table) in table_names: 159 # Drop the table now 160 output.append('%s %s;' % (style.SQL_KEYWORD('DROP TABLE'), 161 style.SQL_TABLE(qn(model._meta.db_table)))) 162 if connection.features.supports_constraints and model in references_to_delete: 163 for rel_class, f in references_to_delete[model]: 164 table = rel_class._meta.db_table 165 col = f.column 166 r_table = model._meta.db_table 167 r_col = model._meta.get_field(f.rel.field_name).column 168 r_name = '%s_refs_%s_%x' % (col, r_col, abs(hash((table, r_table)))) 169 output.append('%s %s %s %s;' % \ 170 (style.SQL_KEYWORD('ALTER TABLE'), 171 style.SQL_TABLE(qn(table)), 172 style.SQL_KEYWORD(connection.ops.drop_foreignkey_sql()), 173 style.SQL_FIELD(truncate_name(r_name, connection.ops.max_name_length())))) 174 del references_to_delete[model] 175 if model._meta.has_auto_field: 176 ds = connection.ops.drop_sequence_sql(model._meta.db_table) 177 if ds: 178 output.append(ds) 97 if connection.introspection.table_name_converter(model._meta.db_table) in table_names: 98 output.extend(connection.creation.sql_destroy_model(model, references_to_delete, style)) 179 99 180 100 # Output DROP TABLE statements for many-to-many tables. 181 101 for model in app_models: 182 102 opts = model._meta 183 103 for f in opts.local_many_to_many: 184 if not f.creates_table: 185 continue 186 if cursor and table_name_converter(f.m2m_db_table()) in table_names: 187 output.append("%s %s;" % (style.SQL_KEYWORD('DROP TABLE'), 188 style.SQL_TABLE(qn(f.m2m_db_table())))) 189 ds = connection.ops.drop_sequence_sql("%s_%s" % (model._meta.db_table, f.column)) 190 if ds: 191 output.append(ds) 104 if cursor and connection.introspection.table_name_converter(f.m2m_db_table()) in table_names: 105 output.extend(connection.creation.sql_destroy_many_to_many(model, f, style)) 192 106 193 107 app_label = app_models[0]._meta.app_label 194 108 … … 213 127 """ 214 128 from django.db import connection 215 129 if only_django: 216 tables = django_table_names()130 tables = connection.introspection.django_table_names() 217 131 else: 218 tables = table_names()219 statements = connection.ops.sql_flush(style, tables, sequence_list())132 tables = connection.introspection.table_names() 133 statements = connection.ops.sql_flush(style, tables, connection.introspection.sequence_list()) 220 134 return statements 221 135 222 136 def sql_custom(app, style): … … 234 148 235 149 def sql_indexes(app, style): 236 150 "Returns a list of the CREATE INDEX SQL statements for all models in the given app." 237 from django.db import models151 from django.db import connection, models 238 152 output = [] 239 153 for model in models.get_models(app): 240 output.extend( sql_indexes_for_model(model, style))154 output.extend(connection.creation.sql_indexes_for_model(model, style)) 241 155 return output 242 156 243 157 def sql_all(app, style): 244 158 "Returns a list of CREATE TABLE SQL, initial-data inserts, and CREATE INDEX SQL for the given module." 245 159 return sql_create(app, style) + sql_custom(app, style) + sql_indexes(app, style) 246 160 247 def sql_model_create(model, style, known_models=set()):248 """249 Returns the SQL required to create a single model, as a tuple of:250 (list_of_sql, pending_references_dict)251 """252 from django.db import connection, models253 254 opts = model._meta255 final_output = []256 table_output = []257 pending_references = {}258 qn = connection.ops.quote_name259 inline_references = connection.features.inline_fk_references260 for f in opts.local_fields:261 col_type = f.db_type()262 tablespace = f.db_tablespace or opts.db_tablespace263 if col_type is None:264 # Skip ManyToManyFields, because they're not represented as265 # database columns in this table.266 continue267 # Make the definition (e.g. 'foo VARCHAR(30)') for this field.268 field_output = [style.SQL_FIELD(qn(f.column)),269 style.SQL_COLTYPE(col_type)]270 field_output.append(style.SQL_KEYWORD('%sNULL' % (not f.null and 'NOT ' or '')))271 if f.primary_key:272 field_output.append(style.SQL_KEYWORD('PRIMARY KEY'))273 elif f.unique:274 field_output.append(style.SQL_KEYWORD('UNIQUE'))275 if tablespace and connection.features.supports_tablespaces and f.unique:276 # We must specify the index tablespace inline, because we277 # won't be generating a CREATE INDEX statement for this field.278 field_output.append(connection.ops.tablespace_sql(tablespace, inline=True))279 if f.rel:280 if inline_references and f.rel.to in known_models:281 field_output.append(style.SQL_KEYWORD('REFERENCES') + ' ' + \282 style.SQL_TABLE(qn(f.rel.to._meta.db_table)) + ' (' + \283 style.SQL_FIELD(qn(f.rel.to._meta.get_field(f.rel.field_name).column)) + ')' +284 connection.ops.deferrable_sql()285 )286 else:287 # We haven't yet created the table to which this field288 # is related, so save it for later.289 pr = pending_references.setdefault(f.rel.to, []).append((model, f))290 table_output.append(' '.join(field_output))291 if opts.order_with_respect_to:292 table_output.append(style.SQL_FIELD(qn('_order')) + ' ' + \293 style.SQL_COLTYPE(models.IntegerField().db_type()) + ' ' + \294 style.SQL_KEYWORD('NULL'))295 for field_constraints in opts.unique_together:296 table_output.append(style.SQL_KEYWORD('UNIQUE') + ' (%s)' % \297 ", ".join([style.SQL_FIELD(qn(opts.get_field(f).column)) for f in field_constraints]))298 299 full_statement = [style.SQL_KEYWORD('CREATE TABLE') + ' ' + style.SQL_TABLE(qn(opts.db_table)) + ' (']300 for i, line in enumerate(table_output): # Combine and add commas.301 full_statement.append(' %s%s' % (line, i < len(table_output)-1 and ',' or ''))302 full_statement.append(')')303 if opts.db_tablespace and connection.features.supports_tablespaces:304 full_statement.append(connection.ops.tablespace_sql(opts.db_tablespace))305 full_statement.append(';')306 final_output.append('\n'.join(full_statement))307 308 if opts.has_auto_field:309 # Add any extra SQL needed to support auto-incrementing primary keys.310 auto_column = opts.auto_field.db_column or opts.auto_field.name311 autoinc_sql = connection.ops.autoinc_sql(opts.db_table, auto_column)312 if autoinc_sql:313 for stmt in autoinc_sql:314 final_output.append(stmt)315 316 return final_output, pending_references317 318 def sql_for_pending_references(model, style, pending_references):319 """320 Returns any ALTER TABLE statements to add constraints after the fact.321 """322 from django.db import connection323 from django.db.backends.util import truncate_name324 325 qn = connection.ops.quote_name326 final_output = []327 if connection.features.supports_constraints:328 opts = model._meta329 if model in pending_references:330 for rel_class, f in pending_references[model]:331 rel_opts = rel_class._meta332 r_table = rel_opts.db_table333 r_col = f.column334 table = opts.db_table335 col = opts.get_field(f.rel.field_name).column336 # For MySQL, r_name must be unique in the first 64 characters.337 # So we are careful with character usage here.338 r_name = '%s_refs_%s_%x' % (r_col, col, abs(hash((r_table, table))))339 final_output.append(style.SQL_KEYWORD('ALTER TABLE') + ' %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s)%s;' % \340 (qn(r_table), truncate_name(r_name, connection.ops.max_name_length()),341 qn(r_col), qn(table), qn(col),342 connection.ops.deferrable_sql()))343 del pending_references[model]344 return final_output345 346 def many_to_many_sql_for_model(model, style):347 from django.db import connection, models348 from django.contrib.contenttypes import generic349 from django.db.backends.util import truncate_name350 351 opts = model._meta352 final_output = []353 qn = connection.ops.quote_name354 inline_references = connection.features.inline_fk_references355 for f in opts.local_many_to_many:356 if f.creates_table:357 tablespace = f.db_tablespace or opts.db_tablespace358 if tablespace and connection.features.supports_tablespaces:359 tablespace_sql = ' ' + connection.ops.tablespace_sql(tablespace, inline=True)360 else:361 tablespace_sql = ''362 table_output = [style.SQL_KEYWORD('CREATE TABLE') + ' ' + \363 style.SQL_TABLE(qn(f.m2m_db_table())) + ' (']364 table_output.append(' %s %s %s%s,' %365 (style.SQL_FIELD(qn('id')),366 style.SQL_COLTYPE(models.AutoField(primary_key=True).db_type()),367 style.SQL_KEYWORD('NOT NULL PRIMARY KEY'),368 tablespace_sql))369 if inline_references:370 deferred = []371 table_output.append(' %s %s %s %s (%s)%s,' %372 (style.SQL_FIELD(qn(f.m2m_column_name())),373 style.SQL_COLTYPE(models.ForeignKey(model).db_type()),374 style.SQL_KEYWORD('NOT NULL REFERENCES'),375 style.SQL_TABLE(qn(opts.db_table)),376 style.SQL_FIELD(qn(opts.pk.column)),377 connection.ops.deferrable_sql()))378 table_output.append(' %s %s %s %s (%s)%s,' %379 (style.SQL_FIELD(qn(f.m2m_reverse_name())),380 style.SQL_COLTYPE(models.ForeignKey(f.rel.to).db_type()),381 style.SQL_KEYWORD('NOT NULL REFERENCES'),382 style.SQL_TABLE(qn(f.rel.to._meta.db_table)),383 style.SQL_FIELD(qn(f.rel.to._meta.pk.column)),384 connection.ops.deferrable_sql()))385 else:386 table_output.append(' %s %s %s,' %387 (style.SQL_FIELD(qn(f.m2m_column_name())),388 style.SQL_COLTYPE(models.ForeignKey(model).db_type()),389 style.SQL_KEYWORD('NOT NULL')))390 table_output.append(' %s %s %s,' %391 (style.SQL_FIELD(qn(f.m2m_reverse_name())),392 style.SQL_COLTYPE(models.ForeignKey(f.rel.to).db_type()),393 style.SQL_KEYWORD('NOT NULL')))394 deferred = [395 (f.m2m_db_table(), f.m2m_column_name(), opts.db_table,396 opts.pk.column),397 ( f.m2m_db_table(), f.m2m_reverse_name(),398 f.rel.to._meta.db_table, f.rel.to._meta.pk.column)399 ]400 table_output.append(' %s (%s, %s)%s' %401 (style.SQL_KEYWORD('UNIQUE'),402 style.SQL_FIELD(qn(f.m2m_column_name())),403 style.SQL_FIELD(qn(f.m2m_reverse_name())),404 tablespace_sql))405 table_output.append(')')406 if opts.db_tablespace and connection.features.supports_tablespaces:407 # f.db_tablespace is only for indices, so ignore its value here.408 table_output.append(connection.ops.tablespace_sql(opts.db_tablespace))409 table_output.append(';')410 final_output.append('\n'.join(table_output))411 412 for r_table, r_col, table, col in deferred:413 r_name = '%s_refs_%s_%x' % (r_col, col,414 abs(hash((r_table, table))))415 final_output.append(style.SQL_KEYWORD('ALTER TABLE') + ' %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s)%s;' %416 (qn(r_table),417 truncate_name(r_name, connection.ops.max_name_length()),418 qn(r_col), qn(table), qn(col),419 connection.ops.deferrable_sql()))420 421 # Add any extra SQL needed to support auto-incrementing PKs422 autoinc_sql = connection.ops.autoinc_sql(f.m2m_db_table(), 'id')423 if autoinc_sql:424 for stmt in autoinc_sql:425 final_output.append(stmt)426 427 return final_output428 429 161 def custom_sql_for_model(model, style): 430 162 from django.db import models 431 163 from django.conf import settings … … 461 193 462 194 return output 463 195 464 def sql_indexes_for_model(model, style):465 "Returns the CREATE INDEX SQL statements for a single model"466 from django.db import connection467 output = []468 196 469 qn = connection.ops.quote_name470 for f in model._meta.local_fields:471 if f.db_index and not f.unique:472 tablespace = f.db_tablespace or model._meta.db_tablespace473 if tablespace and connection.features.supports_tablespaces:474 tablespace_sql = ' ' + connection.ops.tablespace_sql(tablespace)475 else:476 tablespace_sql = ''477 output.append(478 style.SQL_KEYWORD('CREATE INDEX') + ' ' + \479 style.SQL_TABLE(qn('%s_%s' % (model._meta.db_table, f.column))) + ' ' + \480 style.SQL_KEYWORD('ON') + ' ' + \481 style.SQL_TABLE(qn(model._meta.db_table)) + ' ' + \482 "(%s)" % style.SQL_FIELD(qn(f.column)) + \483 "%s;" % tablespace_sql484 )485 return output486 487 197 def emit_post_sync_signal(created_models, verbosity, interactive): 488 198 from django.db import models 489 199 from django.dispatch import dispatcher -
django/contrib/gis/db/backend/postgis/creation.py
1 1 from django.conf import settings 2 2 from django.core.management import call_command 3 3 from django.db import connection 4 from django. test.utils import _set_autocommit,TEST_DATABASE_PREFIX4 from django.db.backends.creation import TEST_DATABASE_PREFIX 5 5 import os, re, sys 6 6 7 7 def getstatusoutput(cmd): … … 38 38 create_sql = 'CREATE DATABASE %s' % connection.ops.quote_name(db_name) 39 39 if settings.DATABASE_USER: 40 40 create_sql += ' OWNER %s' % settings.DATABASE_USER 41 41 42 42 cursor = connection.cursor() 43 _set_autocommit(connection)43 connection.creation._set_autocommit(connection) 44 44 45 45 try: 46 46 # Trying to create the database first. … … 58 58 else: 59 59 raise Exception('Spatial Database Creation canceled.') 60 60 foo = _create_with_cursor 61 61 62 62 created_regex = re.compile(r'^createdb: database creation failed: ERROR: database ".+" already exists') 63 63 def _create_with_shell(db_name, verbosity=1, autoclobber=False): 64 64 """ 65 If no spatial database already exists, then using a cursor will not work. 66 Thus, a `createdb` command will be issued through the shell to bootstrap 65 If no spatial database already exists, then using a cursor will not work. 66 Thus, a `createdb` command will be issued through the shell to bootstrap 67 67 creation of the spatial database. 68 68 """ 69 69 … … 83 83 if verbosity >= 1: print 'Destroying old spatial database...' 84 84 drop_cmd = 'dropdb %s%s' % (options, db_name) 85 85 status, output = getstatusoutput(drop_cmd) 86 if status != 0: 86 if status != 0: 87 87 raise Exception('Could not drop database %s: %s' % (db_name, output)) 88 88 if verbosity >= 1: print 'Creating new spatial database...' 89 89 status, output = getstatusoutput(create_cmd) … … 102 102 raise Exception('Spatial database creation only supported postgresql_psycopg2 platform.') 103 103 104 104 # Getting the spatial database name 105 if test: 105 if test: 106 106 db_name = get_spatial_db(test=True) 107 107 _create_with_cursor(db_name, verbosity=verbosity, autoclobber=autoclobber) 108 else: 108 else: 109 109 db_name = get_spatial_db() 110 110 _create_with_shell(db_name, verbosity=verbosity, autoclobber=autoclobber) 111 111 … … 125 125 126 126 # Syncing the database 127 127 call_command('syncdb', verbosity=verbosity, interactive=interactive) 128 128 129 129 def drop_db(db_name=False, test=False): 130 130 """ 131 131 Drops the given database (defaults to what is returned from … … 151 151 152 152 def get_spatial_db(test=False): 153 153 """ 154 Returns the name of the spatial database. The 'test' keyword may be set 154 Returns the name of the spatial database. The 'test' keyword may be set 155 155 to return the test spatial database name. 156 156 """ 157 157 if test: … … 167 167 168 168 def load_postgis_sql(db_name, verbosity=1): 169 169 """ 170 This routine loads up the PostGIS SQL files lwpostgis.sql and 170 This routine loads up the PostGIS SQL files lwpostgis.sql and 171 171 spatial_ref_sys.sql. 172 172 """ 173 173 174 174 # Getting the path to the PostGIS SQL 175 175 try: 176 # POSTGIS_SQL_PATH may be placed in settings to tell GeoDjango where the 176 # POSTGIS_SQL_PATH may be placed in settings to tell GeoDjango where the 177 177 # PostGIS SQL files are located. This is especially useful on Win32 178 178 # platforms since the output of pg_config looks like "C:/PROGRA~1/..". 179 179 sql_path = settings.POSTGIS_SQL_PATH … … 193 193 # Getting the psql command-line options, and command format. 194 194 options = get_cmd_options(db_name) 195 195 cmd_fmt = 'psql %s-f "%%s"' % options 196 196 197 197 # Now trying to load up the PostGIS functions 198 198 cmd = cmd_fmt % lwpostgis_file 199 199 if verbosity >= 1: print cmd … … 211 211 # Setting the permissions because on Windows platforms the owner 212 212 # of the spatial_ref_sys and geometry_columns tables is always 213 213 # the postgres user, regardless of how the db is created. 214 if os.name == 'nt': set_permissions(db_name) 215 214 if os.name == 'nt': set_permissions(db_name) 215 216 216 def set_permissions(db_name): 217 217 """ 218 218 Sets the permissions on the given database to that of the user specified -
django/contrib/gis/management/commands/inspectdb.py
7 7 from django.contrib.gis.db.backend import SpatialBackend 8 8 9 9 class Command(InspectCommand): 10 10 11 11 # Mapping from lower-case OGC type to the corresponding GeoDjango field. 12 12 geofield_mapping = {'point' : 'PointField', 13 13 'linestring' : 'LineStringField', … … 21 21 22 22 def geometry_columns(self): 23 23 """ 24 Returns a datastructure of metadata information associated with the 24 Returns a datastructure of metadata information associated with the 25 25 `geometry_columns` (or equivalent) table. 26 26 """ 27 27 # The `geo_cols` is a dictionary data structure that holds information 28 # about any geographic columns in the database. 28 # about any geographic columns in the database. 29 29 geo_cols = {} 30 30 def add_col(table, column, coldata): 31 31 if table in geo_cols: … … 47 47 elif SpatialBackend.name == 'mysql': 48 48 # On MySQL have to get all table metadata before hand; this means walking through 49 49 # each table and seeing if any column types are spatial. Can't detect this with 50 # `cursor.description` (what the introspection module does) because all spatial types 50 # `cursor.description` (what the introspection module does) because all spatial types 51 51 # have the same integer type (255 for GEOMETRY). 52 52 from django.db import connection 53 53 cursor = connection.cursor() … … 67 67 68 68 def handle_inspection(self): 69 69 "Overloaded from Django's version to handle geographic database tables." 70 from django.db import connection , get_introspection_module70 from django.db import connection 71 71 import keyword 72 72 73 introspection_module = get_introspection_module()74 75 73 geo_cols = self.geometry_columns() 76 74 77 75 table2model = lambda table_name: table_name.title().replace('_', '') 78 76 79 77 cursor = connection.cursor() … … 88 86 yield '' 89 87 yield 'from django.contrib.gis.db import models' 90 88 yield '' 91 for table_name in introspection_module.get_table_list(cursor):89 for table_name in connection.introspection.get_table_list(cursor): 92 90 # Getting the geographic table dictionary. 93 91 geo_table = geo_cols.get(table_name, {}) 94 92 95 93 yield 'class %s(models.Model):' % table2model(table_name) 96 94 try: 97 relations = introspection_module.get_relations(cursor, table_name)95 relations = connection.introspection.get_relations(cursor, table_name) 98 96 except NotImplementedError: 99 97 relations = {} 100 98 try: 101 indexes = introspection_module.get_indexes(cursor, table_name)99 indexes = connection.introspection.get_indexes(cursor, table_name) 102 100 except NotImplementedError: 103 101 indexes = {} 104 for i, row in enumerate( introspection_module.get_table_description(cursor, table_name)):102 for i, row in enumerate(connection.introspection.get_table_description(cursor, table_name)): 105 103 att_name, iatt_name = row[0].lower(), row[0] 106 104 comment_notes = [] # Holds Field notes, to be displayed in a Python comment. 107 105 extra_params = {} # Holds Field parameters such as 'db_column'. … … 133 131 if srid != 4326: extra_params['srid'] = srid 134 132 else: 135 133 try: 136 field_type = introspection_module.DATA_TYPES_REVERSE[row[1]]134 field_type = connection.introspection.data_types_reverse[row[1]] 137 135 except KeyError: 138 136 field_type = 'TextField' 139 137 comment_notes.append('This field type is a guess.') 140 138 141 # This is a hook for DATA_TYPES_REVERSEto return a tuple of139 # This is a hook for data_types_reverse to return a tuple of 142 140 # (field_type, extra_params_dict). 143 141 if type(field_type) is tuple: 144 142 field_type, new_params = field_type -
tests/regressiontests/backends/models.py
15 15 def __unicode__(self): 16 16 return u'%s %s' % (self.first_name, self.last_name) 17 17 18 if connection.features.uses_case_insensitive_names:19 t_convert = lambda x: x.upper()20 else:21 t_convert = lambda x: x22 18 qn = connection.ops.quote_name 23 19 24 20 __test__ = {'API_TESTS': """ … … 29 25 >>> opts = Square._meta 30 26 >>> f1, f2 = opts.get_field('root'), opts.get_field('square') 31 27 >>> query = ('INSERT INTO %s (%s, %s) VALUES (%%s, %%s)' 32 ... % ( t_convert(opts.db_table), qn(f1.column), qn(f2.column)))28 ... % (connection.introspection.table_name_converter(opts.db_table), qn(f1.column), qn(f2.column))) 33 29 >>> cursor.executemany(query, [(i, i**2) for i in range(-5, 6)]) and None or None 34 30 >>> Square.objects.order_by('root') 35 31 [<Square: -5 ** 2 == 25>, <Square: -4 ** 2 == 16>, <Square: -3 ** 2 == 9>, <Square: -2 ** 2 == 4>, <Square: -1 ** 2 == 1>, <Square: 0 ** 2 == 0>, <Square: 1 ** 2 == 1>, <Square: 2 ** 2 == 4>, <Square: 3 ** 2 == 9>, <Square: 4 ** 2 == 16>, <Square: 5 ** 2 == 25>] … … 48 44 >>> opts2 = Person._meta 49 45 >>> f3, f4 = opts2.get_field('first_name'), opts2.get_field('last_name') 50 46 >>> query2 = ('SELECT %s, %s FROM %s ORDER BY %s' 51 ... % (qn(f3.column), qn(f4.column), t_convert(opts2.db_table),47 ... % (qn(f3.column), qn(f4.column), connection.introspection.table_name_converter(opts2.db_table), 52 48 ... qn(f3.column))) 53 49 >>> cursor.execute(query2) and None or None 54 50 >>> cursor.fetchone() -
docs/testing.txt
1026 1026 black magic hooks into the template system and restoring normal e-mail 1027 1027 services. 1028 1028 1029 The creation module of the database backend (``connection.creation``) also 1030 provides some utilities that can be useful during testing. 1031 1029 1032 ``create_test_db(verbosity=1, autoclobber=False)`` 1030 1033 Creates a new test database and runs ``syncdb`` against it. 1031 1034