Ejemplo n.º 1
0
def get_sql_evolution_detailed(app, style, notify):
    "Returns SQL to update an existing schema to match the existing models."
    
    from django.db import connection
    cursor = connection.cursor()
    #show_evolution_plan(cursor, app, style)

    ops, introspection = get_operations_and_introspection_classes(style)
    app_name = app.__name__.split('.')[-2]
    
    final_output = []

    db_schema, model_schema = get_schemas(cursor, app, style) 
    cursor, app_name, get_installed_tables(app)
    schema_fingerprint = introspection.get_schema_fingerprint(model_schema)
    schema_recognized, all_upgrade_paths, available_upgrades, best_upgrade \
        = get_managed_evolution_options(app, schema_fingerprint, style, notify)
    if schema_recognized:
        if notify: sys.stderr.write(style.NOTICE("deseb: Current schema fingerprint for '%s' is '%s' (recognized)\n" % (app_name, schema_fingerprint)))
        final_output.extend(best_upgrade[2])
        return schema_fingerprint, False, final_output
    else:
        if notify: sys.stderr.write(style.NOTICE("deseb: Current schema fingerprint for '%s' is '%s' (unrecognized)\n" % (app_name, schema_fingerprint)))

    final_output.extend(get_introspected_evolution_options(app, style))
        
    return schema_fingerprint, True, final_output
Ejemplo n.º 2
0
def evolvedb(app, interactive=True, do_save=False, verbose=False, managed_upgrade_only=False):
    from django.db import connection
    cursor = connection.cursor()

    style = color.no_style()
    ops, introspection = get_operations_and_introspection_classes(style)
    app_name = app.__name__.split('.')[-2]
    
    seen_schema_fingerprints = set()
    
    fingerprints, evolutions = get_fingerprints_evolutions_from_app(app, style, verbose)
    if fingerprints and evolutions:
        if verbose:
            print 'deseb: %s.schema_evolution module found (%i fingerprints, %i evolutions)' % \
                    (app_name, len(fingerprints), len(evolutions))

    while True:
        commands = []
        commands_color = []
    
        schema_fingerprint = introspection.get_schema_fingerprint(cursor, app_name, get_installed_tables(app))
        schema_recognized, all_upgrade_paths, available_upgrades, best_upgrade = \
                    get_managed_evolution_options(app, schema_fingerprint, style, verbose)
        if fingerprints and evolutions:
            if schema_recognized:
                if verbose or interactive: 
                    print "deseb: fingerprint for '%s' is '%s' (recognized)" % (app_name, schema_fingerprint)
            else:
                if verbose or interactive: 
                    print "deseb: fingerprint for '%s' is '%s' (unrecognized)" % (app_name, schema_fingerprint)
        managed_upgrade = schema_recognized and available_upgrades and best_upgrade and best_upgrade[3]>0
        if managed_upgrade:
            if verbose or interactive: 
                print "\t and a managed schema upgrade to '%s' is available:" % best_upgrade[1], best_upgrade[3]
            commands_color = commands = best_upgrade[2]
        elif not managed_upgrade_only:
            commands = get_introspected_evolution_options(app, style)
            commands_color = get_introspected_evolution_options(app, color.color_style())
            if interactive:
                if commands:
                    print '%s: the following schema upgrade is available:' % app_name
    #            else:
    #                print '%s: schema is up to date' % app_name
            
        if commands:
            if interactive or DEBUG:
                for cmd in commands_color:
                    print cmd
        else:
                break
    
        if interactive:
            confirm = raw_input("do you want to run the preceeding commands?\ntype 'yes' to continue, or 'no' to cancel: ")
        else:
            confirm = 'yes'
        
        if confirm == 'yes':
            connection._commit() # clean previous commands run state
            for cmd in commands:
                if cmd[:3] != '-- ':
                    cursor.execute(cmd)
            connection._commit() # commit changes
            if interactive: print 'schema upgrade executed'
            new_schema_fingerprint = introspection.get_schema_fingerprint(cursor, app_name, get_installed_tables(app))
            
            if schema_fingerprint==new_schema_fingerprint:
                print "schema fingerprint was unchanged - this really shouldn't happen"
            else:
                if commands and not managed_upgrade and (schema_fingerprint,new_schema_fingerprint) not in all_upgrade_paths:
                    if interactive and do_save:
                        confirm = raw_input("do you want to save these commands in %s.schema_evolution?\n"
                                            "type 'yes' to continue, or 'no' to cancel: " % app_name)
                    else:
                        confirm = 'yes'
                    if do_save and confirm == 'yes':
                        save_managed_evolution(app, commands, schema_fingerprint, new_schema_fingerprint)
            
            if not managed_upgrade: break
        else:
            if interactive: print 'schema not saved'
            break
                
        seen_schema_fingerprints.add(schema_fingerprint)
        schema_fingerprint = new_schema_fingerprint
            
        if managed_upgrade:
            if schema_fingerprint==best_upgrade[1]:
                if verbose: 
                    print '\tfingerprint verification successful'
            else:
                if verbose: 
                    print "\tfingerprint verification failed (is '%s'; was expecting '%s')" % \
                            (schema_fingerprint, best_upgrade[1])
                break
        
        print
    
        if schema_fingerprint in seen_schema_fingerprints:
            break
Ejemplo n.º 3
0
def modeltest(app_name, use_aka=True):
    if not app_name:
        raise Exception("No test name given")
    if not os.path.exists('settings.py'):
        raise Exception('Oops... file settings.py does not exist! Please copy your settings there!')
    from django.conf import settings
    from django.db.models.loading import get_apps, get_app
    from deseb.schema_evolution import evolvediff
    from django.core.management.color import no_style
    from deseb.actions import get_introspected_evolution_options
    from django.core.management.sql import sql_create, sql_indexes
    from django.db.transaction import commit_on_success
    from django.db import connection
    from deseb.actions import get_schemas, show_evolution_plan
    if DEBUG:
        print "Test %s" % app_name
    #reset on post state and pre state
    from deseb import add_aka_support
    if use_aka:
        add_aka_support()
    
    style = no_style()
    settings.INSTALLED_APPS = tuple(list(settings.INSTALLED_APPS[:5]) + [app_name])
    
    write_file(app_name+"/models.py", '') # re-init models.py
    write_file(app_name+"/errdiff.%s.actual" % settings.DATABASE_ENGINE, "")
    write_file(app_name+"/errors.%s.actual" % settings.DATABASE_ENGINE, "")
    get_apps()
    
    drop_all_tables()
    
    reload_models(app_name, 'pre')    
    app = get_app(app_name)
    create = sql_create(app, style) + sql_indexes(app, style)
    write_file(app_name+"/init.%s.actual" % settings.DATABASE_ENGINE, create)
    #FIXME: compare to init.correct later instead of copying
    write_file(app_name+"/init.%s.planned" % settings.DATABASE_ENGINE, create)
    
    reset = sql_create(app, style)
    #print 'SQL:', '\n'.join(reset)
    commit_on_success(run_sql)(reset)
    
    reset_idx = sql_indexes(app, style)
    run_sql(reset_idx)
    
    reload_models(app_name, 'post')
    if use_aka:
        from deseb.storage import update_with_aka, save_renames
        update_with_aka(app_name)
        save_renames(app_name)

    cursor = connection.cursor()
    db_schema, model_schema = get_schemas(cursor, app, style)
    diff = show_evolution_plan(cursor, app, style, db_schema, model_schema)
    write_file(app_name+"/diff.%s.actual" % settings.DATABASE_ENGINE, diff)
    #FIXME: compare to diff.correct later instead of copying
    write_file(app_name+"/diff.%s.planned" % settings.DATABASE_ENGINE, diff)
    
    actions = get_introspected_evolution_options(app, style, db_schema, model_schema)
    write_file(app_name+"/actions.%s.actual" % settings.DATABASE_ENGINE, actions)
    #FIXME: compare to diff.correct later instead of copying
    write_file(app_name+"/actions.%s.planned" % settings.DATABASE_ENGINE, actions)
    try:
        commit_on_success(run_sql)(actions)
    except:
        #print 'changes rolled back'
        from django.db import transaction
        transaction.rollback()
        raise
    #else:
        #print 'changes committed'

    cursor = connection.cursor()
    db_schema, model_schema = get_schemas(cursor, app, style, model_schema=model_schema)
    # due to sqlite3/pysqlite bug, caused deferred index creation, we reget db schema.
    # this is f*****g weird, but i've no any explanation, why getting indxes
    # doesn't work correctly first time  
    db_schema, model_schema = get_schemas(cursor, app, style, model_schema=model_schema)
    diff = show_evolution_plan(cursor, app, style, db_schema, model_schema)
    write_file(app_name+"/errdiff.%s.actual" % settings.DATABASE_ENGINE, diff)
    diff1 = diff.split('\n',1)[1]
    if diff1:
        print "Errors:"
        print diff1

    try:
        actions, db_schema, model_schema = get_introspected_evolution_options(app, style, db_schema, model_schema)
    except Exception:
        actions = ['Was unable to generate error diff SQL commands']
    write_file(app_name+"/errors.%s.actual" % settings.DATABASE_ENGINE, actions)
    #FIXME: compare to diff.correct later instead of copying
    #write_file(app_name+"/errors.%s.planned" % settings.DATABASE_ENGINE, actions)
    return diff1