def test_check_constraints(self): """ Constraint checks should raise an IntegrityError when bad data is in the DB. """ with transaction.atomic(): # Create an Article. models.Article.objects.create(headline="Test article", pub_date=datetime.datetime(2010, 9, 4), reporter=self.r) # Retrieve it from the DB a = models.Article.objects.get(headline="Test article") a.reporter_id = 30 with connection.constraint_checks_disabled(): a.save() with self.assertRaises(IntegrityError): connection.check_constraints() transaction.set_rollback(True)
def test_check_constraints(self): """ Constraint checks should raise an IntegrityError when bad data is in the DB. """ with transaction.atomic(): # Create an Article. models.Article.objects.create(headline="Test article", pub_date=datetime.datetime( 2010, 9, 4), reporter=self.r) # Retrive it from the DB a = models.Article.objects.get(headline="Test article") a.reporter_id = 30 with connection.constraint_checks_disabled(): a.save() with self.assertRaises(IntegrityError): connection.check_constraints() transaction.set_rollback(True)
def test_check_constraints(self): """ Constraint checks should raise an IntegrityError when bad data is in the DB. """ with transaction.atomic(): # Create an Article. Article.objects.create( headline="Test article", pub_date=datetime.datetime(2010, 9, 4), reporter=self.r, ) # Retrieve it from the DB a = Article.objects.get(headline="Test article") a.reporter_id = 30 with connection.constraint_checks_disabled(): a.save() try: connection.check_constraints(table_names=[Article._meta.db_table]) except IntegrityError: pass else: self.skipTest("This backend does not support integrity checks.") transaction.set_rollback(True)
def fix_sqlite_for_django_2(self): # We're monkey patching the __exit__ method of DatabaseSchemaEditor because it reenables constraint checking # which we explicitly DO NOT want to do. The problem is that without patching this if multiple tables have # incorrect foreign key constraints you can't fix one at a time - you have to fix both simultaneously (which # Django doesn't support). Fun times. DatabaseSchemaEditor.__exit__ = BaseDatabaseSchemaEditor.__exit__ try: constraint_check = connection.disable_constraint_checking() except: connection.connection = connection.connect() constraint_check = connection.disable_constraint_checking() # Back up the sqlite databases before we start rebuilding things, just in case. # ol2 -> ol3 try: shutil.copyfile("db.sqlite3.ol2", "db.sqlite3.ol3") except FileNotFoundError: pass # old -> ol2 try: shutil.copyfile("db.sqlite3.old", "db.sqlite3.ol2") except FileNotFoundError: pass # (db) -> old shutil.copyfile("db.sqlite3", "db.sqlite3.old") # Because Django 2.0+ now enforces FK checks for Sqlite DBs, if we are missing migrations that would now involve # FK checks we have a serious problem - We can't apply the migrations until the DB is fixed, and we can't fix # the DB until we apply the migrations. The solution is to apply the migrations with FK checks disabled, then # run this script to fix the database. I've created a management command - `migrate_no_fk` - which can handle # the migration. Let's call that now just to ensure that we're in the right state. execute_from_command_line(['manage.py', 'migrate_no_fk']) # Everything should be migrated at this point - Let's continue. # There was some kind of an issue with firmware data specifically - let's delete it all just to be safe try: self.clear_firmware_data() except: print("Unable to clear data!!") # Once that's done, we're going to attempt to loop over all the apps/models and rebuild everything just to be # safe. for app in apps.get_app_configs(): print("Rebuilding app {}...".format(app.verbose_name)) for model in app.get_models(include_auto_created=True): if model._meta.managed and not (model._meta.proxy or model._meta.swapped): for base in model.__bases__: if hasattr(base, '_meta'): base._meta.local_many_to_many = [] model._meta.local_many_to_many = [] with connection.schema_editor() as editor: try: constraint_check = connection.disable_constraint_checking( ) except: connection.connection = connection.connect() constraint_check = connection.disable_constraint_checking( ) print("Rebuilding model {}".format(model)) editor._remake_table(model) print( "Completed app rebuilding - running check_constraints to ensure we're in a consistent state." ) connection.check_constraints() config.SQLITE_OK_DJANGO_2 = True print("Rebuild complete!") return True