Fix create/drop indexes in every migration (#377)
* Add `__eq__` method for `Index`instances * tests: add Index test case * refactor: compare index instances before set hash and eq func to class * fix: sort fields when generating index hash * docs: update changlog * fix style issue * refactor: use CustomIndex instead of postgres special HashIndex * Check tortoise version before patch Index * Add comment * Add comment for why > work --------- Co-authored-by: dbf <somnium@riseup.net>
This commit is contained in:
parent
f93faa8afb
commit
7d22518c74
@ -16,6 +16,7 @@
|
||||
- Fix configuration file reading error when containing Chinese characters. (#286)
|
||||
- sqlite: failed to create/drop index. (#302)
|
||||
- PostgreSQL: Cannot drop constraint after deleting or rename FK on a model. (#378)
|
||||
- Fix create/drop indexes in every migration. (#377)
|
||||
- Sort m2m fields before comparing them with diff. (#271)
|
||||
|
||||
#### Changed
|
||||
|
@ -1,4 +1,5 @@
|
||||
import hashlib
|
||||
from __future__ import annotations
|
||||
|
||||
import importlib
|
||||
import os
|
||||
from datetime import datetime
|
||||
@ -6,6 +7,7 @@ from pathlib import Path
|
||||
from typing import Dict, Iterable, List, Optional, Set, Tuple, Type, Union, cast
|
||||
|
||||
import asyncclick as click
|
||||
import tortoise
|
||||
from dictdiffer import diff
|
||||
from tortoise import BaseDBAsyncClient, Model, Tortoise
|
||||
from tortoise.exceptions import OperationalError
|
||||
@ -202,21 +204,25 @@ class Migrate:
|
||||
|
||||
@classmethod
|
||||
def _handle_indexes(cls, model: Type[Model], indexes: List[Union[Tuple[str], Index]]) -> list:
|
||||
ret: list = []
|
||||
if tortoise.__version__ > "0.22.2":
|
||||
# The min version of tortoise is '0.11.0', so we can compare it by a `>`,
|
||||
# tortoise>0.22.2 have __eq__/__hash__ with Index class since 313ee76.
|
||||
return indexes
|
||||
if index_classes := set(index.__class__ for index in indexes if isinstance(index, Index)):
|
||||
# Leave magic patch here to compare with older version of tortoise-orm
|
||||
# TODO: limit tortoise>0.22.2 in pyproject.toml and remove this function when v0.9.0 released
|
||||
for index_cls in index_classes:
|
||||
if index_cls(fields=("id",)) != index_cls(fields=("id",)):
|
||||
|
||||
def index_hash(self) -> str:
|
||||
h = hashlib.new("MD5", usedforsecurity=False) # type:ignore[call-arg]
|
||||
h.update(
|
||||
self.index_name(cls.ddl.schema_generator, model).encode()
|
||||
+ self.__class__.__name__.encode()
|
||||
)
|
||||
return h.hexdigest()
|
||||
def _hash(self) -> int:
|
||||
return hash((tuple(sorted(self.fields)), self.name, self.expressions))
|
||||
|
||||
for index in indexes:
|
||||
if isinstance(index, Index):
|
||||
index.__hash__ = index_hash # type:ignore[method-assign,assignment]
|
||||
ret.append(index)
|
||||
return ret
|
||||
def _eq(self, other) -> bool:
|
||||
return type(self) is type(other) and self.__dict__ == other.__dict__
|
||||
|
||||
setattr(index_cls, "__hash__", _hash)
|
||||
setattr(index_cls, "__eq__", _eq)
|
||||
return indexes
|
||||
|
||||
@classmethod
|
||||
def _get_indexes(cls, model, model_describe: dict) -> Set[Union[Index, Tuple[str, ...]]]:
|
||||
|
7
tests/indexes.py
Normal file
7
tests/indexes.py
Normal file
@ -0,0 +1,7 @@
|
||||
from tortoise.indexes import Index
|
||||
|
||||
|
||||
class CustomIndex(Index):
|
||||
def __init__(self, *args, **kw) -> None:
|
||||
super().__init__(*args, **kw)
|
||||
self._foo = ""
|
@ -3,6 +3,9 @@ import uuid
|
||||
from enum import IntEnum
|
||||
|
||||
from tortoise import Model, fields
|
||||
from tortoise.indexes import Index
|
||||
|
||||
from tests.indexes import CustomIndex
|
||||
|
||||
|
||||
class ProductType(IntEnum):
|
||||
@ -33,6 +36,10 @@ class User(Model):
|
||||
|
||||
products: fields.ManyToManyRelation["Product"]
|
||||
|
||||
class Meta:
|
||||
# reverse indexes elements
|
||||
indexes = [CustomIndex(fields=("is_superuser",)), Index(fields=("username", "is_active"))]
|
||||
|
||||
|
||||
class Email(Model):
|
||||
email_id = fields.IntField(primary_key=True)
|
||||
|
@ -2,6 +2,9 @@ import datetime
|
||||
from enum import IntEnum
|
||||
|
||||
from tortoise import Model, fields
|
||||
from tortoise.indexes import Index
|
||||
|
||||
from tests.indexes import CustomIndex
|
||||
|
||||
|
||||
class ProductType(IntEnum):
|
||||
@ -31,6 +34,9 @@ class User(Model):
|
||||
intro = fields.TextField(default="")
|
||||
longitude = fields.DecimalField(max_digits=12, decimal_places=9)
|
||||
|
||||
class Meta:
|
||||
indexes = [Index(fields=("username", "is_active")), CustomIndex(fields=("is_superuser",))]
|
||||
|
||||
|
||||
class Email(Model):
|
||||
email = fields.CharField(max_length=200)
|
||||
|
@ -3,6 +3,7 @@ from pathlib import Path
|
||||
import pytest
|
||||
import tortoise
|
||||
from pytest_mock import MockerFixture
|
||||
from tortoise.indexes import Index
|
||||
|
||||
from aerich.ddl.mysql import MysqlDDL
|
||||
from aerich.ddl.postgres import PostgresDDL
|
||||
@ -10,6 +11,7 @@ from aerich.ddl.sqlite import SqliteDDL
|
||||
from aerich.exceptions import NotSupportError
|
||||
from aerich.migrate import MIGRATE_TEMPLATE, Migrate
|
||||
from aerich.utils import get_models_describe
|
||||
from tests.indexes import CustomIndex
|
||||
|
||||
# tortoise-orm>=0.21 changes IntField constraints
|
||||
# from {"ge": 1, "le": 2147483647} to {"ge": -2147483648, "le": 2147483647}
|
||||
@ -608,7 +610,7 @@ old_models_describe = {
|
||||
"description": None,
|
||||
"docstring": None,
|
||||
"unique_together": [],
|
||||
"indexes": [],
|
||||
"indexes": [Index(fields=("username", "is_active")), CustomIndex(fields=("is_superuser",))],
|
||||
"pk_field": {
|
||||
"name": "id",
|
||||
"field_type": "IntField",
|
||||
|
Loading…
x
Reference in New Issue
Block a user