First stab at MySQL support

This commit is contained in:
Andrew Godwin 2012-08-18 12:29:31 +01:00
parent 60873ea2ad
commit cab044c66c
5 changed files with 62 additions and 4 deletions

View File

@ -37,6 +37,7 @@ from django.db.backends.mysql.client import DatabaseClient
from django.db.backends.mysql.creation import DatabaseCreation from django.db.backends.mysql.creation import DatabaseCreation
from django.db.backends.mysql.introspection import DatabaseIntrospection from django.db.backends.mysql.introspection import DatabaseIntrospection
from django.db.backends.mysql.validation import DatabaseValidation from django.db.backends.mysql.validation import DatabaseValidation
from django.db.backends.mysql.schema import DatabaseSchemaEditor
from django.utils.functional import cached_property from django.utils.functional import cached_property
from django.utils.safestring import SafeString, SafeUnicode from django.utils.safestring import SafeString, SafeUnicode
from django.utils import six from django.utils import six
@ -488,3 +489,7 @@ class DatabaseWrapper(BaseDatabaseWrapper):
% (table_name, bad_row[0], % (table_name, bad_row[0],
table_name, column_name, bad_row[1], table_name, column_name, bad_row[1],
referenced_table_name, referenced_column_name)) referenced_table_name, referenced_column_name))
def schema_editor(self):
"Returns a new instance of this backend's SchemaEditor"
return DatabaseSchemaEditor(self)

View File

@ -102,3 +102,35 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
indexes[row[4]] = {'primary_key': (row[2] == 'PRIMARY'), 'unique': not bool(row[1])} indexes[row[4]] = {'primary_key': (row[2] == 'PRIMARY'), 'unique': not bool(row[1])}
return indexes return indexes
def get_constraints(self, cursor, table_name):
"""
Retrieves any constraints (unique, pk, fk, check) across one or more columns.
Returns {'cnname': {'columns': set(columns), 'primary_key': bool, 'unique': bool}}
"""
constraints = {}
# Loop over the constraint tables, collecting things as constraints
ifsc_tables = ["constraint_column_usage", "key_column_usage"]
for ifsc_table in ifsc_tables:
cursor.execute("""
SELECT kc.constraint_name, kc.column_name, c.constraint_type
FROM information_schema.%s AS kc
JOIN information_schema.table_constraints AS c ON
kc.table_schema = c.table_schema AND
kc.table_name = c.table_name AND
kc.constraint_name = c.constraint_name
WHERE
kc.table_schema = %%s AND
kc.table_name = %%s
""" % ifsc_table, [self.connection.settings_dict['NAME'], table_name])
for constraint, column, kind in cursor.fetchall():
# If we're the first column, make the record
if constraint not in constraints:
constraints[constraint] = {
"columns": set(),
"primary_key": kind.lower() == "primary key",
"foreign_key": kind.lower() == "foreign key",
"unique": kind.lower() in ["primary key", "unique"],
}
# Record the details
constraints[constraint]['columns'].add(column)
return constraints

View File

@ -0,0 +1,24 @@
from django.db.backends.schema import BaseDatabaseSchemaEditor
class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
sql_rename_table = "RENAME TABLE %(old_table)s TO %(new_table)s"
sql_alter_column_null = "MODIFY %(column)s %(type)s NULL"
sql_alter_column_not_null = "MODIFY %(column)s %(type)s NULL"
sql_delete_unique = "ALTER TABLE %(table)s DROP INDEX %(name)s"
sql_create_fk = "ALTER TABLE %(table)s ADD CONSTRAINT %(name)s FOREIGN KEY (%(column)s) REFERENCES %(to_table)s (%(to_column)s)"
sql_delete_fk = "ALTER TABLE %(table)s DROP FOREIGN KEY %(name)s"
sql_delete_index = "DROP INDEX %(name)s ON %(table_name)s"
sql_delete_pk = "ALTER TABLE %(table)s DROP PRIMARY KEY"
alter_string_set_null = 'MODIFY %(column)s %(type)s NULL;'
alter_string_drop_null = 'MODIFY %(column)s %(type)s NOT NULL;'

View File

@ -91,7 +91,7 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
def get_constraints(self, cursor, table_name): def get_constraints(self, cursor, table_name):
""" """
Retrieves any constraints (unique, pk, check) across one or more columns. Retrieves any constraints (unique, pk, fk, check) across one or more columns.
Returns {'cnname': {'columns': set(columns), 'primary_key': bool, 'unique': bool}} Returns {'cnname': {'columns': set(columns), 'primary_key': bool, 'unique': bool}}
""" """
constraints = {} constraints = {}

View File

@ -167,7 +167,6 @@ class SchemaTests(TestCase):
# Ensure the field is right to begin with # Ensure the field is right to begin with
columns = self.column_classes(Author) columns = self.column_classes(Author)
self.assertEqual(columns['name'][0], "CharField") self.assertEqual(columns['name'][0], "CharField")
self.assertEqual(columns['name'][1][3], 255)
self.assertEqual(columns['name'][1][6], False) self.assertEqual(columns['name'][1][6], False)
# Alter the name field to a TextField # Alter the name field to a TextField
new_field = TextField(null=True) new_field = TextField(null=True)
@ -197,7 +196,6 @@ class SchemaTests(TestCase):
# Ensure the field is right to begin with # Ensure the field is right to begin with
columns = self.column_classes(Author) columns = self.column_classes(Author)
self.assertEqual(columns['name'][0], "CharField") self.assertEqual(columns['name'][0], "CharField")
self.assertEqual(columns['name'][1][3], 255)
self.assertNotIn("display_name", columns) self.assertNotIn("display_name", columns)
# Alter the name field's name # Alter the name field's name
new_field = CharField(max_length=254) new_field = CharField(max_length=254)
@ -213,7 +211,6 @@ class SchemaTests(TestCase):
# Ensure the field is right afterwards # Ensure the field is right afterwards
columns = self.column_classes(Author) columns = self.column_classes(Author)
self.assertEqual(columns['display_name'][0], "CharField") self.assertEqual(columns['display_name'][0], "CharField")
self.assertEqual(columns['display_name'][1][3], 254)
self.assertNotIn("name", columns) self.assertNotIn("name", columns)
def test_m2m(self): def test_m2m(self):