Plain is headed towards 1.0! Subscribe for development updates →

 1from __future__ import annotations
 2
 3from typing import TYPE_CHECKING
 4
 5from plain.models.backends.base.validation import BaseDatabaseValidation
 6from plain.preflight import PreflightResult
 7
 8if TYPE_CHECKING:
 9    from plain.models.fields import Field
10
11    from .base import MySQLDatabaseWrapper
12
13
14class DatabaseValidation(BaseDatabaseValidation):
15    # Type hint: narrow connection type to MySQL-specific wrapper
16    connection: MySQLDatabaseWrapper
17
18    def preflight(self) -> list[PreflightResult]:
19        issues = super().preflight()
20        issues.extend(self._check_sql_mode())
21        return issues
22
23    def _check_sql_mode(self) -> list[PreflightResult]:
24        if not (
25            self.connection.sql_mode & {"STRICT_TRANS_TABLES", "STRICT_ALL_TABLES"}
26        ):
27            return [
28                PreflightResult(
29                    fix=f"{self.connection.display_name} Strict Mode is not set for the database connection. "
30                    f"{self.connection.display_name}'s Strict Mode fixes many data integrity problems in "
31                    f"{self.connection.display_name}, such as data truncation upon insertion, by "
32                    "escalating warnings into errors. It is strongly "
33                    "recommended you activate it.",
34                    id="mysql.strict_mode_not_enabled",
35                    warning=True,
36                )
37            ]
38        return []
39
40    def check_field_type(self, field: Field, field_type: str) -> list[PreflightResult]:
41        """
42        MySQL has the following field length restriction:
43        No character (varchar) fields can have a length exceeding 255
44        characters if they have a unique index on them.
45        MySQL doesn't support a database index on some data types.
46        """
47        errors = []
48        if (
49            field_type.startswith("varchar")
50            and field.primary_key
51            and (field.max_length is None or int(field.max_length) > 255)
52        ):
53            errors.append(
54                PreflightResult(
55                    fix=f"{self.connection.display_name} may not allow unique CharFields to have a max_length "
56                    "> 255.",
57                    obj=field,
58                    id="mysql.unique_charfield_max_length_too_long",
59                    warning=True,
60                )
61            )
62
63        return errors