def run_forwards(app, migrations, fake=False, db_dry_run=False, silent=False): """ Runs the specified migrations forwards, in order. """ for migration in migrations: app_name = get_app_name(app) if not silent: print " > %s: %s" % (app_name, migration) klass = get_migration(app, migration) if fake: if not silent: print " (faked)" else: if db_dry_run: db.dry_run = True db.start_transaction() try: klass().forwards() db.execute_deferred_sql() except: db.rollback_transaction() raise else: db.commit_transaction() if not db_dry_run: # Record us as having done this record = MigrationHistory.for_migration(app_name, migration) record.applied = datetime.datetime.utcnow() record.save()
def _create_table_and_fields(model_class): """ creates a table and fields """ fields = [(f.name, f) for f in model_class._meta.local_fields] table_name = model_class._meta.db_table db.create_table(table_name, fields) db.execute_deferred_sql()
def add_necessary_db_columns(model_class): """ Creates new table or relevant columns as necessary based on the model_class. No columns or data are renamed or removed. This is available in case a database exception occurs. """ db.start_transaction() # Create table if missing create_db_table(model_class) # Add field columns if missing table_name = model_class._meta.db_table fields = _get_fields(model_class) db_column_names = [row[0] for row in connection.introspection.get_table_description(connection.cursor(), table_name)] for field_name, field in fields: if field.column not in db_column_names: logger.debug("Adding field '%s' to table '%s'" % (field_name, table_name)) db.add_column(table_name, field_name, field) # Some columns require deferred SQL to be run. This was collected # when running db.add_column(). db.execute_deferred_sql() db.commit_transaction()
def test_alter_constraints(self): """ Tests that going from a PostiveIntegerField to an IntegerField drops the constraint on the database. """ # Make the test table db.create_table("test_alterc", [ ('num', models.PositiveIntegerField()), ]) db.execute_deferred_sql() # Add in some test values db.execute("INSERT INTO test_alterc (num) VALUES (1)") db.execute("INSERT INTO test_alterc (num) VALUES (2)") # Ensure that adding a negative number is bad db.commit_transaction() db.start_transaction() try: db.execute("INSERT INTO test_alterc (num) VALUES (-3)") except: db.rollback_transaction() else: self.fail( "Could insert a negative integer into a PositiveIntegerField.") # Alter it to a normal IntegerField db.alter_column("test_alterc", "num", models.IntegerField()) db.execute_deferred_sql() # It should now work db.execute("INSERT INTO test_alterc (num) VALUES (-3)") db.delete_table("test_alterc") # We need to match up for tearDown db.start_transaction()
def test_alter_constraints(self): """ Tests that going from a PostiveIntegerField to an IntegerField drops the constraint on the database. """ # Make the test table db.create_table("test_alterc", [ ('num', models.PositiveIntegerField()), ]) db.execute_deferred_sql() # Add in some test values db.execute("INSERT INTO test_alterc (num) VALUES (1)") db.execute("INSERT INTO test_alterc (num) VALUES (2)") # Ensure that adding a negative number is bad db.commit_transaction() db.start_transaction() try: db.execute("INSERT INTO test_alterc (num) VALUES (-3)") except: db.rollback_transaction() else: self.fail("Could insert a negative integer into a PositiveIntegerField.") # Alter it to a normal IntegerField db.alter_column("test_alterc", "num", models.IntegerField()) db.execute_deferred_sql() # It should now work db.execute("INSERT INTO test_alterc (num) VALUES (-3)") db.delete_table("test_alterc") # We need to match up for tearDown db.start_transaction()
def add_necessary_db_columns(model_class): """ Cria nova tabela ou colunas pertinentes, se necessário com base no model_class. Sem colunas ou dados são renomeados ou removidos. Esta opção está disponível no caso de uma exceção de banco de dados ocorre. """ db.start_transaction() # Create table if missing create_db_table(model_class) # Add field columns if missing table_name = model_class._meta.db_table fields = _get_fields(model_class) db_column_names = [row[0] for row in connection.introspection.get_table_description(connection.cursor(), table_name)] for field_name, field in fields: if field.column not in db_column_names: logger.debug("Adding field '%s' to table '%s'" % (field_name, table_name)) db.add_column(table_name, field_name, field) # Algumas colunas necessitam de SQL adiada para ser executado. Este foi recolhido # Durante a execução db.add_column (). db.execute_deferred_sql() db.commit_transaction()
def createTable(self): """ Sets up the database table using self.field_list """ if not self.field_list: self._getModelFieldList() if not transaction.is_managed(): db.start_transaction() db.create_table(self._tname, tuple(self.field_list)) # Executing deferred SQL, after correcting the CREATE INDEX statements deferred_sql = [] for stmt in db.deferred_sql: deferred_sql.append(re.sub('^CREATE INDEX \"customforms\".', 'CREATE INDEX ', stmt)) db.deferred_sql = deferred_sql db.execute_deferred_sql() db.commit_transaction() else: db.create_table(self._tname, tuple(self.field_list)) # Executing deferred SQL, after correcting the CREATE INDEX statements deferred_sql = [] for stmt in db.deferred_sql: deferred_sql.append(re.sub('^CREATE INDEX \"customforms\".', 'CREATE INDEX ', stmt)) db.deferred_sql = deferred_sql db.execute_deferred_sql()
def test_change_foreign_key_target(self): # Tables for FK to target User = db.mock_model(model_name='User', db_table='auth_user', db_tablespace='', pk_field_name='id', pk_field_type=models.AutoField, pk_field_args=[], pk_field_kwargs={}) db.create_table("test_fk_changed_target", [ ('eggs', models.IntegerField(primary_key=True)), ]) Egg = db.mock_model(model_name='Egg', db_table='test_fk_changed_target', db_tablespace='', pk_field_name='eggs', pk_field_type=models.AutoField, pk_field_args=[], pk_field_kwargs={}) # Table with a foreign key to the wrong table db.create_table("test_fk_changing", [ ('egg', models.ForeignKey(User, null=True)), ]) db.execute_deferred_sql() # Change foreign key pointing db.alter_column("test_fk_changing", "egg_id", models.ForeignKey(Egg, null=True)) db.execute_deferred_sql() # Test that it is pointing at the right table now try: non_user_id = db.execute("SELECT MAX(id) FROM auth_user")[0][0] + 1 except (TypeError, IndexError): # Got a "None" or no records, treat as 0 non_user_id = 17 db.execute("INSERT INTO test_fk_changed_target (eggs) VALUES (%s)", [non_user_id]) db.execute("INSERT INTO test_fk_changing (egg_id) VALUES (%s)", [non_user_id]) db.commit_transaction() db.start_transaction() # The test framework expects tests to end in transaction
def test_primary_key_implicit(self): """ Tests changing primary key implicitly. """ # This is ONLY important for SQLite. It's not a feature we support, but # not implementing it means SQLite fails (due to the table-copying weirdness). if db.backend_name != "sqlite3": return db.create_table("test_pki", [ ('id', models.IntegerField(primary_key=True)), ('new_pkey', models.IntegerField()), ('eggs', models.IntegerField(unique=True)), ]) db.execute_deferred_sql() # Remove the default primary key, and make eggs it db.alter_column("test_pki", "id", models.IntegerField()) db.alter_column("test_pki", "new_pkey", models.IntegerField(primary_key=True)) # Try inserting a now-valid row pair db.execute( "INSERT INTO test_pki (id, new_pkey, eggs) VALUES (1, 2, 3)") db.execute( "INSERT INTO test_pki (id, new_pkey, eggs) VALUES (1, 3, 4)") db.delete_table("test_pki")
def add_necessary_db_columns(model_class): ''' Takes a Django model class and creates relevant columns as necessary based on the model_class. No columns or data are renamed or removed. This is available in case a database exception occurs. ''' db.start_transaction() # Add field columns if missing table_name = model_class._meta.db_table fields = _get_fields(model_class) db_column_names = [row[0] for row in connection.introspection.get_table_description(connection.cursor(), table_name)] for field_name, field in fields: if field.column not in db_column_names: try: db.add_column(table_name, field_name, field) except ValueError: field.null=True db.add_column(table_name, field_name, field) # Some columns require deferred SQL to be run. This was collected # when running db.add_column(). db.execute_deferred_sql() db.commit_transaction()
def add_necessary_db_columns(model_class): """ Creates new table or relevant columns as necessary based on the model_class. No columns or data are renamed or removed. This is available in case a database exception occurs. """ db.start_transaction() # Create table if missing create_db_table(model_class) # Add field columns if missing table_name = model_class._meta.db_table fields = _get_fields(model_class) db_column_names = [ row[0] for row in connection.introspection.get_table_description( connection.cursor(), table_name) ] for field_name, field in fields: if field.column not in db_column_names: logger.debug("Adding field '%s' to table '%s'" % (field_name, table_name)) db.add_column(table_name, field_name, field) # Some columns require deferred SQL to be run. This was collected # when running db.add_column(). db.execute_deferred_sql() db.commit_transaction()
def test_primary_key(self): """ Test the primary key operations """ # SQLite backend doesn't support this yet. if db.backend_name == "sqlite3": return db.create_table( "test_pk", [ ("id", models.IntegerField(primary_key=True)), ("new_pkey", models.IntegerField()), ("eggs", models.IntegerField(unique=True)), ], ) db.execute_deferred_sql() # Remove the default primary key, and make eggs it db.drop_primary_key("test_pk") db.create_primary_key("test_pk", "new_pkey") # Try inserting a now-valid row pair db.execute("INSERT INTO test_pk (id, new_pkey, eggs) VALUES (1, 2, 3)") db.execute("INSERT INTO test_pk (id, new_pkey, eggs) VALUES (1, 3, 4)") db.delete_table("test_pk")
def create_table_for_dynamic_class(model_class): fields = [(f.name, f) for f in model_class._meta.local_fields] table_name = model_class._meta.db_table db.create_table(table_name, fields) # some fields (eg GeoDjango) require additional SQL to be executed # Because of the poor Django/GeoDjango support for schemas, we have to manipulate the GeoDjango sql here so that the table is resolved to the correct schema, sigh if len(table_name.split('.'))==2: schema, table = parse_schema_and_table(table_name) for i, sql in enumerate(db.deferred_sql): # Replace the POSTGIS single argument with two arguments # TODO this stupidly assumes that all deferred sql is POSTGIS # Substitution for '"schema"."table"' to 'schema','table'. This is for AddGeometryColumn db.deferred_sql[i] = re.sub("'{0}'".format(table_name), "'{0}','{1}'".format(schema, table), sql) # Substitution for "schema"."table" to schema.table. This is for CREATE INDEX db.deferred_sql[i] = re.sub("{0}".format(table_name), "{0}.{1}".format(schema, table), db.deferred_sql[i]) # Substitution for "schema"."tableHEX". Some indexes add random hex to the table name inside the double quotes. They may also truncate the table name, so just capture everything between "s # Also truncate to 64 characters the schema name minus the length of the table name, favoring the end of the schema which is most unique db.deferred_sql[i] = re.sub(r'"(".*)"\."(.*") ON', r'\1.\2 ON'.format(schema, table), db.deferred_sql[i]) if string.find(db.deferred_sql[i], 'CREATE INDEX') == 0: subs = db.deferred_sql[i] # Truncate the index name. This could be done more elegantly db.deferred_sql[i] = subs[0:14] + subs[14:string.index(subs, '" ON')][-64:] + subs[string.index(subs, '" ON'):] db.execute_deferred_sql()
def test_add_columns(self): """ Test adding columns """ db.create_table("test_addc", [ ('spam', models.BooleanField(default=False)), ('eggs', models.IntegerField()), ]) # Add a column db.add_column("test_addc", "add1", models.IntegerField(default=3)) User = db.mock_model(model_name='User', db_table='auth_user', db_tablespace='', pk_field_name='id', pk_field_type=models.AutoField, pk_field_args=[], pk_field_kwargs={}) # insert some data so we can test the default value of the added fkey db.execute( "INSERT INTO test_addc (spam, eggs, add1) VALUES (%s, 1, 2)", [False]) db.add_column("test_addc", "user", models.ForeignKey(User, null=True)) db.execute_deferred_sql() # try selecting from the user_id column to make sure it was actually created val = db.execute("SELECT user_id FROM test_addc")[0][0] self.assertEquals(val, None) db.delete_column("test_addc", "add1") # make sure adding an indexed field works db.add_column( "test_addc", "add2", models.CharField(max_length=15, db_index=True, default='pi')) db.execute_deferred_sql() db.delete_table("test_addc")
def run_backwards(app, migrations, ignore=[], fake=False, db_dry_run=False, silent=False): """ Runs the specified migrations backwards, in order, skipping those migrations in 'ignore'. """ for migration in migrations: if migration not in ignore: app_name = get_app_name(app) if not silent: print " < %s: %s" % (app_name, migration) klass = get_migration(app, migration) if fake: if not silent: print " (faked)" else: if db_dry_run: db.dry_run = True db.start_transaction() try: klass().backwards() db.execute_deferred_sql() except: db.rollback_transaction() raise else: db.commit_transaction() if not db_dry_run: # Record us as having not done this record = MigrationHistory.for_migration(app_name, migration) record.delete()
def finish_db_creation(self): """ Exceute deferred SQL after creating several models. MUST BE CALLED after self.create_db_model() """ db.execute_deferred_sql()
def create_tables_for_dynamic_classes(*model_classes): """ Creates the table for the dynamic model class if needed :param model_classes: 0 or more model classes for which to create a table :return: """ for model_class in model_classes: if dynamic_model_table_exists(model_class): continue #info = "Model class table {model_class} doesn't exist -- creating it \n" #logger.debug(info.format(model_class=model_class._meta.db_table)) fields = [(f.name, f) for f in model_class._meta.local_fields] table_name = model_class._meta.db_table db.create_table(table_name, fields) # some fields (eg GeoDjango) require additional SQL to be executed # Because of the poor Django/GeoDjango support for schemas, we have to manipulate the GeoDjango sql here so that the table is resolved to the correct schema, sigh if len(table_name.split('.')) == 2: schema, table = parse_schema_and_table(table_name) for i, sql in enumerate(db.deferred_sql): # Replace the POSTGIS single argument with two arguments # TODO this stupidly assumes that all deferred sql is POSTGIS # Substitution for '"schema"."table"' to 'schema','table'. This is for AddGeometryColumn db.deferred_sql[i] = re.sub( "'{0}'".format(table_name), "'{0}','{1}'".format(schema, table), sql) # Substitution for "schema"."table" to schema.table. This is for CREATE INDEX db.deferred_sql[i] = re.sub("{0}".format(table_name), "{0}.{1}".format(schema, table), db.deferred_sql[i]) # Substitution for "schema"."tableHEX". Some indexes add random hex to the table name inside the double quotes. They may also truncate the table name, so just capture everything between "s # Also truncate to 64 characters the schema name minus the length of the table name, favoring the end of the schema which is most unique db.deferred_sql[i] = re.sub(r'"(".*)"\."(.*") ON', r'\1.\2 ON'.format(schema, table), db.deferred_sql[i]) # Last ditch effort to remove extra " when we can't match generated index db.deferred_sql[i] = re.sub(r'""', r'"', db.deferred_sql[i]) if string.find(db.deferred_sql[i], 'CREATE INDEX') == 0: subs = db.deferred_sql[i] # Truncate the index name. This could be done more elegantly # db.deferred_sql[i] = subs[0:14] + subs[14:string.index(subs, '" ON')][-63:] + subs[string.index(subs, '" ON'):] db.deferred_sql[i] = subs[0:14] + table + '_' + re.findall( r'"([^"]*)"', subs)[1] + subs[string.index(subs, '" ON'):] try: db.execute_deferred_sql() except Exception, e: raise Exception( "The table {table_name} was not created. Original exception: {message}. Deferred sql calls: {sql}" .format(table_name=model_class._meta.db_table, message=e.message, sql='\n'.join(db.deferred_sql))) # TODO I don't know if or when this is needed. if transaction.is_managed(): transaction.commit()
def create_db_structure(self, metadata_definition): ''' as seen in http://dynamic-models.readthedocs.org/en/latest/topics/database-migration.html#topics-database-migration ''' fields = [(f.name, f) for f in metadata_definition._meta.local_fields] table_name = metadata_definition._meta.db_table db.create_table(table_name, fields) db.execute_deferred_sql() db.send_create_signal(metadata_definition._meta.app_label, metadata_definition.__name__)
def test_delete_fk_column(self): main_table = 'test_drop_foreign' ref_table = 'test_df_ref' self._create_foreign_tables(main_table, ref_table) db.execute_deferred_sql() constraints = db._find_foreign_constraints(main_table, 'foreign_id') self.assertEquals(len(constraints), 1) db.delete_column(main_table, 'foreign_id') constraints = db._find_foreign_constraints(main_table, 'foreign_id') self.assertEquals(len(constraints), 0) db.delete_table(main_table) db.delete_table(ref_table)
def test_constraint_references(self): """Tests that referred table is reported accurately""" main_table = 'test_cns_ref' reference_table = 'test_cr_foreign' db.start_transaction() self._create_foreign_tables(main_table, reference_table) db.execute_deferred_sql() constraint = db._find_foreign_constraints(main_table, 'foreign_id')[0] references = db._lookup_constraint_references(main_table, constraint) self.assertEquals((reference_table, 'id'), references) db.delete_table(main_table) db.delete_table(reference_table)
def run_migration(self, migration): migration_function = self.direction(migration) db.start_transaction() try: migration_function() db.execute_deferred_sql() except: db.rollback_transaction() if not db.has_ddl_transactions: print self.run_migration_error(migration) raise else: db.commit_transaction()
def test_recursive_foreign_key_delete(self): """ Test that recursive foreign keys are deleted correctly (see #1065) """ Test = db.mock_model(model_name='Test', db_table='test_rec_fk_del', db_tablespace='', pk_field_name='id', pk_field_type=models.AutoField, pk_field_args=[]) db.create_table('test_rec_fk_del', [ ('id', models.AutoField(primary_key=True, auto_created=True)), ('fk', models.ForeignKey(Test)), ]) db.execute_deferred_sql() db.delete_foreign_key('test_rec_fk_del', 'fk_id')
def test_foreign_keys(self): """ Tests foreign key creation, especially uppercase (see #61) """ Test = db.mock_model(model_name='Test', db_table='test5a', db_tablespace='', pk_field_name='ID', pk_field_type=models.AutoField, pk_field_args=[]) db.create_table("test5a", [('ID', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True))]) db.create_table("test5b", [ ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), ('UNIQUE', models.ForeignKey(Test)), ]) db.execute_deferred_sql()
def test_reverse_column_constraint(self): """Tests that referred column in a foreign key (ex. id) is found""" main_table = 'test_reverse_ref' reference_table = 'test_rr_foreign' db.start_transaction() self._create_foreign_tables(main_table, reference_table) db.execute_deferred_sql() inverse = db._lookup_reverse_constraint(reference_table, 'id') (cname, rev_table, rev_column) = inverse[0] self.assertEquals(main_table, rev_table) self.assertEquals('foreign_id', rev_column) db.delete_table(main_table) db.delete_table(reference_table)
def test_make_foreign_key_null(self): # Table for FK to target User = db.mock_model(model_name='User', db_table='auth_user', db_tablespace='', pk_field_name='id', pk_field_type=models.AutoField, pk_field_args=[], pk_field_kwargs={}) # Table with no foreign key db.create_table("test_make_fk_null", [ ('eggs', models.IntegerField()), ('foreik', models.ForeignKey(User)) ]) db.execute_deferred_sql() # Make the FK null db.alter_column("test_make_fk_null", "foreik_id", models.ForeignKey(User, null=True)) db.execute_deferred_sql()
def test_add_unique_fk(self): """ Test adding a ForeignKey with unique=True or a OneToOneField """ db.create_table("test_add_unique_fk", [ ('spam', models.BooleanField(default=False)) ]) db.add_column("test_add_unique_fk", "mock1", models.ForeignKey(db.mock_model('User', 'auth_user'), null=True, unique=True)) db.add_column("test_add_unique_fk", "mock2", models.OneToOneField(db.mock_model('User', 'auth_user'), null=True)) db.execute_deferred_sql() db.delete_table("test_add_unique_fk")
def get(self, *args, **kwargs): try: #db.start_transaction() # Delete old RetrvScheme, clear data db.delete_table(RetrvPatent._meta.db_table) RetrvPatentField.objects.all().delete() # Add builtin field for field in BuiltinRetrvField.objects.filter(scheme__current=True).order_by('sort'): RetrvPatentField( field_name = field.field_name, field_label = Patent._meta.get_field(field.field_name).verbose_name, display = field.display, retrieve = field.retrieve, type = field.type, sort = field.sort).save() for field in CustomizedRetrvField.objects.filter(scheme__current=True).order_by('sort'): RetrvPatentField( field_name = field.field.field_name, field_label = field.field.field_label, display = field.display, retrieve = field.retrieve, type = field.type, sort = field.sort).save() # Recreate RetrvPatent table fields = [(f.name, f) for f in RetrvPatent._meta.local_fields] db.create_table(RetrvPatent._meta.db_table, fields) db.execute_deferred_sql() # Export Patents for patent in Patent.objects.all(): target = RetrvPatent() for field in BuiltinRetrvField.objects.filter(scheme__current=True).order_by('sort'): setattr(target, field.field_name, getattr(patent, field.field_name)) for extfield in PatentExtField.objects.filter(patent=patent): if hasattr(target, extfield.type.field_name): setattr(target, extfield.type.field_name, extfield.value) print target target.save() # Commit transaction #db.commit_transaction() except: #db.rollback_transaction() messages.error(self.request, u"导出失败") return HttpResponseRedirect(reverse_lazy('patent-retrvscheme')) messages.success(self.request, u"成功导出%d条记录至专利检索系统"%Patent.objects.all().count()) return HttpResponseRedirect(reverse_lazy('patent-retrvscheme'))
def test_text_to_char(self): """ On Oracle, you can't simply ALTER TABLE MODIFY a textfield to a charfield """ value = "kawabanga" db.create_table("test_text_to_char", [ ('textcol', models.TextField()), ]) db.execute_deferred_sql() db.execute("INSERT INTO test_text_to_char VALUES (%s)", [value]) db.alter_column("test_text_to_char", "textcol", models.CharField(max_length=100)) db.execute_deferred_sql() after = db.execute("select * from test_text_to_char")[0][0] self.assertEqual(value, after, "Change from text to char altered value [ %r != %r ]" % (value, after))
def test_text_to_char(self): """ On Oracle, you can't simply ALTER TABLE MODIFY a textfield to a charfield """ value = "kawabanga" db.create_table("test_text_to_char", [ ('textcol', models.TextField()), ]) db.execute_deferred_sql() db.execute("INSERT INTO test_text_to_char VALUES (%s)", [value]) db.alter_column("test_text_to_char", "textcol", models.CharField(max_length=100)) db.execute_deferred_sql() after = db.execute("select * from test_text_to_char")[0][0] self.assertEqual(value, after, "Change from text to char altered value [ %s != %s ]" % (`value`,`after`))
def test_datetime_default(self): """ Test that defaults are correctly not created for datetime columns """ end_of_world = datetime.datetime(2012, 12, 21, 0, 0, 1) try: from django.utils import timezone except ImportError: pass else: from django.conf import settings if getattr(settings, 'USE_TZ', False): end_of_world = end_of_world.replace(tzinfo=timezone.utc) db.create_table("test_datetime_def", [ ('col0', models.IntegerField(null=True)), ('col1', models.DateTimeField(default=end_of_world)), ('col2', models.DateTimeField(null=True)), ]) db.execute_deferred_sql() # insert a row db.execute( "INSERT INTO test_datetime_def (col0, col1, col2) values (null,%s,null)", [end_of_world]) db.alter_column("test_datetime_def", "col2", models.DateTimeField(default=end_of_world)) db.add_column("test_datetime_def", "col3", models.DateTimeField(default=end_of_world), keep_default=False) db.execute_deferred_sql() db.commit_transaction() # In the single existing row, we now expect col1=col2=col3=end_of_world... db.start_transaction() ends = db.execute("select col1,col2,col3 from test_datetime_def")[0] self.failUnlessEqual(len(ends), 3) for e in ends: self.failUnlessEqual(e, end_of_world) db.commit_transaction() # ...but there should not be a default in the database for col1 or col3 for cols in ["col1,col2", "col2,col3"]: db.start_transaction() statement = "insert into test_datetime_def (col0,%s) values (null,%%s,%%s)" % cols self.assertRaises(IntegrityError, db.execute, statement, [end_of_world, end_of_world]) db.rollback_transaction() db.start_transaction( ) # To preserve the sanity and semantics of this test class
def forwards(self, orm): # Adding field 'User._unit_rows' db.add_column(u'accounts_user', '_unit_rows', self.gf('django.db.models.fields.SmallIntegerField')(default=9, db_column='unit_rows'), keep_default=False) if "pootle_app_pootleprofile" in connection.introspection.table_names(): print("Importing old profile data") db.execute("""UPDATE accounts_user SET unit_rows = (SELECT unit_rows FROM pootle_app_pootleprofile WHERE pootle_app_pootleprofile.user_id = accounts_user.id) """) # Adding M2M table for field alt_src_langs on 'User' old_m2m_table_name = db.shorten_name(u'pootle_app_pootleprofile_alt_src_langs') m2m_table_name = db.shorten_name(u'accounts_user_alt_src_langs') if old_m2m_table_name in connection.introspection.table_names(): print("Importing alt_src_langs data. If you have a lot of users, this can take a while.") # Add the column db.add_column(old_m2m_table_name, "user", self.gf("django.db.models.fields.related.ForeignKey")(to=orm[AUTH_USER_MODEL], null=True), keep_default=False) # Update it with profile.user_id db.execute("""UPDATE %(t)s SET user_id = (select pootle_app_pootleprofile.user_id FROM pootle_app_pootleprofile WHERE pootle_app_pootleprofile.id = %(t)s.pootleprofile_id) """ % {"t": old_m2m_table_name}) # Set the new user_id column to NOT NULL. Doesn't work in sqlite. if db.backend_name == "postgresql": db.execute("ALTER TABLE %s ALTER COLUMN user_id SET NOT NULL" % (old_m2m_table_name)) elif db.backend_name == "mysql": # disgusting... db.execute("ALTER TABLE %s MODIFY user_id INTEGER NOT NULL" % (old_m2m_table_name)) print("Renaming %r to %r" % (old_m2m_table_name, m2m_table_name)) # We need to execute some deferred SQL because south breaks on mysql if this is run # after we rename the column db.execute_deferred_sql() db.rename_table(old_m2m_table_name, m2m_table_name) else: print("%r does not exist. Creating table %r instead" % (old_m2m_table_name, m2m_table_name)) db.create_table(m2m_table_name, ( ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), ('user', models.ForeignKey(orm[u'accounts.user'], null=False)), ('language', models.ForeignKey(orm[u'pootle_language.language'], null=False)) )) print("Creating unique between %r.user_id<->%r.language_id" % (m2m_table_name, m2m_table_name)) db.create_unique(m2m_table_name, ['user_id', 'language_id'])
def test_column_constraint(self): """ Tests that the value constraint of PositiveIntegerField is enforced on the database level. """ if not db.has_check_constraints: return db.create_table("test_column_constraint", [ ('spam', models.PositiveIntegerField()), ]) db.execute_deferred_sql() # Make sure we can't insert negative values db.commit_transaction() db.start_transaction() try: db.execute("INSERT INTO test_column_constraint VALUES (-42)") except: pass else: self.fail( "Could insert a negative value into a PositiveIntegerField.") db.rollback_transaction() # remove constraint db.alter_column("test_column_constraint", "spam", models.IntegerField()) # make sure the insertion works now db.execute('INSERT INTO test_column_constraint VALUES (-42)') db.execute('DELETE FROM test_column_constraint') # add it back again db.alter_column("test_column_constraint", "spam", models.PositiveIntegerField()) # it should fail again db.start_transaction() try: db.execute("INSERT INTO test_column_constraint VALUES (-42)") except: pass else: self.fail( "Could insert a negative value after changing an IntegerField to a PositiveIntegerField." ) db.rollback_transaction() db.delete_table("test_column_constraint") db.start_transaction()
def test_alter_unique(self): """ Tests that unique constraints are properly created and deleted when altering columns. """ db.create_table("test_alter_unique", [ ('spam', models.IntegerField()), ('eggs', models.IntegerField(unique=True)), ]) db.execute_deferred_sql() # Make sure the unique constraint is created db.execute('INSERT INTO test_alter_unique VALUES (0, 42)') db.commit_transaction() db.start_transaction() try: db.execute("INSERT INTO test_alter_unique VALUES (1, 42)") except: pass else: self.fail( "Could insert the same integer twice into a field with unique=True." ) db.rollback_transaction() # remove constraint db.alter_column("test_alter_unique", "eggs", models.IntegerField()) # make sure the insertion works now db.execute('INSERT INTO test_alter_unique VALUES (1, 42)') # add it back again db.execute('DELETE FROM test_alter_unique WHERE spam=1') db.alter_column("test_alter_unique", "eggs", models.IntegerField(unique=True)) # it should fail again db.start_transaction() try: db.execute("INSERT INTO test_alter_unique VALUES (1, 42)") except: pass else: self.fail("Unique constraint not created during alter_column()") db.rollback_transaction() # Delete the unique index/constraint if db.backend_name != "sqlite3": db.delete_unique("test_alter_unique", ["eggs"]) db.delete_table("test_alter_unique") db.start_transaction()
def test_char_to_text(self): """ On Oracle, you can't simply ALTER TABLE MODIFY a charfield to a textfield either """ value = "agnabawak" db.create_table("test_char_to_text", [ ('textcol', models.CharField(max_length=100)), ]) db.execute_deferred_sql() db.execute("INSERT INTO test_char_to_text VALUES (%s)", [value]) db.alter_column("test_char_to_text", "textcol", models.TextField()) db.execute_deferred_sql() after = db.execute("select * from test_char_to_text")[0][0] after = unicode(after) # Oracle text fields return a sort of lazy string -- force evaluation self.assertEqual(value, after, "Change from char to text altered value [ %s != %s ]" % (`value`,`after`))
def test_rename_fk_column(self): if db.backend_name != "mysql": return main_table = 'test_rename_foreign' ref_table = 'test_rf_ref' self._create_foreign_tables(main_table, ref_table) db.execute_deferred_sql() constraints = db._find_foreign_constraints(main_table, 'foreign_id') self.assertEquals(len(constraints), 1) db.rename_column(main_table, 'foreign_id', 'reference_id') db.execute_deferred_sql() #Create constraints constraints = db._find_foreign_constraints(main_table, 'reference_id') self.assertEquals(len(constraints), 1) db.delete_table(main_table) db.delete_table(ref_table)
def test_char_to_text(self): """ On Oracle, you can't simply ALTER TABLE MODIFY a charfield to a textfield either """ value = "agnabawak" db.create_table("test_char_to_text", [ ('textcol', models.CharField(max_length=100)), ]) db.execute_deferred_sql() db.execute("INSERT INTO test_char_to_text VALUES (%s)", [value]) db.alter_column("test_char_to_text", "textcol", models.TextField()) db.execute_deferred_sql() after = db.execute("select * from test_char_to_text")[0][0] after = text_type(after) # Oracle text fields return a sort of lazy string -- force evaluation self.assertEqual(value, after, "Change from char to text altered value [ %r != %r ]" % (value, after))
def get(self, *args, **kwargs): try: db.start_transaction() # Delete old RetrvScheme, clear data db.delete_table(RetrvSoftware._meta.db_table) RetrvSoftwareField.objects.all().delete() # Add builtin field for field in BuiltinRetrvField.objects.filter(scheme__current=True).order_by('sort'): RetrvSoftwareField( field_name = field.field_name, field_label = Software._meta.get_field(field.field_name).verbose_name, display = field.display, retrieve = field.retrieve, sort = field.sort).save() for field in CustomizedRetrvField.objects.filter(scheme__current=True).order_by('sort'): RetrvSoftwareField( field_name = field.field.field_name, field_label = field.field.field_label, display = field.display, retrieve = field.retrieve, sort = field.sort).save() # Recreate RetrvSoftware table fields = [(f.name, f) for f in RetrvSoftware._meta.local_fields] db.create_table(RetrvSoftware._meta.db_table, fields) db.execute_deferred_sql() # Export Softwares for scr in Software.objects.all(): target = RetrvSoftware() for field in BuiltinRetrvField.objects.filter(scheme__current=True).order_by('sort'): setattr(target, field.field_name, getattr(scr, field.field_name)) for extfield in SoftwareExtField.objects.filter(scr=scr): if hasattr(target, extfield.type.field_name): setattr(target, extfield.type.field_name, extfield.value) print target target.save() # Commit transaction db.commit_transaction() except: db.rollback_transaction() return HttpResponse('Failed') return HttpResponse('OK')
def test_constraint_references(self): """Tests that referred table is reported accurately""" if db.backend_name != "mysql": return main_table = 'test_cns_ref' reference_table = 'test_cr_foreign' db.start_transaction() self._create_foreign_tables(main_table, reference_table) db.execute_deferred_sql() constraint = db._find_foreign_constraints(main_table, 'foreign_id')[0] constraint_name = 'foreign_id_refs_id_%x' % (abs(hash((main_table, reference_table)))) self.assertEquals(constraint_name, constraint) references = db._lookup_constraint_references(main_table, constraint) self.assertEquals((reference_table, 'id'), references) db.delete_table(main_table) db.delete_table(reference_table)
def test_primary_key_implicit(self): """ Tests that changing primary key implicitly fails. """ db.create_table("test_pki", [ ('id', models.IntegerField(primary_key=True)), ('new_pkey', models.IntegerField()), ('eggs', models.IntegerField(unique=True)), ]) db.execute_deferred_sql() # Fiddle with alter_column to attempt to make it remove the primary key db.alter_column("test_pki", "id", models.IntegerField()) db.alter_column("test_pki", "new_pkey", models.IntegerField(primary_key=True)) # Try inserting a should-be-valid row pair db.execute("INSERT INTO test_pki (id, new_pkey, eggs) VALUES (1, 2, 3)") db.execute("INSERT INTO test_pki (id, new_pkey, eggs) VALUES (2, 2, 4)") db.delete_table("test_pki")
def test_constraint_references(self): """Tests that referred table is reported accurately""" if db.backend_name != "mysql": return main_table = 'test_cns_ref' reference_table = 'test_cr_foreign' db.start_transaction() self._create_foreign_tables(main_table, reference_table) db.execute_deferred_sql() constraint = db._find_foreign_constraints(main_table, 'foreign_id')[0] constraint_name = 'foreign_id_refs_id_%x' % (abs( hash((main_table, reference_table)))) self.assertEquals(constraint_name, constraint) references = db._lookup_constraint_references(main_table, constraint) self.assertEquals((reference_table, 'id'), references) db.delete_table(main_table) db.delete_table(reference_table)
def get(self, *args, **kwargs): try: # Delete old RetrvScheme, clear data db.delete_table(self.retrv_model._meta.db_table) self.retrv_field_model.objects.all().delete() # Add builtin field for field in self.builtin_field_model.objects.filter(scheme__current=True).order_by('sort'): self.retrv_field_model( field_name = field.field_name, field_label = self.model._meta.get_field(field.field_name).verbose_name, display = field.display, retrieve = field.retrieve, type = field.type, sort = field.sort).save() for field in self.customized_field_model.objects.filter(scheme__current=True).order_by('sort'): self.retrv_field_model( field_name = field.field.field_name, field_label = field.field.field_label, display = field.display, retrieve = field.retrieve, type = field.type, sort = field.sort).save() # Recreate self.retrv_model table fields = [(f.name, f) for f in self.retrv_model._meta.local_fields] db.create_table(self.retrv_model._meta.db_table, fields) db.execute_deferred_sql() # Export Data for obj in self.model.objects.all(): target = self.retrv_model() for field in self.builtin_field_model.objects.filter(scheme__current=True).order_by('sort'): setattr(target, field.field_name, getattr(obj, field.field_name)) for extfield in self.extfield_model.objects.filter((self.ref_name, obj)): if hasattr(target, extfield.type.field_name): setattr(target, extfield.type.field_name, extfield.value) print target target.save() except: #db.rollback_transaction() messages.error(self.request, u"导出失败") return HttpResponseRedirect(self.retrun_url) messages.success(self.request, u"成功导出%d条记录至检索系统"%self.model.objects.all().count()) return HttpResponseRedirect(self.return_url)
def test_alter_unique(self): """ Tests that unique constraints are not affected when altering columns (that's handled by create_/delete_unique) """ db.create_table("test_alter_unique", [ ('spam', models.IntegerField()), ('eggs', models.IntegerField(unique=True)), ]) db.execute_deferred_sql() # Make sure the unique constraint is created db.execute('INSERT INTO test_alter_unique (spam, eggs) VALUES (0, 42)') db.commit_transaction() db.start_transaction() try: db.execute( "INSERT INTO test_alter_unique (spam, eggs) VALUES (1, 42)") except: pass else: self.fail( "Could insert the same integer twice into a unique field.") db.rollback_transaction() # Alter without unique=True (should not affect anything) db.alter_column("test_alter_unique", "eggs", models.IntegerField()) # Insertion should still fail db.start_transaction() try: db.execute( "INSERT INTO test_alter_unique (spam, eggs) VALUES (1, 42)") except: pass else: self.fail( "Could insert the same integer twice into a unique field after alter_column with unique=False." ) db.rollback_transaction() # Delete the unique index/constraint if db.backend_name != "sqlite3": db.delete_unique("test_alter_unique", ["eggs"]) db.delete_table("test_alter_unique") db.start_transaction()
def test_alter_unique(self): """ Tests that unique constraints are properly created and deleted when altering columns. """ db.create_table("test_alter_unique", [ ('spam', models.IntegerField()), ('eggs', models.IntegerField(unique=True)), ]) db.execute_deferred_sql() # Make sure the unique constraint is created db.execute('INSERT INTO test_alter_unique VALUES (0, 42)') db.commit_transaction() db.start_transaction() try: db.execute("INSERT INTO test_alter_unique VALUES (1, 42)") except: pass else: self.fail("Could insert the same integer twice into a field with unique=True.") db.rollback_transaction() # remove constraint db.alter_column("test_alter_unique", "eggs", models.IntegerField()) # make sure the insertion works now db.execute('INSERT INTO test_alter_unique VALUES (1, 42)') # add it back again db.execute('DELETE FROM test_alter_unique WHERE spam=1') db.alter_column("test_alter_unique", "eggs", models.IntegerField(unique=True)) # it should fail again db.start_transaction() try: db.execute("INSERT INTO test_alter_unique VALUES (1, 42)") except: pass else: self.fail("Unique constraint not created during alter_column()") db.rollback_transaction() # Delete the unique index/constraint if db.backend_name != "sqlite3": db.delete_unique("test_alter_unique", ["eggs"]) db.delete_table("test_alter_unique") db.start_transaction()
def test_renamed_referenced_table(self): """Rename a table referred to in a foreign key""" main_table = 'test_rn_refd_table' ref_table = 'test_rrt_ref' renamed_table = 'test_renamed_ref' self._create_foreign_tables(main_table, ref_table) db.execute_deferred_sql() constraints = db._lookup_reverse_constraint(ref_table) self.assertEquals(len(constraints), 1) db.rename_table(ref_table, renamed_table) db.execute_deferred_sql() #Create constraints constraints = db._find_foreign_constraints(main_table, 'foreign_id') self.assertEquals(len(constraints), 1) (rtable, rcolumn) = db._lookup_constraint_references( main_table, constraints[0]) self.assertEquals(renamed_table, rtable) db.delete_table(main_table) db.delete_table(renamed_table)
def test_primary_key(self): """ Test the primary key operations """ db.create_table("test_pk", [ ('id', models.IntegerField(primary_key=True)), ('new_pkey', models.IntegerField()), ('eggs', models.IntegerField(unique=True)), ]) db.execute_deferred_sql() # Remove the default primary key, and make eggs it db.delete_primary_key("test_pk") db.create_primary_key("test_pk", "new_pkey") # Try inserting a now-valid row pair db.execute("INSERT INTO test_pk (id, new_pkey, eggs) VALUES (1, 2, 3)") db.execute("INSERT INTO test_pk (id, new_pkey, eggs) VALUES (1, 3, 4)") db.delete_table("test_pk")
def test_rename_constrained_table(self): """Renames a table with a foreign key column (towards another table)""" main_table = 'test_rn_table' ref_table = 'test_rt_ref' renamed_table = 'test_renamed_table' self._create_foreign_tables(main_table, ref_table) db.execute_deferred_sql() constraints = db._find_foreign_constraints(main_table, 'foreign_id') self.assertEquals(len(constraints), 1) db.rename_table(main_table, renamed_table) db.execute_deferred_sql() #Create constraints constraints = db._find_foreign_constraints(renamed_table, 'foreign_id') self.assertEquals(len(constraints), 1) (rtable, rcolumn) = db._lookup_constraint_references( renamed_table, constraints[0]) self.assertEquals(rcolumn, 'id') db.delete_table(renamed_table) db.delete_table(ref_table)
def test_add_unique_fk(self): """ Test adding a ForeignKey with unique=True or a OneToOneField """ db.create_table("test_add_unique_fk", [('spam', models.BooleanField(default=False))]) db.add_column( "test_add_unique_fk", "mock1", models.ForeignKey(db.mock_model('User', 'auth_user'), null=True, unique=True)) db.add_column( "test_add_unique_fk", "mock2", models.OneToOneField(db.mock_model('User', 'auth_user'), null=True)) db.execute_deferred_sql() db.delete_table("test_add_unique_fk")
def test_alter_double_indexed_column(self): # Table for FK to target User = db.mock_model(model_name='User', db_table='auth_user', db_tablespace='', pk_field_name='id', pk_field_type=models.AutoField, pk_field_args=[], pk_field_kwargs={}) # Table with no foreign key db.create_table("test_2indexed", [('eggs', models.IntegerField()), ('foreik', models.ForeignKey(User))]) db.create_unique("test_2indexed", ["eggs", "foreik_id"]) db.execute_deferred_sql() # Make the FK null db.alter_column("test_2indexed", "foreik_id", models.ForeignKey(User, null=True)) db.execute_deferred_sql()
def test_index(self): """ Test the index operations """ db.create_table("test3", [ ('SELECT', models.BooleanField(default=False)), ('eggs', models.IntegerField(unique=True)), ]) db.execute_deferred_sql() # Add an index on that column db.create_index("test3", ["SELECT"]) # Add another index on two columns db.create_index("test3", ["SELECT", "eggs"]) # Delete them both db.delete_index("test3", ["SELECT"]) db.delete_index("test3", ["SELECT", "eggs"]) # Delete the unique index/constraint db.delete_unique("test3", ["eggs"]) db.delete_table("test3")