fix: migration with duplicate renaming of columns in some cases (#395)
* fix: migration with duplicate renaming of columns in some cases * Update var name * fix downgrade sql error * fix test error * docs: update changelog * Add unittest * Move not change line to origin position * Update sort key to make it more frieldly interactive from multi fields rename * refactor: remove puzzle vars * docs: fix PR links in changelog * fix sort key lambda error
This commit is contained in:
parent
7d22518c74
commit
5e8a7c7e91
54
CHANGELOG.md
54
CHANGELOG.md
@ -2,27 +2,46 @@
|
|||||||
|
|
||||||
## 0.8
|
## 0.8
|
||||||
|
|
||||||
### [0.8.1](Unreleased)
|
### [0.8.1]*(Unreleased)*
|
||||||
|
|
||||||
#### Fixed
|
#### Fixed
|
||||||
- fix: add o2o field does not create constraint when migrating. (#396)
|
- fix: add o2o field does not create constraint when migrating. ([#396])
|
||||||
- fix: intermediate table for m2m relation not created. (#394)
|
- Migration with duplicate renaming of columns in some cases. ([#395])
|
||||||
- Migrate add m2m field with custom through generate duplicated table. (#393)
|
- fix: intermediate table for m2m relation not created. ([#394])
|
||||||
- Migrate drop the wrong m2m field when model have multi m2m fields. (#376)
|
- Migrate add m2m field with custom through generate duplicated table. ([#393])
|
||||||
- KeyError raised when removing or renaming an existing model (#386)
|
- Migrate drop the wrong m2m field when model have multi m2m fields. ([#376])
|
||||||
- fix: error when there is `__init__.py` in the migration folder (#272)
|
- KeyError raised when removing or renaming an existing model. ([#386])
|
||||||
- Setting null=false on m2m field causes migration to fail. (#334)
|
- fix: error when there is `__init__.py` in the migration folder. ([#272])
|
||||||
- Fix NonExistentKey when running `aerich init` without `[tool]` section in config file. (#284)
|
- Setting null=false on m2m field causes migration to fail. ([#334])
|
||||||
- Fix configuration file reading error when containing Chinese characters. (#286)
|
- Fix NonExistentKey when running `aerich init` without `[tool]` section in config file. ([#284])
|
||||||
- sqlite: failed to create/drop index. (#302)
|
- Fix configuration file reading error when containing Chinese characters. ([#286])
|
||||||
- PostgreSQL: Cannot drop constraint after deleting or rename FK on a model. (#378)
|
- sqlite: failed to create/drop index. ([#302])
|
||||||
- Fix create/drop indexes in every migration. (#377)
|
- PostgreSQL: Cannot drop constraint after deleting or rename FK on a model. ([#378])
|
||||||
- Sort m2m fields before comparing them with diff. (#271)
|
- Fix create/drop indexes in every migration. ([#377])
|
||||||
|
- Sort m2m fields before comparing them with diff. ([#271])
|
||||||
|
|
||||||
#### Changed
|
#### Changed
|
||||||
- Allow run `aerich init-db` with empty migration directories instead of abort with warnings. (#286)
|
- Allow run `aerich init-db` with empty migration directories instead of abort with warnings. ([#286])
|
||||||
- Add version constraint(>=0.21) for tortoise-orm. (#388)
|
- Add version constraint(>=0.21) for tortoise-orm. ([#388])
|
||||||
- Move `tomlkit` to optional and support `pip install aerich[toml]`. (#392)
|
- Move `tomlkit` to optional and support `pip install aerich[toml]`. ([#392])
|
||||||
|
|
||||||
|
[#396]: https://github.com/tortoise/aerich/pull/396
|
||||||
|
[#395]: https://github.com/tortoise/aerich/pull/395
|
||||||
|
[#394]: https://github.com/tortoise/aerich/pull/394
|
||||||
|
[#393]: https://github.com/tortoise/aerich/pull/393
|
||||||
|
[#376]: https://github.com/tortoise/aerich/pull/376
|
||||||
|
[#386]: https://github.com/tortoise/aerich/pull/386
|
||||||
|
[#272]: https://github.com/tortoise/aerich/pull/272
|
||||||
|
[#334]: https://github.com/tortoise/aerich/pull/334
|
||||||
|
[#284]: https://github.com/tortoise/aerich/pull/284
|
||||||
|
[#286]: https://github.com/tortoise/aerich/pull/286
|
||||||
|
[#302]: https://github.com/tortoise/aerich/pull/302
|
||||||
|
[#378]: https://github.com/tortoise/aerich/pull/378
|
||||||
|
[#377]: https://github.com/tortoise/aerich/pull/377
|
||||||
|
[#271]: https://github.com/tortoise/aerich/pull/271
|
||||||
|
[#286]: https://github.com/tortoise/aerich/pull/286
|
||||||
|
[#388]: https://github.com/tortoise/aerich/pull/388
|
||||||
|
[#392]: https://github.com/tortoise/aerich/pull/392
|
||||||
|
|
||||||
### [0.8.0](../../releases/tag/v0.8.0) - 2024-12-04
|
### [0.8.0](../../releases/tag/v0.8.0) - 2024-12-04
|
||||||
|
|
||||||
@ -31,6 +50,7 @@
|
|||||||
- Correct the click import. (#360)
|
- Correct the click import. (#360)
|
||||||
- Improve CLI help text and output. (#355)
|
- Improve CLI help text and output. (#355)
|
||||||
- Fix mysql drop unique index raises OperationalError. (#346)
|
- Fix mysql drop unique index raises OperationalError. (#346)
|
||||||
|
|
||||||
**Upgrade note:**
|
**Upgrade note:**
|
||||||
1. Use column name as unique key name for mysql
|
1. Use column name as unique key name for mysql
|
||||||
2. Drop support for Python3.7
|
2. Drop support for Python3.7
|
||||||
|
@ -44,8 +44,7 @@ class Migrate:
|
|||||||
_upgrade_m2m: List[str] = []
|
_upgrade_m2m: List[str] = []
|
||||||
_downgrade_m2m: List[str] = []
|
_downgrade_m2m: List[str] = []
|
||||||
_aerich = Aerich.__name__
|
_aerich = Aerich.__name__
|
||||||
_rename_old: List[str] = []
|
_rename_fields: Dict[str, Dict[str, str]] = {} # {'model': {'old_field': 'new_field'}}
|
||||||
_rename_new: List[str] = []
|
|
||||||
|
|
||||||
ddl: BaseDDL
|
ddl: BaseDDL
|
||||||
ddl_class: Type[BaseDDL]
|
ddl_class: Type[BaseDDL]
|
||||||
@ -363,6 +362,7 @@ class Migrate:
|
|||||||
_aerich = f"{cls.app}.{cls._aerich}"
|
_aerich = f"{cls.app}.{cls._aerich}"
|
||||||
old_models.pop(_aerich, None)
|
old_models.pop(_aerich, None)
|
||||||
new_models.pop(_aerich, None)
|
new_models.pop(_aerich, None)
|
||||||
|
models_with_rename_field: Set[str] = set() # models that trigger the click.prompt
|
||||||
|
|
||||||
for new_model_str, new_model_describe in new_models.items():
|
for new_model_str, new_model_describe in new_models.items():
|
||||||
model = cls._get_model(new_model_describe["name"].split(".")[1])
|
model = cls._get_model(new_model_describe["name"].split(".")[1])
|
||||||
@ -447,33 +447,63 @@ class Migrate:
|
|||||||
):
|
):
|
||||||
new_data_field = cls.get_field_by_name(new_data_field_name, new_data_fields)
|
new_data_field = cls.get_field_by_name(new_data_field_name, new_data_fields)
|
||||||
is_rename = False
|
is_rename = False
|
||||||
for old_data_field in old_data_fields:
|
field_type = new_data_field.get("field_type")
|
||||||
|
db_column = new_data_field.get("db_column")
|
||||||
|
new_name = set(new_data_field_name)
|
||||||
|
for old_data_field in sorted(
|
||||||
|
old_data_fields,
|
||||||
|
key=lambda f: (
|
||||||
|
f.get("field_type") != field_type,
|
||||||
|
# old field whose name have more same characters with new field's
|
||||||
|
# should be put in front of the other
|
||||||
|
len(new_name.symmetric_difference(set(f.get("name", "")))),
|
||||||
|
),
|
||||||
|
):
|
||||||
changes = list(diff(old_data_field, new_data_field))
|
changes = list(diff(old_data_field, new_data_field))
|
||||||
old_data_field_name = cast(str, old_data_field.get("name"))
|
old_data_field_name = cast(str, old_data_field.get("name"))
|
||||||
if len(changes) == 2:
|
if len(changes) == 2:
|
||||||
# rename field
|
# rename field
|
||||||
name_diff = (old_data_field_name, new_data_field_name)
|
name_diff = (old_data_field_name, new_data_field_name)
|
||||||
column_diff = (
|
column_diff = (old_data_field.get("db_column"), db_column)
|
||||||
old_data_field.get("db_column"),
|
|
||||||
new_data_field.get("db_column"),
|
|
||||||
)
|
|
||||||
if (
|
if (
|
||||||
changes[0] == ("change", "name", name_diff)
|
changes[0] == ("change", "name", name_diff)
|
||||||
and changes[1] == ("change", "db_column", column_diff)
|
and changes[1] == ("change", "db_column", column_diff)
|
||||||
and old_data_field_name not in new_data_fields_name
|
and old_data_field_name not in new_data_fields_name
|
||||||
):
|
):
|
||||||
if upgrade:
|
if upgrade:
|
||||||
|
if (
|
||||||
|
rename_fields := cls._rename_fields.get(new_model_str)
|
||||||
|
) and (
|
||||||
|
old_data_field_name in rename_fields
|
||||||
|
or new_data_field_name in rename_fields.values()
|
||||||
|
):
|
||||||
|
continue
|
||||||
|
prefix = f"({new_model_str}) "
|
||||||
|
if new_model_str not in models_with_rename_field:
|
||||||
|
if models_with_rename_field:
|
||||||
|
# When there are multi rename fields with different models,
|
||||||
|
# print a empty line to warn that is another model
|
||||||
|
prefix = "\n" + prefix
|
||||||
|
models_with_rename_field.add(new_model_str)
|
||||||
is_rename = click.prompt(
|
is_rename = click.prompt(
|
||||||
f"Rename {old_data_field_name} to {new_data_field_name}?",
|
f"{prefix}Rename {old_data_field_name} to {new_data_field_name}?",
|
||||||
default=True,
|
default=True,
|
||||||
type=bool,
|
type=bool,
|
||||||
show_choices=True,
|
show_choices=True,
|
||||||
)
|
)
|
||||||
|
if is_rename:
|
||||||
|
if rename_fields is None:
|
||||||
|
rename_fields = cls._rename_fields[new_model_str] = {}
|
||||||
|
rename_fields[old_data_field_name] = new_data_field_name
|
||||||
else:
|
else:
|
||||||
is_rename = old_data_field_name in cls._rename_new
|
is_rename = False
|
||||||
|
if rename_to := cls._rename_fields.get(new_model_str, {}).get(
|
||||||
|
new_data_field_name
|
||||||
|
):
|
||||||
|
is_rename = True
|
||||||
|
if rename_to != old_data_field_name:
|
||||||
|
continue
|
||||||
if is_rename:
|
if is_rename:
|
||||||
cls._rename_new.append(new_data_field_name)
|
|
||||||
cls._rename_old.append(old_data_field_name)
|
|
||||||
# only MySQL8+ has rename syntax
|
# only MySQL8+ has rename syntax
|
||||||
if (
|
if (
|
||||||
cls.dialect == "mysql"
|
cls.dialect == "mysql"
|
||||||
@ -492,13 +522,7 @@ class Migrate:
|
|||||||
upgrade,
|
upgrade,
|
||||||
)
|
)
|
||||||
if not is_rename:
|
if not is_rename:
|
||||||
cls._add_operator(
|
cls._add_operator(cls._add_field(model, new_data_field), upgrade)
|
||||||
cls._add_field(
|
|
||||||
model,
|
|
||||||
new_data_field,
|
|
||||||
),
|
|
||||||
upgrade,
|
|
||||||
)
|
|
||||||
if (
|
if (
|
||||||
new_data_field["indexed"]
|
new_data_field["indexed"]
|
||||||
and new_data_field["db_column"] not in new_o2o_columns
|
and new_data_field["db_column"] not in new_o2o_columns
|
||||||
@ -511,12 +535,14 @@ class Migrate:
|
|||||||
True,
|
True,
|
||||||
)
|
)
|
||||||
# remove fields
|
# remove fields
|
||||||
|
rename_fields = cls._rename_fields.get(new_model_str)
|
||||||
for old_data_field_name in set(old_data_fields_name).difference(
|
for old_data_field_name in set(old_data_fields_name).difference(
|
||||||
set(new_data_fields_name)
|
set(new_data_fields_name)
|
||||||
):
|
):
|
||||||
# don't remove field if is renamed
|
# don't remove field if is renamed
|
||||||
if (upgrade and old_data_field_name in cls._rename_old) or (
|
if rename_fields and (
|
||||||
not upgrade and old_data_field_name in cls._rename_new
|
(upgrade and old_data_field_name in rename_fields)
|
||||||
|
or (not upgrade and old_data_field_name in rename_fields.values())
|
||||||
):
|
):
|
||||||
continue
|
continue
|
||||||
old_data_field = cls.get_field_by_name(old_data_field_name, old_data_fields)
|
old_data_field = cls.get_field_by_name(old_data_field_name, old_data_fields)
|
||||||
|
@ -81,6 +81,7 @@ class Product(Model):
|
|||||||
pic = fields.CharField(max_length=200)
|
pic = fields.CharField(max_length=200)
|
||||||
body = fields.TextField()
|
body = fields.TextField()
|
||||||
created_at = fields.DatetimeField(auto_now_add=True)
|
created_at = fields.DatetimeField(auto_now_add=True)
|
||||||
|
is_deleted = fields.BooleanField(default=False)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
unique_together = (("name", "type"),)
|
unique_together = (("name", "type"),)
|
||||||
|
@ -61,13 +61,14 @@ class Product(Model):
|
|||||||
name = fields.CharField(max_length=50)
|
name = fields.CharField(max_length=50)
|
||||||
view_num = fields.IntField(description="View Num")
|
view_num = fields.IntField(description="View Num")
|
||||||
sort = fields.IntField()
|
sort = fields.IntField()
|
||||||
is_reviewed = fields.BooleanField(description="Is Reviewed")
|
is_review = fields.BooleanField(description="Is Reviewed")
|
||||||
type = fields.IntEnumField(
|
type = fields.IntEnumField(
|
||||||
ProductType, description="Product Type", source_field="type_db_alias"
|
ProductType, description="Product Type", source_field="type_db_alias"
|
||||||
)
|
)
|
||||||
image = fields.CharField(max_length=200)
|
image = fields.CharField(max_length=200)
|
||||||
body = fields.TextField()
|
body = fields.TextField()
|
||||||
created_at = fields.DatetimeField(auto_now_add=True)
|
created_at = fields.DatetimeField(auto_now_add=True)
|
||||||
|
is_delete = fields.BooleanField(default=False)
|
||||||
|
|
||||||
|
|
||||||
class Config(Model):
|
class Config(Model):
|
||||||
|
@ -368,7 +368,12 @@ old_models_describe = {
|
|||||||
"description": None,
|
"description": None,
|
||||||
"docstring": None,
|
"docstring": None,
|
||||||
"constraints": {},
|
"constraints": {},
|
||||||
"db_field_types": {"": "BOOL", "sqlite": "INT"},
|
"db_field_types": {
|
||||||
|
"": "BOOL",
|
||||||
|
"mssql": "BIT",
|
||||||
|
"oracle": "NUMBER(1)",
|
||||||
|
"sqlite": "INT",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "user_id",
|
"name": "user_id",
|
||||||
@ -494,9 +499,9 @@ old_models_describe = {
|
|||||||
"db_field_types": {"": "INT"},
|
"db_field_types": {"": "INT"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "is_reviewed",
|
"name": "is_review",
|
||||||
"field_type": "BooleanField",
|
"field_type": "BooleanField",
|
||||||
"db_column": "is_reviewed",
|
"db_column": "is_review",
|
||||||
"python_type": "bool",
|
"python_type": "bool",
|
||||||
"generated": False,
|
"generated": False,
|
||||||
"nullable": False,
|
"nullable": False,
|
||||||
@ -506,7 +511,12 @@ old_models_describe = {
|
|||||||
"description": "Is Reviewed",
|
"description": "Is Reviewed",
|
||||||
"docstring": None,
|
"docstring": None,
|
||||||
"constraints": {},
|
"constraints": {},
|
||||||
"db_field_types": {"": "BOOL", "sqlite": "INT"},
|
"db_field_types": {
|
||||||
|
"": "BOOL",
|
||||||
|
"mssql": "BIT",
|
||||||
|
"oracle": "NUMBER(1)",
|
||||||
|
"sqlite": "INT",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "type",
|
"name": "type",
|
||||||
@ -574,6 +584,26 @@ old_models_describe = {
|
|||||||
"auto_now_add": True,
|
"auto_now_add": True,
|
||||||
"auto_now": False,
|
"auto_now": False,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "is_delete",
|
||||||
|
"field_type": "BooleanField",
|
||||||
|
"db_column": "is_delete",
|
||||||
|
"python_type": "bool",
|
||||||
|
"generated": False,
|
||||||
|
"nullable": False,
|
||||||
|
"unique": False,
|
||||||
|
"indexed": False,
|
||||||
|
"default": False,
|
||||||
|
"description": None,
|
||||||
|
"docstring": None,
|
||||||
|
"constraints": {},
|
||||||
|
"db_field_types": {
|
||||||
|
"": "BOOL",
|
||||||
|
"mssql": "BIT",
|
||||||
|
"oracle": "NUMBER(1)",
|
||||||
|
"sqlite": "INT",
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
"fk_fields": [],
|
"fk_fields": [],
|
||||||
"backward_fk_fields": [],
|
"backward_fk_fields": [],
|
||||||
@ -691,7 +721,12 @@ old_models_describe = {
|
|||||||
"description": "Is Active",
|
"description": "Is Active",
|
||||||
"docstring": None,
|
"docstring": None,
|
||||||
"constraints": {},
|
"constraints": {},
|
||||||
"db_field_types": {"": "BOOL", "sqlite": "INT"},
|
"db_field_types": {
|
||||||
|
"": "BOOL",
|
||||||
|
"mssql": "BIT",
|
||||||
|
"oracle": "NUMBER(1)",
|
||||||
|
"sqlite": "INT",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "is_superuser",
|
"name": "is_superuser",
|
||||||
@ -706,7 +741,12 @@ old_models_describe = {
|
|||||||
"description": "Is SuperUser",
|
"description": "Is SuperUser",
|
||||||
"docstring": None,
|
"docstring": None,
|
||||||
"constraints": {},
|
"constraints": {},
|
||||||
"db_field_types": {"": "BOOL", "sqlite": "INT"},
|
"db_field_types": {
|
||||||
|
"": "BOOL",
|
||||||
|
"mssql": "BIT",
|
||||||
|
"oracle": "NUMBER(1)",
|
||||||
|
"sqlite": "INT",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "avatar",
|
"name": "avatar",
|
||||||
@ -872,8 +912,8 @@ def test_migrate(mocker: MockerFixture):
|
|||||||
models.py diff with old_models.py
|
models.py diff with old_models.py
|
||||||
- change email pk: id -> email_id
|
- change email pk: id -> email_id
|
||||||
- add field: Email.address
|
- add field: Email.address
|
||||||
- add fk: Config.user
|
- add fk field: Config.user
|
||||||
- drop fk: Email.user
|
- drop fk field: Email.user
|
||||||
- drop field: User.avatar
|
- drop field: User.avatar
|
||||||
- add index: Email.email
|
- add index: Email.email
|
||||||
- add many to many: Email.users
|
- add many to many: Email.users
|
||||||
@ -886,9 +926,11 @@ def test_migrate(mocker: MockerFixture):
|
|||||||
- drop unique field: Config.name
|
- drop unique field: Config.name
|
||||||
- alter default: Config.status
|
- alter default: Config.status
|
||||||
- rename column: Product.image -> Product.pic
|
- rename column: Product.image -> Product.pic
|
||||||
|
- rename column: Product.is_review -> Product.is_reviewed
|
||||||
|
- rename column: Product.is_delete -> Product.is_deleted
|
||||||
- rename fk column: Category.user -> Category.owner
|
- rename fk column: Category.user -> Category.owner
|
||||||
"""
|
"""
|
||||||
mocker.patch("asyncclick.prompt", side_effect=(True, True))
|
mocker.patch("asyncclick.prompt", side_effect=(True, True, True, True))
|
||||||
|
|
||||||
models_describe = get_models_describe("models")
|
models_describe = get_models_describe("models")
|
||||||
Migrate.app = "models"
|
Migrate.app = "models"
|
||||||
@ -910,6 +952,7 @@ def test_migrate(mocker: MockerFixture):
|
|||||||
"ALTER TABLE `category` DROP INDEX `title`",
|
"ALTER TABLE `category` DROP INDEX `title`",
|
||||||
"ALTER TABLE `category` RENAME COLUMN `user_id` TO `owner_id`",
|
"ALTER TABLE `category` RENAME COLUMN `user_id` TO `owner_id`",
|
||||||
"ALTER TABLE `category` ADD CONSTRAINT `fk_category_user_110d4c63` FOREIGN KEY (`owner_id`) REFERENCES `user` (`id`) ON DELETE CASCADE",
|
"ALTER TABLE `category` ADD CONSTRAINT `fk_category_user_110d4c63` FOREIGN KEY (`owner_id`) REFERENCES `user` (`id`) ON DELETE CASCADE",
|
||||||
|
"ALTER TABLE `email` DROP COLUMN `user_id`",
|
||||||
"ALTER TABLE `config` DROP COLUMN `name`",
|
"ALTER TABLE `config` DROP COLUMN `name`",
|
||||||
"ALTER TABLE `config` DROP INDEX `name`",
|
"ALTER TABLE `config` DROP INDEX `name`",
|
||||||
"ALTER TABLE `config` ADD `user_id` INT NOT NULL COMMENT 'User'",
|
"ALTER TABLE `config` ADD `user_id` INT NOT NULL COMMENT 'User'",
|
||||||
@ -929,20 +972,18 @@ def test_migrate(mocker: MockerFixture):
|
|||||||
"ALTER TABLE `product` ADD UNIQUE INDEX `uid_product_name_869427` (`name`, `type_db_alias`)",
|
"ALTER TABLE `product` ADD UNIQUE INDEX `uid_product_name_869427` (`name`, `type_db_alias`)",
|
||||||
"ALTER TABLE `product` ALTER COLUMN `view_num` SET DEFAULT 0",
|
"ALTER TABLE `product` ALTER COLUMN `view_num` SET DEFAULT 0",
|
||||||
"ALTER TABLE `product` MODIFY COLUMN `created_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6)",
|
"ALTER TABLE `product` MODIFY COLUMN `created_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6)",
|
||||||
"ALTER TABLE `product` MODIFY COLUMN `is_reviewed` BOOL NOT NULL COMMENT 'Is Reviewed'",
|
"ALTER TABLE `product` RENAME COLUMN `is_delete` TO `is_deleted`",
|
||||||
|
"ALTER TABLE `product` RENAME COLUMN `is_review` TO `is_reviewed`",
|
||||||
"ALTER TABLE `user` DROP COLUMN `avatar`",
|
"ALTER TABLE `user` DROP COLUMN `avatar`",
|
||||||
"ALTER TABLE `user` MODIFY COLUMN `password` VARCHAR(100) NOT NULL",
|
"ALTER TABLE `user` MODIFY COLUMN `password` VARCHAR(100) NOT NULL",
|
||||||
"ALTER TABLE `user` MODIFY COLUMN `intro` LONGTEXT NOT NULL",
|
"ALTER TABLE `user` MODIFY COLUMN `intro` LONGTEXT NOT NULL",
|
||||||
"ALTER TABLE `user` MODIFY COLUMN `last_login` DATETIME(6) NOT NULL COMMENT 'Last Login'",
|
"ALTER TABLE `user` MODIFY COLUMN `last_login` DATETIME(6) NOT NULL COMMENT 'Last Login'",
|
||||||
"ALTER TABLE `user` MODIFY COLUMN `is_active` BOOL NOT NULL COMMENT 'Is Active' DEFAULT 1",
|
|
||||||
"ALTER TABLE `user` MODIFY COLUMN `is_superuser` BOOL NOT NULL COMMENT 'Is SuperUser' DEFAULT 0",
|
|
||||||
"ALTER TABLE `user` MODIFY COLUMN `longitude` DECIMAL(10,8) NOT NULL",
|
"ALTER TABLE `user` MODIFY COLUMN `longitude` DECIMAL(10,8) NOT NULL",
|
||||||
"ALTER TABLE `user` ADD UNIQUE INDEX `username` (`username`)",
|
"ALTER TABLE `user` ADD UNIQUE INDEX `username` (`username`)",
|
||||||
"CREATE TABLE `email_user` (\n `email_id` INT NOT NULL REFERENCES `email` (`email_id`) ON DELETE CASCADE,\n `user_id` INT NOT NULL REFERENCES `user` (`id`) ON DELETE CASCADE\n) CHARACTER SET utf8mb4",
|
"CREATE TABLE `email_user` (\n `email_id` INT NOT NULL REFERENCES `email` (`email_id`) ON DELETE CASCADE,\n `user_id` INT NOT NULL REFERENCES `user` (`id`) ON DELETE CASCADE\n) CHARACTER SET utf8mb4",
|
||||||
"CREATE TABLE IF NOT EXISTS `newmodel` (\n `id` INT NOT NULL PRIMARY KEY AUTO_INCREMENT,\n `name` VARCHAR(50) NOT NULL\n) CHARACTER SET utf8mb4",
|
"CREATE TABLE IF NOT EXISTS `newmodel` (\n `id` INT NOT NULL PRIMARY KEY AUTO_INCREMENT,\n `name` VARCHAR(50) NOT NULL\n) CHARACTER SET utf8mb4",
|
||||||
"ALTER TABLE `category` MODIFY COLUMN `created_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6)",
|
"ALTER TABLE `category` MODIFY COLUMN `created_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6)",
|
||||||
"ALTER TABLE `product` MODIFY COLUMN `body` LONGTEXT NOT NULL",
|
"ALTER TABLE `product` MODIFY COLUMN `body` LONGTEXT NOT NULL",
|
||||||
"ALTER TABLE `email` MODIFY COLUMN `is_primary` BOOL NOT NULL DEFAULT 0",
|
|
||||||
"CREATE TABLE `product_user` (\n `product_id` INT NOT NULL REFERENCES `product` (`id`) ON DELETE CASCADE,\n `user_id` INT NOT NULL REFERENCES `user` (`id`) ON DELETE CASCADE\n) CHARACTER SET utf8mb4",
|
"CREATE TABLE `product_user` (\n `product_id` INT NOT NULL REFERENCES `product` (`id`) ON DELETE CASCADE,\n `user_id` INT NOT NULL REFERENCES `user` (`id`) ON DELETE CASCADE\n) CHARACTER SET utf8mb4",
|
||||||
"CREATE TABLE `config_category_map` (\n `category_id` INT NOT NULL REFERENCES `category` (`id`) ON DELETE CASCADE,\n `config_id` INT NOT NULL REFERENCES `config` (`id`) ON DELETE CASCADE\n) CHARACTER SET utf8mb4",
|
"CREATE TABLE `config_category_map` (\n `category_id` INT NOT NULL REFERENCES `category` (`id`) ON DELETE CASCADE,\n `config_id` INT NOT NULL REFERENCES `config` (`id`) ON DELETE CASCADE\n) CHARACTER SET utf8mb4",
|
||||||
"DROP TABLE IF EXISTS `config_category`",
|
"DROP TABLE IF EXISTS `config_category`",
|
||||||
@ -958,6 +999,7 @@ def test_migrate(mocker: MockerFixture):
|
|||||||
"ALTER TABLE `config` DROP FOREIGN KEY `fk_config_user_17daa970`",
|
"ALTER TABLE `config` DROP FOREIGN KEY `fk_config_user_17daa970`",
|
||||||
"ALTER TABLE `config` ALTER COLUMN `status` SET DEFAULT 1",
|
"ALTER TABLE `config` ALTER COLUMN `status` SET DEFAULT 1",
|
||||||
"ALTER TABLE `email` ADD `user_id` INT NOT NULL",
|
"ALTER TABLE `email` ADD `user_id` INT NOT NULL",
|
||||||
|
"ALTER TABLE `config` DROP COLUMN `user_id`",
|
||||||
"ALTER TABLE `email` DROP COLUMN `address`",
|
"ALTER TABLE `email` DROP COLUMN `address`",
|
||||||
"ALTER TABLE `email` DROP COLUMN `config_id`",
|
"ALTER TABLE `email` DROP COLUMN `config_id`",
|
||||||
"ALTER TABLE `email` DROP FOREIGN KEY `fk_email_config_76a9dc71`",
|
"ALTER TABLE `email` DROP FOREIGN KEY `fk_email_config_76a9dc71`",
|
||||||
@ -970,6 +1012,8 @@ def test_migrate(mocker: MockerFixture):
|
|||||||
"ALTER TABLE `email` DROP INDEX `idx_email_email_4a1a33`",
|
"ALTER TABLE `email` DROP INDEX `idx_email_email_4a1a33`",
|
||||||
"ALTER TABLE `product` DROP INDEX `uid_product_name_869427`",
|
"ALTER TABLE `product` DROP INDEX `uid_product_name_869427`",
|
||||||
"ALTER TABLE `product` ALTER COLUMN `view_num` DROP DEFAULT",
|
"ALTER TABLE `product` ALTER COLUMN `view_num` DROP DEFAULT",
|
||||||
|
"ALTER TABLE `product` RENAME COLUMN `is_deleted` TO `is_delete`",
|
||||||
|
"ALTER TABLE `product` RENAME COLUMN `is_reviewed` TO `is_review`",
|
||||||
"ALTER TABLE `user` ADD `avatar` VARCHAR(200) NOT NULL DEFAULT ''",
|
"ALTER TABLE `user` ADD `avatar` VARCHAR(200) NOT NULL DEFAULT ''",
|
||||||
"ALTER TABLE `user` DROP INDEX `username`",
|
"ALTER TABLE `user` DROP INDEX `username`",
|
||||||
"ALTER TABLE `user` MODIFY COLUMN `password` VARCHAR(200) NOT NULL",
|
"ALTER TABLE `user` MODIFY COLUMN `password` VARCHAR(200) NOT NULL",
|
||||||
@ -980,13 +1024,9 @@ def test_migrate(mocker: MockerFixture):
|
|||||||
"ALTER TABLE `config` MODIFY COLUMN `value` TEXT NOT NULL",
|
"ALTER TABLE `config` MODIFY COLUMN `value` TEXT NOT NULL",
|
||||||
"ALTER TABLE `category` MODIFY COLUMN `created_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6)",
|
"ALTER TABLE `category` MODIFY COLUMN `created_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6)",
|
||||||
"ALTER TABLE `product` MODIFY COLUMN `created_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6)",
|
"ALTER TABLE `product` MODIFY COLUMN `created_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6)",
|
||||||
"ALTER TABLE `product` MODIFY COLUMN `is_reviewed` BOOL NOT NULL COMMENT 'Is Reviewed'",
|
|
||||||
"ALTER TABLE `user` MODIFY COLUMN `last_login` DATETIME(6) NOT NULL COMMENT 'Last Login'",
|
"ALTER TABLE `user` MODIFY COLUMN `last_login` DATETIME(6) NOT NULL COMMENT 'Last Login'",
|
||||||
"ALTER TABLE `user` MODIFY COLUMN `is_active` BOOL NOT NULL COMMENT 'Is Active' DEFAULT 1",
|
|
||||||
"ALTER TABLE `user` MODIFY COLUMN `is_superuser` BOOL NOT NULL COMMENT 'Is SuperUser' DEFAULT 0",
|
|
||||||
"ALTER TABLE `user` MODIFY COLUMN `longitude` DECIMAL(12,9) NOT NULL",
|
"ALTER TABLE `user` MODIFY COLUMN `longitude` DECIMAL(12,9) NOT NULL",
|
||||||
"ALTER TABLE `product` MODIFY COLUMN `body` LONGTEXT NOT NULL",
|
"ALTER TABLE `product` MODIFY COLUMN `body` LONGTEXT NOT NULL",
|
||||||
"ALTER TABLE `email` MODIFY COLUMN `is_primary` BOOL NOT NULL DEFAULT 0",
|
|
||||||
"CREATE TABLE `config_category` (\n `config_id` INT NOT NULL REFERENCES `config` (`id`) ON DELETE CASCADE,\n `category_id` INT NOT NULL REFERENCES `category` (`id`) ON DELETE CASCADE\n) CHARACTER SET utf8mb4",
|
"CREATE TABLE `config_category` (\n `config_id` INT NOT NULL REFERENCES `config` (`id`) ON DELETE CASCADE,\n `category_id` INT NOT NULL REFERENCES `category` (`id`) ON DELETE CASCADE\n) CHARACTER SET utf8mb4",
|
||||||
"DROP TABLE IF EXISTS `config_category_map`",
|
"DROP TABLE IF EXISTS `config_category_map`",
|
||||||
}
|
}
|
||||||
@ -1013,22 +1053,21 @@ def test_migrate(mocker: MockerFixture):
|
|||||||
'ALTER TABLE "configs" RENAME TO "config"',
|
'ALTER TABLE "configs" RENAME TO "config"',
|
||||||
'ALTER TABLE "email" ADD "address" VARCHAR(200) NOT NULL',
|
'ALTER TABLE "email" ADD "address" VARCHAR(200) NOT NULL',
|
||||||
'ALTER TABLE "email" RENAME COLUMN "id" TO "email_id"',
|
'ALTER TABLE "email" RENAME COLUMN "id" TO "email_id"',
|
||||||
'ALTER TABLE "email" ALTER COLUMN "is_primary" TYPE BOOL USING "is_primary"::BOOL',
|
'ALTER TABLE "email" DROP COLUMN "user_id"',
|
||||||
'ALTER TABLE "email" ADD CONSTRAINT "fk_email_config_76a9dc71" FOREIGN KEY ("config_id") REFERENCES "config" ("id") ON DELETE CASCADE',
|
'ALTER TABLE "email" ADD CONSTRAINT "fk_email_config_76a9dc71" FOREIGN KEY ("config_id") REFERENCES "config" ("id") ON DELETE CASCADE',
|
||||||
'ALTER TABLE "email" ADD "config_id" INT NOT NULL UNIQUE',
|
'ALTER TABLE "email" ADD "config_id" INT NOT NULL UNIQUE',
|
||||||
'DROP INDEX IF EXISTS "uid_product_uuid_d33c18"',
|
'DROP INDEX IF EXISTS "uid_product_uuid_d33c18"',
|
||||||
'ALTER TABLE "product" DROP COLUMN "uuid"',
|
'ALTER TABLE "product" DROP COLUMN "uuid"',
|
||||||
'ALTER TABLE "product" ALTER COLUMN "view_num" SET DEFAULT 0',
|
'ALTER TABLE "product" ALTER COLUMN "view_num" SET DEFAULT 0',
|
||||||
'ALTER TABLE "product" RENAME COLUMN "image" TO "pic"',
|
'ALTER TABLE "product" RENAME COLUMN "image" TO "pic"',
|
||||||
'ALTER TABLE "product" ALTER COLUMN "is_reviewed" TYPE BOOL USING "is_reviewed"::BOOL',
|
|
||||||
'ALTER TABLE "product" ALTER COLUMN "body" TYPE TEXT USING "body"::TEXT',
|
'ALTER TABLE "product" ALTER COLUMN "body" TYPE TEXT USING "body"::TEXT',
|
||||||
'ALTER TABLE "product" ALTER COLUMN "created_at" TYPE TIMESTAMPTZ USING "created_at"::TIMESTAMPTZ',
|
'ALTER TABLE "product" ALTER COLUMN "created_at" TYPE TIMESTAMPTZ USING "created_at"::TIMESTAMPTZ',
|
||||||
|
'ALTER TABLE "product" RENAME COLUMN "is_review" TO "is_reviewed"',
|
||||||
|
'ALTER TABLE "product" RENAME COLUMN "is_delete" TO "is_deleted"',
|
||||||
'ALTER TABLE "user" ALTER COLUMN "password" TYPE VARCHAR(100) USING "password"::VARCHAR(100)',
|
'ALTER TABLE "user" ALTER COLUMN "password" TYPE VARCHAR(100) USING "password"::VARCHAR(100)',
|
||||||
'ALTER TABLE "user" DROP COLUMN "avatar"',
|
'ALTER TABLE "user" DROP COLUMN "avatar"',
|
||||||
'ALTER TABLE "user" ALTER COLUMN "is_superuser" TYPE BOOL USING "is_superuser"::BOOL',
|
|
||||||
'ALTER TABLE "user" ALTER COLUMN "last_login" TYPE TIMESTAMPTZ USING "last_login"::TIMESTAMPTZ',
|
'ALTER TABLE "user" ALTER COLUMN "last_login" TYPE TIMESTAMPTZ USING "last_login"::TIMESTAMPTZ',
|
||||||
'ALTER TABLE "user" ALTER COLUMN "intro" TYPE TEXT USING "intro"::TEXT',
|
'ALTER TABLE "user" ALTER COLUMN "intro" TYPE TEXT USING "intro"::TEXT',
|
||||||
'ALTER TABLE "user" ALTER COLUMN "is_active" TYPE BOOL USING "is_active"::BOOL',
|
|
||||||
'ALTER TABLE "user" ALTER COLUMN "longitude" TYPE DECIMAL(10,8) USING "longitude"::DECIMAL(10,8)',
|
'ALTER TABLE "user" ALTER COLUMN "longitude" TYPE DECIMAL(10,8) USING "longitude"::DECIMAL(10,8)',
|
||||||
'CREATE INDEX "idx_product_name_869427" ON "product" ("name", "type_db_alias")',
|
'CREATE INDEX "idx_product_name_869427" ON "product" ("name", "type_db_alias")',
|
||||||
'CREATE INDEX "idx_email_email_4a1a33" ON "email" ("email")',
|
'CREATE INDEX "idx_email_email_4a1a33" ON "email" ("email")',
|
||||||
@ -1053,25 +1092,24 @@ def test_migrate(mocker: MockerFixture):
|
|||||||
'ALTER TABLE "config" DROP CONSTRAINT IF EXISTS "fk_config_user_17daa970"',
|
'ALTER TABLE "config" DROP CONSTRAINT IF EXISTS "fk_config_user_17daa970"',
|
||||||
'ALTER TABLE "config" RENAME TO "configs"',
|
'ALTER TABLE "config" RENAME TO "configs"',
|
||||||
'ALTER TABLE "config" ALTER COLUMN "value" TYPE JSONB USING "value"::JSONB',
|
'ALTER TABLE "config" ALTER COLUMN "value" TYPE JSONB USING "value"::JSONB',
|
||||||
|
'ALTER TABLE "config" DROP COLUMN "user_id"',
|
||||||
'ALTER TABLE "email" ADD "user_id" INT NOT NULL',
|
'ALTER TABLE "email" ADD "user_id" INT NOT NULL',
|
||||||
'ALTER TABLE "email" DROP COLUMN "address"',
|
'ALTER TABLE "email" DROP COLUMN "address"',
|
||||||
'ALTER TABLE "email" RENAME COLUMN "email_id" TO "id"',
|
'ALTER TABLE "email" RENAME COLUMN "email_id" TO "id"',
|
||||||
'ALTER TABLE "email" ALTER COLUMN "is_primary" TYPE BOOL USING "is_primary"::BOOL',
|
|
||||||
'ALTER TABLE "email" DROP COLUMN "config_id"',
|
'ALTER TABLE "email" DROP COLUMN "config_id"',
|
||||||
'ALTER TABLE "email" DROP CONSTRAINT IF EXISTS "fk_email_config_76a9dc71"',
|
'ALTER TABLE "email" DROP CONSTRAINT IF EXISTS "fk_email_config_76a9dc71"',
|
||||||
'ALTER TABLE "product" ADD "uuid" INT NOT NULL UNIQUE',
|
'ALTER TABLE "product" ADD "uuid" INT NOT NULL UNIQUE',
|
||||||
'CREATE UNIQUE INDEX "uid_product_uuid_d33c18" ON "product" ("uuid")',
|
'CREATE UNIQUE INDEX "uid_product_uuid_d33c18" ON "product" ("uuid")',
|
||||||
'ALTER TABLE "product" ALTER COLUMN "view_num" DROP DEFAULT',
|
'ALTER TABLE "product" ALTER COLUMN "view_num" DROP DEFAULT',
|
||||||
'ALTER TABLE "product" RENAME COLUMN "pic" TO "image"',
|
'ALTER TABLE "product" RENAME COLUMN "pic" TO "image"',
|
||||||
|
'ALTER TABLE "product" RENAME COLUMN "is_deleted" TO "is_delete"',
|
||||||
|
'ALTER TABLE "product" RENAME COLUMN "is_reviewed" TO "is_review"',
|
||||||
'ALTER TABLE "user" ADD "avatar" VARCHAR(200) NOT NULL DEFAULT \'\'',
|
'ALTER TABLE "user" ADD "avatar" VARCHAR(200) NOT NULL DEFAULT \'\'',
|
||||||
'ALTER TABLE "user" ALTER COLUMN "password" TYPE VARCHAR(200) USING "password"::VARCHAR(200)',
|
'ALTER TABLE "user" ALTER COLUMN "password" TYPE VARCHAR(200) USING "password"::VARCHAR(200)',
|
||||||
'ALTER TABLE "user" ALTER COLUMN "last_login" TYPE TIMESTAMPTZ USING "last_login"::TIMESTAMPTZ',
|
'ALTER TABLE "user" ALTER COLUMN "last_login" TYPE TIMESTAMPTZ USING "last_login"::TIMESTAMPTZ',
|
||||||
'ALTER TABLE "user" ALTER COLUMN "is_superuser" TYPE BOOL USING "is_superuser"::BOOL',
|
|
||||||
'ALTER TABLE "user" ALTER COLUMN "is_active" TYPE BOOL USING "is_active"::BOOL',
|
|
||||||
'ALTER TABLE "user" ALTER COLUMN "intro" TYPE TEXT USING "intro"::TEXT',
|
'ALTER TABLE "user" ALTER COLUMN "intro" TYPE TEXT USING "intro"::TEXT',
|
||||||
'ALTER TABLE "user" ALTER COLUMN "longitude" TYPE DECIMAL(12,9) USING "longitude"::DECIMAL(12,9)',
|
'ALTER TABLE "user" ALTER COLUMN "longitude" TYPE DECIMAL(12,9) USING "longitude"::DECIMAL(12,9)',
|
||||||
'ALTER TABLE "product" ALTER COLUMN "created_at" TYPE TIMESTAMPTZ USING "created_at"::TIMESTAMPTZ',
|
'ALTER TABLE "product" ALTER COLUMN "created_at" TYPE TIMESTAMPTZ USING "created_at"::TIMESTAMPTZ',
|
||||||
'ALTER TABLE "product" ALTER COLUMN "is_reviewed" TYPE BOOL USING "is_reviewed"::BOOL',
|
|
||||||
'ALTER TABLE "product" ALTER COLUMN "body" TYPE TEXT USING "body"::TEXT',
|
'ALTER TABLE "product" ALTER COLUMN "body" TYPE TEXT USING "body"::TEXT',
|
||||||
'DROP TABLE IF EXISTS "product_user"',
|
'DROP TABLE IF EXISTS "product_user"',
|
||||||
'DROP INDEX IF EXISTS "idx_product_name_869427"',
|
'DROP INDEX IF EXISTS "idx_product_name_869427"',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user