Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
moved most of the sql_evolve code into its own module git-svn-id: http://code.djangoproject.com/svn/django/branches/schema-evolution@5789 bcc190cf-cafb-0310-a4f2-bffc1f526a37
- Loading branch information
Showing
2 changed files
with
161 additions
and
150 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
import django | ||
from django.core.exceptions import ImproperlyConfigured | ||
from optparse import OptionParser | ||
from django.utils import termcolors | ||
from django.conf import settings | ||
import os, re, shutil, sys, textwrap | ||
import management | ||
|
||
|
||
def get_sql_evolution_check_for_new_fields(klass, new_table_name): | ||
"checks for model fields that are not in the existing data structure" | ||
from django.db import backend, get_creation_module, models, get_introspection_module, connection | ||
data_types = get_creation_module().DATA_TYPES | ||
cursor = connection.cursor() | ||
introspection = get_introspection_module() | ||
opts = klass._meta | ||
output = [] | ||
db_table = klass._meta.db_table | ||
if new_table_name: | ||
db_table = new_table_name | ||
for f in opts.fields: | ||
existing_fields = introspection.get_columns(cursor,db_table) | ||
if f.column not in existing_fields and (not f.aka or f.aka not in existing_fields and len(set(f.aka) & set(existing_fields))==0): | ||
rel_field = f | ||
data_type = f.get_internal_type() | ||
col_type = data_types.get(data_type) | ||
if col_type is not None: | ||
output.extend( backend.get_add_column_sql( klass._meta.db_table, f.column, management.style.SQL_COLTYPE(col_type % rel_field.__dict__), f.null, f.unique, f.primary_key ) ) | ||
return output | ||
|
||
def get_sql_evolution_check_for_changed_model_name(klass): | ||
from django.db import backend, get_creation_module, models, get_introspection_module, connection | ||
cursor = connection.cursor() | ||
introspection = get_introspection_module() | ||
table_list = introspection.get_table_list(cursor) | ||
if klass._meta.db_table in table_list: | ||
return [], None | ||
if klass._meta.aka in table_list: | ||
return backend.get_change_table_name_sql( klass._meta.db_table, klass._meta.aka), klass._meta.aka | ||
elif len(set(klass._meta.aka) & set(table_list))==1: | ||
return backend.get_change_table_name_sql( klass._meta.db_table, klass._meta.aka[0]), klass._meta.aka[0] | ||
else: | ||
return [], None | ||
|
||
def get_sql_evolution_check_for_changed_field_name(klass, new_table_name): | ||
from django.db import backend, get_creation_module, models, get_introspection_module, connection | ||
data_types = get_creation_module().DATA_TYPES | ||
cursor = connection.cursor() | ||
introspection = get_introspection_module() | ||
opts = klass._meta | ||
output = [] | ||
db_table = klass._meta.db_table | ||
if new_table_name: | ||
db_table = new_table_name | ||
for f in opts.fields: | ||
existing_fields = introspection.get_columns(cursor,db_table) | ||
if f.column not in existing_fields and f.aka and (f.aka in existing_fields or len(set(f.aka) & set(existing_fields)))==1: | ||
old_col = None | ||
if isinstance( f.aka, str ): | ||
old_col = f.aka | ||
else: | ||
old_col = f.aka[0] | ||
rel_field = f | ||
data_type = f.get_internal_type() | ||
col_type = data_types[data_type] | ||
if col_type is not None: | ||
col_def = management.style.SQL_COLTYPE(col_type % rel_field.__dict__) +' '+ management.style.SQL_KEYWORD('%sNULL' % (not f.null and 'NOT ' or '')) | ||
if f.unique: | ||
col_def += management.style.SQL_KEYWORD(' UNIQUE') | ||
if f.primary_key: | ||
col_def += management.style.SQL_KEYWORD(' PRIMARY KEY') | ||
output.extend( backend.get_change_column_name_sql( klass._meta.db_table, introspection.get_indexes(cursor,db_table), old_col, f.column, col_def ) ) | ||
return output | ||
|
||
def get_sql_evolution_check_for_changed_field_flags(klass, new_table_name): | ||
from django.db import backend, get_creation_module, models, get_introspection_module, connection | ||
from django.db.models.fields import CharField, SlugField | ||
from django.db.models.fields.related import RelatedField, ForeignKey | ||
data_types = get_creation_module().DATA_TYPES | ||
cursor = connection.cursor() | ||
introspection = get_introspection_module() | ||
opts = klass._meta | ||
output = [] | ||
db_table = klass._meta.db_table | ||
if new_table_name: | ||
db_table = new_table_name | ||
for f in opts.fields: | ||
existing_fields = introspection.get_columns(cursor,db_table) | ||
# print existing_fields | ||
cf = None # current field, ie what it is before any renames | ||
if f.column in existing_fields: | ||
cf = f.column | ||
elif f.aka in existing_fields: | ||
cf = f.aka | ||
elif f.aka and len(set(f.aka) & set(existing_fields))==1: | ||
cf = f.aka[0] | ||
else: | ||
continue # no idea what column you're talking about - should be handled by get_sql_evolution_check_for_new_fields()) | ||
data_type = f.get_internal_type() | ||
if data_types.has_key(data_type): | ||
column_flags = introspection.get_known_column_flags(cursor, db_table, cf) | ||
# print db_table, cf, column_flags | ||
if column_flags['allow_null']!=f.null or \ | ||
( not f.primary_key and isinstance(f, CharField) and column_flags['maxlength']!=str(f.maxlength) ) or \ | ||
( not f.primary_key and isinstance(f, SlugField) and column_flags['maxlength']!=str(f.maxlength) ) or \ | ||
( column_flags['unique']!=f.unique and ( settings.DATABASE_ENGINE!='postgresql' or not f.primary_key ) ) or \ | ||
column_flags['primary_key']!=f.primary_key: | ||
#column_flags['foreign_key']!=f.foreign_key: | ||
# print 'need to change' | ||
# print db_table, f.column, column_flags | ||
# print "column_flags['allow_null']!=f.null", column_flags['allow_null']!=f.null | ||
# print "not f.primary_key and isinstance(f, CharField) and column_flags['maxlength']!=str(f.maxlength)", not f.primary_key and isinstance(f, CharField) and column_flags['maxlength']!=str(f.maxlength) | ||
# print "not f.primary_key and isinstance(f, SlugField) and column_flags['maxlength']!=str(f.maxlength)", not f.primary_key and isinstance(f, SlugField) and column_flags['maxlength']!=str(f.maxlength) | ||
# print "column_flags['unique']!=f.unique", column_flags['unique']!=f.unique | ||
# print "column_flags['primary_key']!=f.primary_key", column_flags['primary_key']!=f.primary_key | ||
col_type = data_types[data_type] | ||
col_type_def = management.style.SQL_COLTYPE(col_type % f.__dict__) | ||
# col_def = style.SQL_COLTYPE(col_type % f.__dict__) +' '+ style.SQL_KEYWORD('%sNULL' % (not f.null and 'NOT ' or '')) | ||
# if f.unique: | ||
# col_def += ' '+ style.SQL_KEYWORD('UNIQUE') | ||
# if f.primary_key: | ||
# col_def += ' '+ style.SQL_KEYWORD('PRIMARY KEY') | ||
output.extend( backend.get_change_column_def_sql( klass._meta.db_table, cf, col_type_def, f.null, f.unique, f.primary_key ) ) | ||
#print db_table, cf, f.maxlength, introspection.get_known_column_flags(cursor, db_table, cf) | ||
return output | ||
|
||
def get_sql_evolution_check_for_dead_fields(klass, new_table_name): | ||
from django.db import backend, get_creation_module, models, get_introspection_module, connection | ||
from django.db.models.fields import CharField, SlugField | ||
from django.db.models.fields.related import RelatedField, ForeignKey | ||
data_types = get_creation_module().DATA_TYPES | ||
cursor = connection.cursor() | ||
introspection = get_introspection_module() | ||
opts = klass._meta | ||
output = [] | ||
db_table = klass._meta.db_table | ||
if new_table_name: | ||
db_table = new_table_name | ||
suspect_fields = set(introspection.get_columns(cursor,db_table)) | ||
# print 'suspect_fields = ', suspect_fields | ||
for f in opts.fields: | ||
# print 'f = ', f | ||
# print 'f.aka = ', f.aka | ||
suspect_fields.discard(f.column) | ||
suspect_fields.discard(f.aka) | ||
if f.aka: suspect_fields.difference_update(f.aka) | ||
if len(suspect_fields)>0: | ||
output.append( '-- warning: the following may cause data loss' ) | ||
for suspect_field in suspect_fields: | ||
output.extend( backend.get_drop_column_sql( klass._meta.db_table, suspect_field ) ) | ||
output.append( '-- end warning' ) | ||
return output | ||
|