예제 #1
0
    def rename_column(self, model, old_field, new_field):
        if old_field.column == new_field.column:
            # No Operation
            return []

        qn = self.connection.ops.quote_name
        max_name_length = self.connection.ops.max_name_length()

        sql_result = AlterTableSQLResult(self, model)

        pre_sql, stash = self.stash_field_ref_constraints(model=model,
                                                          replaced_fields={
                                                              old_field:
                                                              new_field,
                                                          })
        sql_result.add_pre_sql(pre_sql)

        sql_result.add_alter_table([{
            'independent':
            True,
            'sql':
            'RENAME COLUMN %s TO %s' %
            (truncate_name(qn(old_field.column), max_name_length),
             truncate_name(qn(new_field.column), max_name_length)),
        }])

        sql_result.add_post_sql(self.restore_field_ref_constraints(stash))

        return sql_result
예제 #2
0
    def get_change_column_type_sql(self, model, old_field, new_field):
        """Return SQL to change the type of a column.

        Version Added:
            2.2

        Args:
            model (type):
                The type of model owning the field.

            old_field (django.db.models.Field):
                The old field.

            new_field (django.db.models.Field):
                The new field.

        Returns:
            django_evolution.sql_result.AlterTableSQLResult:
            The SQL statements for changing the column type.
        """
        connection = self.connection
        qn = connection.ops.quote_name

        schema = self.build_column_schema(
            model=model,
            field=new_field,
            initial=new_field.default,
            skip_null_constraint=True,
            skip_primary_or_unique_constraint=True,
            skip_references=True)
        column_name = schema['name']
        table_name = model._meta.db_table

        sql_result = AlterTableSQLResult(self, model)

        old_field_type = old_field.db_type(connection=connection).lower()
        new_field_type = schema['db_type'].lower()

        was_serial = old_field_type in self.alter_field_type_map
        is_serial = new_field_type in self.alter_field_type_map

        if is_serial:
            # This is a serial field. We will need to change the type and
            # update the sequence. We will also need to choose the actual
            # type to set for the column definition.
            new_field_type = self.alter_field_type_map.get(
                new_field_type, new_field_type)

        alter_type_params = ['TYPE', new_field_type] + schema['definition']

        if not self._are_column_types_compatible(old_field, new_field):
            alter_type_params += [
                'USING',
                '%s::%s' % (column_name, new_field_type),
            ]

        sql_result.add_alter_table([{
            'op':
            'ALTER COLUMN',
            'column':
            column_name,
            'params':
            alter_type_params,
            'sql_params':
            schema['definition_sql_params'],
        }])

        if is_serial:
            # Reset the sequence.
            sequence_name = '%s_%s_seq' % (table_name, column_name)

            sequence_sql_result = AlterTableSQLResult(self, model)
            sequence_sql_result.add_pre_sql([
                'DROP SEQUENCE IF EXISTS %s CASCADE;' % qn(sequence_name),
                'CREATE SEQUENCE %s;' % qn(sequence_name),
            ])
            sequence_sql_result.add_alter_table([{
                'op':
                'ALTER COLUMN',
                'column':
                column_name,
                'params': [
                    'SET',
                    'DEFAULT',
                    "nextval('%s')" % qn(sequence_name),
                ],
            }])
            sequence_sql_result.add_post_sql([
                "SELECT setval('%s', MAX(%s)) FROM %s;" %
                (qn(sequence_name), qn(column_name), qn(table_name)),
                'ALTER SEQUENCE %s OWNED BY %s.%s;' %
                (qn(sequence_name), qn(table_name), qn(column_name)),
            ])

            sql_result.add_post_sql(sequence_sql_result)
        elif was_serial:
            # Drop the old sequence, since we no longer need it.
            sequence_name = '%s_%s_seq' % (table_name, old_field.column)
            sql_result.add_post_sql([
                'DROP SEQUENCE IF EXISTS %s CASCADE;' % qn(sequence_name),
            ])

        return sql_result
예제 #3
0
    def rename_column(self, model, old_field, new_field):
        """Rename the specified column.

        This will rename the column through ``ALTER TABLE .. CHANGE COLUMN``.

        Any constraints on the column will be stashed away before the
        ``ALTER TABLE`` and restored afterward.

        If the column has not actually changed, or it's not a real column
        (a many-to-many relation), then this will return empty statements.

        Args:
            model (type):
                The model representing the table containing the column.

            old_field (django.db.models.Field):
                The old field definition.

            new_field (django.db.models.Field):
                The new field definition.

        Returns:
            django_evolution.db.sql_result.AlterTableSQLResult or list:
            The statements for renaming the column. This may be an empty
            list if the column won't be renamed.
        """
        if old_field.column == new_field.column:
            # No Operation
            return []

        col_type = new_field.db_type(connection=self.connection)

        if col_type is None:
            # Skip ManyToManyFields, because they're not represented as
            # database columns in this table.
            return []

        qn = self.connection.ops.quote_name
        sql_result = AlterTableSQLResult(self, model)

        pre_sql, stash = self.stash_field_ref_constraints(
            model=model,
            replaced_fields={
                old_field: new_field,
            })
        sql_result.add_pre_sql(pre_sql)

        schema = self.build_column_schema(model=model,
                                          field=new_field,
                                          initial=new_field.default)

        alter_table_items = []

        if old_field.primary_key:
            alter_table_items.append('DROP PRIMARY KEY')

        alter_table_items.append(
            'CHANGE COLUMN %s %s'
            % (qn(old_field.column), ' '.join([
                qn(schema['name']),
                schema['db_type'],
            ] + schema['definition'])))

        sql_result.add_alter_table([{
            'sql': ', '.join(alter_table_items),
        }])
        sql_result.add_post_sql(self.restore_field_ref_constraints(stash))

        return sql_result