def execute_transaction(sql, output=False, database='default'): "A transaction wrapper for executing a list of SQL statements" my_connection = connection using_args = {} if is_multi_db(): if not database: database = DEFAULT_DB_ALIAS my_connection = connections[database] using_args['using'] = database try: # Begin Transaction transaction.enter_transaction_management(**using_args) transaction.managed(True, **using_args) cursor = my_connection.cursor() # Perform the SQL if output: write_sql(sql, database) execute_sql(cursor, sql) transaction.commit(**using_args) transaction.leave_transaction_management(**using_args) except Exception: transaction.rollback(**using_args) raise
def execute_test_sql(start, end, sql, debug=False, app_label='tests', database='default'): """ Execute a test SQL sequence. This method also creates and destroys the database tables required by the models registered against the test application. start and end are the start- and end-point states of the application cache. sql is the list of sql statements to execute. cleanup is a list of extra sql statements required to clean up. This is primarily for any extra m2m tables that were added during a test that won't be cleaned up by Django's sql_delete() implementation. debug is a helper flag. It displays the ALL the SQL that would be executed, (including setup and teardown SQL), and executes the Django-derived setup/teardown SQL. """ # Set up the initial state of the app cache set_app_test_models(copy.deepcopy(start), app_label=app_label) # Install the initial tables and indicies style = no_style() execute_transaction(sql_create(evo_test, style, database), output=debug, database=database) execute_transaction(sql_indexes(evo_test, style, database), output=debug, database=database) create_test_data(models.get_models(evo_test), database) # Set the app cache to the end state set_app_test_models(copy.deepcopy(end), app_label=app_label) try: # Execute the test sql if debug: write_sql(sql, database) else: execute_transaction(sql, output=True, database=database) finally: # Cleanup the apps. if debug: print sql_delete(evo_test, style, database) else: execute_transaction(sql_delete(evo_test, style, database), output=debug, database=database)
def _display_compiled_sql(self): """Display the compiled SQL for the evolution run. This will output the SQL that would be executed based on the options passed to the command. """ database_name = self.evolver.database_name for i, task in enumerate(self.evolver.tasks): if task.sql: if i > 0: self.stdout.write('\n') self.stdout.write('-- %s\n' % task) write_sql(task.sql, database_name)
def execute_transaction(sql, output=False): "A transaction wrapper for executing a list of SQL statements" try: # Begin Transaction transaction.enter_transaction_management() transaction.managed(True) cursor = connection.cursor() # Perform the SQL if output: write_sql(sql) execute_sql(cursor, sql) transaction.commit() transaction.leave_transaction_management() except Exception, ex: transaction.rollback() raise ex
def execute_test_sql(start_sig, end_sig, generate_sql_func, app_label='tests', database=DEFAULT_DB_ALIAS): """Execute SQL for a unit test. This will register all necessary models and indexes, as defined by the starting signature, and populate them in the database. It then sets the model state to reflect the ending signature, allowing the unit test to perform operations to go from the in-database starting state to the new ending signature state. The SQL provided by ``generate_sql_func`` will be output to the console, to aid in debugging when tests fail. Args: start_sig (dict): The signature for the initial database state, used to generate tables and indexes in the database. end_sig (dict): The signature for the ending database state, reflecting what the evolutions will be attempting to evolve to. generate_sql_func (callable): A function that takes no parameters and returns SQL to execute, once the database and app/model states are set up. app_label (unicode, optional): The application label for any models contained in the signature. database (unicode, optional): The name of the database to execute on. Returns: list of unicode: The list of executed SQL statements for the test. """ with ensure_test_db(model_entries=six.iteritems(start_sig), app_label=app_label, database=database): # Set the app cache to the end state. generate_sql will depend on # this state. register_app_models(app_label, six.iteritems(end_sig), reset=True) # Execute and output the SQL for the test. sql = generate_sql_func() sql_out = write_sql(sql, database) execute_transaction(sql, database) return sql_out
def execute_transaction(sql, output=False, database='default'): "A transaction wrapper for executing a list of SQL statements" my_connection = connection out_sql = [] if not database: database = DEFAULT_DB_ALIAS my_connection = connections[database] try: with atomic(using=database): cursor = my_connection.cursor() # Perform the SQL if output: out_sql.extend(write_sql(sql, database)) execute_sql(cursor, sql, database) except Exception, e: logging.error('Error executing SQL %s: %s' % (sql, e)) raise
# Now run the simulation, which will modify the # signatures try: mutation.simulate(app_label, database_sig, database) except CannotSimulate: simulated = False new_evolutions.extend( Evolution(app_label=app_label, label=label) for label in evolutions) if not execute: if compile_sql: write_sql(app_sql, database) else: print '#----- Evolution for %s' % app_label print 'from django_evolution.mutations import *' print 'from django.db import models' print print 'MUTATIONS = [' print ' ', print ',\n '.join(unicode(m) for m in mutations) print ']' print '#----------------------' sql.extend(app_sql) else: if verbosity > 1: print 'Application %s is up to date' % app_label
database)) # Now run the simulation, which will modify the # signatures try: mutation.simulate(app_label, database_sig, database) except CannotSimulate: simulated = False new_evolutions.extend( Evolution(app_label=app_label, label=label) for label in evolutions) if not execute: if compile_sql: write_sql(app_sql, database) else: print '#----- Evolution for %s' % app_label print 'from django_evolution.mutations import *' print 'from django.db import models' print print 'MUTATIONS = [' print ' ', print ',\n '.join(unicode(m) for m in mutations) print ']' print '#----------------------' sql.extend(app_sql) else: if verbosity > 1: print 'Application %s is up to date' % app_label
for mutation in mutations: # Only compile SQL if we want to show it if compile_sql or execute: app_sql.extend(mutation.mutate(app_label, database_sig)) # Now run the simulation, which will modify the signatures try: mutation.simulate(app_label, database_sig) except CannotSimulate: simulated = False new_evolutions.extend(Evolution(app_label=app_label, label=label) for label in evolutions) if not execute: if compile_sql: write_sql(app_sql) else: print '#----- Evolution for %s' % app_label print 'from django_evolution.mutations import *' print 'from django.db import models' print print 'MUTATIONS = [' print ' ', print ',\n '.join(unicode(m) for m in mutations) print ']' print '#----------------------' sql.extend(app_sql) else: if verbosity > 1: print 'Application %s is up to date' % app_label
def execute_test_sql(start, end, sql, debug=False, app_label='tests', database='default', database_sig=None, return_sql=False, rescan_indexes=True): """ Execute a test SQL sequence. This method also creates and destroys the database tables required by the models registered against the test application. start and end are the start- and end-point states of the application cache. sql is the list of sql statements to execute. cleanup is a list of extra sql statements required to clean up. This is primarily for any extra m2m tables that were added during a test that won't be cleaned up by Django's sql_delete() implementation. debug is a helper flag. It displays the ALL the SQL that would be executed, (including setup and teardown SQL), and executes the Django-derived setup/teardown SQL. """ out_sql = [] # Set up the initial state of the app cache set_app_test_models(copy.deepcopy(start), app_label=app_label) # Install the initial tables and indicies execute_transaction(sql_create(evo_test, database), output=debug, database=database) if rescan_indexes and database_sig: rescan_indexes_for_database_sig(database_sig, database) create_test_data(get_models(evo_test), database) # Set the app cache to the end state set_app_test_models(copy.deepcopy(end), app_label=app_label) try: if callable(sql): sql = sql() # Execute the test sql if debug: out_sql.extend(write_sql(sql, database)) else: out_sql.extend(execute_transaction(sql, output=True, database=database)) finally: # Cleanup the apps. delete_sql = sql_delete(evo_test, database) if debug: out_sql.append(delete_sql) else: out_sql.extend(execute_transaction(delete_sql, output=False, database=database)) # This is a terrible hack, but it's necessary while we use doctests # and normal unit tests. If we always return the SQL, then the # doctests will expect us to compare the output of that (along with the # print statements). # # Down the road, everything should be redone to be standard unit tests, # and then we can just compare the returned SQL statements instead of # dealing with anything on stdout. if return_sql: return out_sql else: return None
if compile_sql or execute: app_sql.extend( mutation.mutate(app_label, database_sig)) # Now run the simulation, which will modify the signatures try: mutation.simulate(app_label, database_sig) except CannotSimulate: simulated = False new_evolutions.extend( Evolution(app_label=app_label, label=label) for label in evolutions) if not execute: if compile_sql: write_sql(app_sql) else: print '#----- Evolution for %s' % app_label print 'from django_evolution.mutations import *' print 'from django.db import models' print print 'MUTATIONS = [' print ' ', print ',\n '.join(unicode(m) for m in mutations) print ']' print '#----------------------' sql.extend(app_sql) else: if verbosity > 1: print 'Application %s is up to date' % app_label