fix: mysql drop unique index migrate error
This commit is contained in:
parent
51117867a6
commit
e971653851
@ -1,7 +1,12 @@
|
|||||||
|
from typing import TYPE_CHECKING, List, Type
|
||||||
|
|
||||||
from tortoise.backends.mysql.schema_generator import MySQLSchemaGenerator
|
from tortoise.backends.mysql.schema_generator import MySQLSchemaGenerator
|
||||||
|
|
||||||
from aerich.ddl import BaseDDL
|
from aerich.ddl import BaseDDL
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from tortoise import Model # noqa:F401
|
||||||
|
|
||||||
|
|
||||||
class MysqlDDL(BaseDDL):
|
class MysqlDDL(BaseDDL):
|
||||||
schema_generator_cls = MySQLSchemaGenerator
|
schema_generator_cls = MySQLSchemaGenerator
|
||||||
@ -30,3 +35,29 @@ class MysqlDDL(BaseDDL):
|
|||||||
)
|
)
|
||||||
_MODIFY_COLUMN_TEMPLATE = "ALTER TABLE `{table_name}` MODIFY COLUMN {column}"
|
_MODIFY_COLUMN_TEMPLATE = "ALTER TABLE `{table_name}` MODIFY COLUMN {column}"
|
||||||
_RENAME_TABLE_TEMPLATE = "ALTER TABLE `{old_table_name}` RENAME TO `{new_table_name}`"
|
_RENAME_TABLE_TEMPLATE = "ALTER TABLE `{old_table_name}` RENAME TO `{new_table_name}`"
|
||||||
|
|
||||||
|
def _index_name(self, unique: bool, model: "Type[Model]", field_names: List[str]) -> str:
|
||||||
|
if unique:
|
||||||
|
if len(field_names) == 1:
|
||||||
|
# Example: `email = CharField(max_length=50, unique=True)`
|
||||||
|
# Generate schema: `"email" VARCHAR(10) NOT NULL UNIQUE`
|
||||||
|
# Unique index key is the same as field name: `email`
|
||||||
|
return field_names[0]
|
||||||
|
index_prefix = "uid"
|
||||||
|
else:
|
||||||
|
index_prefix = "idx"
|
||||||
|
return self.schema_generator._generate_index_name(index_prefix, model, field_names)
|
||||||
|
|
||||||
|
def add_index(self, model: "Type[Model]", field_names: List[str], unique=False) -> str:
|
||||||
|
return self._ADD_INDEX_TEMPLATE.format(
|
||||||
|
unique="UNIQUE " if unique else "",
|
||||||
|
index_name=self._index_name(unique, model, field_names),
|
||||||
|
table_name=model._meta.db_table,
|
||||||
|
column_names=", ".join(self.schema_generator.quote(f) for f in field_names),
|
||||||
|
)
|
||||||
|
|
||||||
|
def drop_index(self, model: "Type[Model]", field_names: List[str], unique=False) -> str:
|
||||||
|
return self._DROP_INDEX_TEMPLATE.format(
|
||||||
|
index_name=self._index_name(unique, model, field_names),
|
||||||
|
table_name=model._meta.db_table,
|
||||||
|
)
|
||||||
|
@ -477,12 +477,13 @@ class Migrate:
|
|||||||
_, option, old_new = change
|
_, option, old_new = change
|
||||||
if option == "indexed":
|
if option == "indexed":
|
||||||
# change index
|
# change index
|
||||||
unique = new_data_field.get("unique")
|
|
||||||
if old_new[0] is False and old_new[1] is True:
|
if old_new[0] is False and old_new[1] is True:
|
||||||
|
unique = new_data_field.get("unique")
|
||||||
cls._add_operator(
|
cls._add_operator(
|
||||||
cls._add_index(model, (field_name,), unique), upgrade, True
|
cls._add_index(model, (field_name,), unique), upgrade, True
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
unique = old_data_field.get("unique")
|
||||||
cls._add_operator(
|
cls._add_operator(
|
||||||
cls._drop_index(model, (field_name,), unique), upgrade, True
|
cls._drop_index(model, (field_name,), unique), upgrade, True
|
||||||
)
|
)
|
||||||
|
@ -151,9 +151,7 @@ def test_add_index():
|
|||||||
index_u = Migrate.ddl.add_index(Category, ["name"], True)
|
index_u = Migrate.ddl.add_index(Category, ["name"], True)
|
||||||
if isinstance(Migrate.ddl, MysqlDDL):
|
if isinstance(Migrate.ddl, MysqlDDL):
|
||||||
assert index == "ALTER TABLE `category` ADD INDEX `idx_category_name_8b0cb9` (`name`)"
|
assert index == "ALTER TABLE `category` ADD INDEX `idx_category_name_8b0cb9` (`name`)"
|
||||||
assert (
|
assert index_u == "ALTER TABLE `category` ADD UNIQUE INDEX `name` (`name`)"
|
||||||
index_u == "ALTER TABLE `category` ADD UNIQUE INDEX `uid_category_name_8b0cb9` (`name`)"
|
|
||||||
)
|
|
||||||
elif isinstance(Migrate.ddl, PostgresDDL):
|
elif isinstance(Migrate.ddl, PostgresDDL):
|
||||||
assert index == 'CREATE INDEX "idx_category_name_8b0cb9" ON "category" ("name")'
|
assert index == 'CREATE INDEX "idx_category_name_8b0cb9" ON "category" ("name")'
|
||||||
assert index_u == 'CREATE UNIQUE INDEX "uid_category_name_8b0cb9" ON "category" ("name")'
|
assert index_u == 'CREATE UNIQUE INDEX "uid_category_name_8b0cb9" ON "category" ("name")'
|
||||||
@ -169,7 +167,7 @@ def test_drop_index():
|
|||||||
ret_u = Migrate.ddl.drop_index(Category, ["name"], True)
|
ret_u = Migrate.ddl.drop_index(Category, ["name"], True)
|
||||||
if isinstance(Migrate.ddl, MysqlDDL):
|
if isinstance(Migrate.ddl, MysqlDDL):
|
||||||
assert ret == "ALTER TABLE `category` DROP INDEX `idx_category_name_8b0cb9`"
|
assert ret == "ALTER TABLE `category` DROP INDEX `idx_category_name_8b0cb9`"
|
||||||
assert ret_u == "ALTER TABLE `category` DROP INDEX `uid_category_name_8b0cb9`"
|
assert ret_u == "ALTER TABLE `category` DROP INDEX `name`"
|
||||||
elif isinstance(Migrate.ddl, PostgresDDL):
|
elif isinstance(Migrate.ddl, PostgresDDL):
|
||||||
assert ret == 'DROP INDEX "idx_category_name_8b0cb9"'
|
assert ret == 'DROP INDEX "idx_category_name_8b0cb9"'
|
||||||
assert ret_u == 'DROP INDEX "uid_category_name_8b0cb9"'
|
assert ret_u == 'DROP INDEX "uid_category_name_8b0cb9"'
|
||||||
|
@ -44,8 +44,8 @@ old_models_describe = {
|
|||||||
"python_type": "str",
|
"python_type": "str",
|
||||||
"generated": False,
|
"generated": False,
|
||||||
"nullable": False,
|
"nullable": False,
|
||||||
"unique": False,
|
"unique": True,
|
||||||
"indexed": False,
|
"indexed": True,
|
||||||
"default": None,
|
"default": None,
|
||||||
"description": None,
|
"description": None,
|
||||||
"docstring": None,
|
"docstring": None,
|
||||||
@ -786,7 +786,8 @@ def test_migrate(mocker: MockerFixture):
|
|||||||
- 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
|
||||||
- remove unique: User.username
|
- remove unique: Category.slug
|
||||||
|
- add unique: User.username
|
||||||
- change column: length User.password
|
- change column: length User.password
|
||||||
- add unique_together: (name,type) of Product
|
- add unique_together: (name,type) of Product
|
||||||
- alter default: Config.status
|
- alter default: Config.status
|
||||||
@ -806,6 +807,7 @@ def test_migrate(mocker: MockerFixture):
|
|||||||
Migrate._merge_operators()
|
Migrate._merge_operators()
|
||||||
if isinstance(Migrate.ddl, MysqlDDL):
|
if isinstance(Migrate.ddl, MysqlDDL):
|
||||||
expected_upgrade_operators = {
|
expected_upgrade_operators = {
|
||||||
|
"ALTER TABLE `category` DROP INDEX `slug`",
|
||||||
"ALTER TABLE `category` MODIFY COLUMN `name` VARCHAR(200)",
|
"ALTER TABLE `category` MODIFY COLUMN `name` VARCHAR(200)",
|
||||||
"ALTER TABLE `category` MODIFY COLUMN `slug` VARCHAR(100) NOT NULL",
|
"ALTER TABLE `category` MODIFY COLUMN `slug` VARCHAR(100) NOT NULL",
|
||||||
"ALTER TABLE `config` ADD `user_id` INT NOT NULL COMMENT 'User'",
|
"ALTER TABLE `config` ADD `user_id` INT NOT NULL COMMENT 'User'",
|
||||||
@ -830,7 +832,7 @@ def test_migrate(mocker: MockerFixture):
|
|||||||
"ALTER TABLE `user` MODIFY COLUMN `is_active` BOOL NOT NULL COMMENT 'Is Active' DEFAULT 1",
|
"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 `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 `uid_user_usernam_9987ab` (`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)",
|
||||||
@ -838,6 +840,7 @@ def test_migrate(mocker: MockerFixture):
|
|||||||
"ALTER TABLE `email` MODIFY COLUMN `is_primary` BOOL NOT NULL DEFAULT 0",
|
"ALTER TABLE `email` MODIFY COLUMN `is_primary` BOOL NOT NULL DEFAULT 0",
|
||||||
}
|
}
|
||||||
expected_downgrade_operators = {
|
expected_downgrade_operators = {
|
||||||
|
"ALTER TABLE `category` ADD UNIQUE INDEX `slug` (`slug`)",
|
||||||
"ALTER TABLE `category` MODIFY COLUMN `name` VARCHAR(200) NOT NULL",
|
"ALTER TABLE `category` MODIFY COLUMN `name` VARCHAR(200) NOT NULL",
|
||||||
"ALTER TABLE `category` MODIFY COLUMN `slug` VARCHAR(200) NOT NULL",
|
"ALTER TABLE `category` MODIFY COLUMN `slug` VARCHAR(200) NOT NULL",
|
||||||
"ALTER TABLE `config` DROP COLUMN `user_id`",
|
"ALTER TABLE `config` DROP COLUMN `user_id`",
|
||||||
@ -853,7 +856,7 @@ def test_migrate(mocker: MockerFixture):
|
|||||||
"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 `user` ADD `avatar` VARCHAR(200) NOT NULL DEFAULT ''",
|
"ALTER TABLE `user` ADD `avatar` VARCHAR(200) NOT NULL DEFAULT ''",
|
||||||
"ALTER TABLE `user` DROP INDEX `idx_user_usernam_9987ab`",
|
"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",
|
||||||
"DROP TABLE IF EXISTS `email_user`",
|
"DROP TABLE IF EXISTS `email_user`",
|
||||||
"DROP TABLE IF EXISTS `newmodel`",
|
"DROP TABLE IF EXISTS `newmodel`",
|
||||||
@ -877,6 +880,7 @@ def test_migrate(mocker: MockerFixture):
|
|||||||
|
|
||||||
elif isinstance(Migrate.ddl, PostgresDDL):
|
elif isinstance(Migrate.ddl, PostgresDDL):
|
||||||
expected_upgrade_operators = {
|
expected_upgrade_operators = {
|
||||||
|
'DROP INDEX "uid_category_slug_e9bcff"',
|
||||||
'ALTER TABLE "category" ALTER COLUMN "name" DROP NOT NULL',
|
'ALTER TABLE "category" ALTER COLUMN "name" DROP NOT NULL',
|
||||||
'ALTER TABLE "category" ALTER COLUMN "slug" TYPE VARCHAR(100) USING "slug"::VARCHAR(100)',
|
'ALTER TABLE "category" ALTER COLUMN "slug" TYPE VARCHAR(100) USING "slug"::VARCHAR(100)',
|
||||||
'ALTER TABLE "category" ALTER COLUMN "created_at" TYPE TIMESTAMPTZ USING "created_at"::TIMESTAMPTZ',
|
'ALTER TABLE "category" ALTER COLUMN "created_at" TYPE TIMESTAMPTZ USING "created_at"::TIMESTAMPTZ',
|
||||||
@ -909,6 +913,7 @@ def test_migrate(mocker: MockerFixture):
|
|||||||
'CREATE UNIQUE INDEX "uid_user_usernam_9987ab" ON "user" ("username")',
|
'CREATE UNIQUE INDEX "uid_user_usernam_9987ab" ON "user" ("username")',
|
||||||
}
|
}
|
||||||
expected_downgrade_operators = {
|
expected_downgrade_operators = {
|
||||||
|
'CREATE UNIQUE INDEX "uid_category_slug_e9bcff" ON "category" ("slug")',
|
||||||
'ALTER TABLE "category" ALTER COLUMN "name" SET NOT NULL',
|
'ALTER TABLE "category" ALTER COLUMN "name" SET NOT NULL',
|
||||||
'ALTER TABLE "category" ALTER COLUMN "slug" TYPE VARCHAR(200) USING "slug"::VARCHAR(200)',
|
'ALTER TABLE "category" ALTER COLUMN "slug" TYPE VARCHAR(200) USING "slug"::VARCHAR(200)',
|
||||||
'ALTER TABLE "category" ALTER COLUMN "created_at" TYPE TIMESTAMPTZ USING "created_at"::TIMESTAMPTZ',
|
'ALTER TABLE "category" ALTER COLUMN "created_at" TYPE TIMESTAMPTZ USING "created_at"::TIMESTAMPTZ',
|
||||||
@ -935,7 +940,7 @@ def test_migrate(mocker: MockerFixture):
|
|||||||
'ALTER TABLE "product" ALTER COLUMN "body" TYPE TEXT USING "body"::TEXT',
|
'ALTER TABLE "product" ALTER COLUMN "body" TYPE TEXT USING "body"::TEXT',
|
||||||
'DROP INDEX "idx_product_name_869427"',
|
'DROP INDEX "idx_product_name_869427"',
|
||||||
'DROP INDEX "idx_email_email_4a1a33"',
|
'DROP INDEX "idx_email_email_4a1a33"',
|
||||||
'DROP INDEX "idx_user_usernam_9987ab"',
|
'DROP INDEX "uid_user_usernam_9987ab"',
|
||||||
'DROP INDEX "uid_product_name_869427"',
|
'DROP INDEX "uid_product_name_869427"',
|
||||||
'DROP TABLE IF EXISTS "email_user"',
|
'DROP TABLE IF EXISTS "email_user"',
|
||||||
'DROP TABLE IF EXISTS "newmodel"',
|
'DROP TABLE IF EXISTS "newmodel"',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user