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