Skip to content

Commit

Permalink
refs #134: fix test_alter_size with redshift. Redshift can not decrea…
Browse files Browse the repository at this point in the history
…se the size of a column that have default.
  • Loading branch information
shimizukawa committed Jul 16, 2024
1 parent 9d7dca9 commit d85f51b
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 5 deletions.
10 changes: 9 additions & 1 deletion django_redshift_backend/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -849,13 +849,17 @@ def _get_max_length(field):

old_max_length = _get_max_length(old_field)
new_max_length = _get_max_length(new_field)
decrease_size_with_default = old_default is not None and (
old_max_length > new_max_length
)

# Size is changed
if (
type(old_field) is type(new_field)
and old_max_length is not None
and new_max_length is not None
and old_max_length != new_max_length
and not decrease_size_with_default
):
# if shrink size as `old_field.max_length > new_field.max_length` and
# larger data in database, this change will raise exception.
Expand Down Expand Up @@ -921,7 +925,11 @@ def _get_max_length(field):
fragment = actions.pop(0)

# Type or default is changed?
elif (old_type != new_type) or needs_database_default:
elif (
(old_type != new_type)
or needs_database_default
or decrease_size_with_default
):
fragment, actions = self._alter_column_with_recreate(
model, old_field, new_field
)
Expand Down
47 changes: 43 additions & 4 deletions tests/test_migrations.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,40 @@ def execute(self, sql, params=()):
print('\n'.join(collected_sql))

@postgres_fixture()
def test_alter_size(self):
def test_alter_size_with_nullable(self):
new_state = self.set_up_test_model('test')
operations = [
migrations.AddField(
model_name='Pony',
name='name',
field=models.CharField(max_length=10, verbose_name='name', null=True),
),
migrations.AlterField(
model_name='Pony',
name='name',
field=models.CharField(max_length=20, verbose_name='name', null=True),
),
migrations.AlterField(
model_name='Pony',
name='name',
field=models.CharField(max_length=10, verbose_name='name', null=True),
),
]

with self.collect_sql() as sqls:
self.apply_operations('test', new_state, operations)

self.assertEqual([
# add column
'''ALTER TABLE "test_pony" ADD COLUMN "name" varchar(10) NULL;''',
# increase size
'''ALTER TABLE "test_pony" ALTER COLUMN "name" TYPE varchar(20);''',
# decrease size
'''ALTER TABLE "test_pony" ALTER COLUMN "name" TYPE varchar(10);''',
], sqls)

@postgres_fixture()
def test_alter_size_with_default(self):
new_state = self.set_up_test_model('test')
operations = [
migrations.AddField(
Expand All @@ -48,22 +81,28 @@ def test_alter_size(self):
migrations.AlterField(
model_name='Pony',
name='name',
field=models.CharField(max_length=20, verbose_name='name'),
field=models.CharField(max_length=20, verbose_name='name', default=''),
),
migrations.AlterField(
model_name='Pony',
name='name',
field=models.CharField(max_length=10, verbose_name='name'),
field=models.CharField(max_length=10, verbose_name='name', default=''),
),
]

with self.collect_sql() as sqls:
self.apply_operations('test', new_state, operations)

self.assertEqual([
# add column
'''ALTER TABLE "test_pony" ADD COLUMN "name" varchar(10) DEFAULT '' NOT NULL;''',
# increase size
'''ALTER TABLE "test_pony" ALTER COLUMN "name" TYPE varchar(20);''',
'''ALTER TABLE "test_pony" ALTER COLUMN "name" TYPE varchar(10);''',
# decrease size
'''ALTER TABLE "test_pony" ADD COLUMN "name_tmp" varchar(10) DEFAULT '' NOT NULL;''',
'''UPDATE test_pony SET "name_tmp" = "name" WHERE "name" IS NOT NULL;''',
'''ALTER TABLE test_pony DROP COLUMN "name" CASCADE;''',
'''ALTER TABLE test_pony RENAME COLUMN "name_tmp" TO "name";''',
], sqls)

@postgres_fixture()
Expand Down

0 comments on commit d85f51b

Please sign in to comment.