From ddf4856a85ca29470091871c9e5ddbc42ad9a221 Mon Sep 17 00:00:00 2001 From: logan Date: Mon, 25 May 2026 01:56:26 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=8D=87=E7=BA=A7FLOAT/DOUBLE=E5=AE=A1?= =?UTF-8?q?=E6=A0=B8=E8=A7=84=E5=88=99=E4=B8=BAERROR=E7=BA=A7=E5=88=AB-?= =?UTF-8?q?=E8=A6=86=E7=9B=96CREATE+ALTER-MODIFY-CHANGE-=E9=98=B2=E6=AD=A2?= =?UTF-8?q?=E7=94=9F=E4=BA=A7=E7=B2=BE=E5=BA=A6=E4=B8=A2=E5=A4=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app/services/mysql_audit_rules.py | 38 ++++++++++++++++------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/backend/app/services/mysql_audit_rules.py b/backend/app/services/mysql_audit_rules.py index 1bf40ad..42ba2b4 100644 --- a/backend/app/services/mysql_audit_rules.py +++ b/backend/app/services/mysql_audit_rules.py @@ -392,25 +392,41 @@ def check_mysql_ddl_004(sql_clean: str, sql_upper: str, report: AuditReportV2, r code="MYSQL-DDL-005", name="DDLCheckFloatDouble", category=RuleCategory.DDL, - severity=Severity.WARNING, + severity=Severity.ERROR, db_type="mysql", - description="不建议使用 FLOAT/DOUBLE 类型,建议使用 DECIMAL 替代", + description="禁止使用 FLOAT/DOUBLE 类型存储金额/数值数据,必须使用 DECIMAL 保证精度", config={"enabled": True}, - message_template="表 '{table}' 的字段 '{column}' 使用了 {ctype} 类型,建议改为 DECIMAL", + message_template="表 '{table}' 的字段 '{column}' 使用了 {ctype} 类型,存在精度丢失风险,必须使用 DECIMAL 替代(如 DECIMAL(16,4))", )) def check_mysql_ddl_005(sql_clean: str, sql_upper: str, report: AuditReportV2, rule: AuditRuleV2) -> None: - """强制float/double类型变更为decimal类型。""" - if not re.search(r"\bCREATE\s+TABLE\b", sql_upper, re.IGNORECASE): - return - table_name = _extract_table_name(sql_upper, sql_clean) or "unknown" - columns = _extract_column_definitions(sql_upper) - for col in columns: - if col["type"].upper() in ("FLOAT", "DOUBLE"): + """禁止 FLOAT/DOUBLE 类型,强制使用 DECIMAL 保证精度。""" + # 检查 CREATE TABLE + if re.search(r"\bCREATE\s+TABLE\b", sql_upper, re.IGNORECASE): + table_name = _extract_table_name(sql_upper, sql_clean) or "unknown" + columns = _extract_column_definitions(sql_upper) + for col in columns: + if col["type"].upper() in ("FLOAT", "DOUBLE", "REAL"): + report.findings.append(AuditFindingV2( + rule_code=rule.code, + rule_name=rule.name, + level=rule.severity, + message=rule.message_template.format(table=table_name, column=col["name"], ctype=col["type"]), + )) + + # 检查 ALTER TABLE ADD/MODIFY/CHANGE COLUMN + alter_match = re.search(r"\bALTER\s+TABLE\s+[`\"']?(\w+)", sql_upper, re.IGNORECASE) + if alter_match: + table_name = alter_match.group(1) + # 匹配 ADD/MODIFY/CHANGE COLUMN 中出现的 FLOAT/DOUBLE 类型 + float_pattern = r"(?:ADD|MODIFY|CHANGE)\s+(?:COLUMN\s+)?[`\"']?(\w+)[`\"']?\s+(?:FLOAT|DOUBLE|REAL)\b" + for m in re.finditer(float_pattern, sql_upper, re.IGNORECASE): + col_name = m.group(1) + ctype = "FLOAT" if "FLOAT" in m.group(0).upper() else ("DOUBLE" if "DOUBLE" in m.group(0).upper() else "REAL") report.findings.append(AuditFindingV2( rule_code=rule.code, rule_name=rule.name, level=rule.severity, - message=rule.message_template.format(table=table_name, column=col["name"], ctype=col["type"]), + message=rule.message_template.format(table=table_name, column=col_name, ctype=ctype), ))