sqlor/aidocs/mysqlor.md
2025-10-05 11:24:24 +08:00

12 KiB
Raw Blame History

以下是针对你提供的 Python 代码编写的 Markdown 格式技术文档,适用于项目内部文档或开发者参考手册。


MySqlor 类技术文档

概述

MySqlor 是一个用于操作 MySQL 数据库的 SQL 构建与元数据提取类,继承自 SQLor 基类。它封装了与 MySQL 相关的 DDL 模板、类型映射、分页查询、表结构查询等功能,支持从数据库中提取表、字段、主键、外键、索引等元信息,并提供模型与数据库之间的类型转换机制。

该类主要配合 pymysql 驱动使用,通过动态生成 SQL 查询语句实现对数据库结构的反向工程(Reverse Engineering)和 ORM 映射支持。


继承关系

class MySqlor(SQLor)
  • 父类:SQLor
  • 所属模块:.sor.SQLor

导入依赖

from appPublic.argsConvert import ArgsConvert, ConditionConvert
from .sor import SQLor
from .const import ROWS
from .ddl_template_mysql import mysql_ddl_tmpl
  • ArgsConvert, ConditionConvert: 参数与条件转换工具。
  • ROWS: 分页常量定义。
  • mysql_ddl_tmpl: MySQL 的 DDL 模板(如建表语句模板)。

类属性

ddl_template

ddl_template = mysql_ddl_tmpl
  • 类型:dict
  • 描述:MySQL 的 DDL 建表语句模板,用于根据模型生成建表 SQL。
  • 来源:导入自 ddl_template_mysql.py 文件中的 mysql_ddl_tmpl 变量。

db2modelTypeMapping

将 MySQL 数据库字段类型映射为应用层模型类型(Model Type)。

数据库类型 模型类型
tinyint short
smallint short
mediumint long
int long
bigint long
decimal float
double float
float float
char char
varchar str
tinyblob / tinytext text
mediumblob / mediumtext text
blob / text text
longblob bin
longtext text
binary / varbinary text
date date
time time
datetime datetime
timestamp datestamp
year short

说明:

  • BLOB 类型统一映射为 bin 或 text,取决于大小。
  • 时间类型做了精细化区分,例如 timestamp 映射为 datestamp,便于后续处理。

model2dbTypemapping

将模型类型映射回数据库字段类型。

模型类型 数据库类型
date date
time date
timestamp timestamp
str varchar
char char
short int
long bigint
float double
text longtext
bin longblob
file longblob

注意:time 类型在数据库中仍以 date 存储,可能需结合上下文解析;实际应考虑使用 time 类型优化。


类方法

isMe(cls, name)

判断当前数据库驱动是否匹配。

参数

  • name (str):数据库连接驱动名称(如 'pymysql')

返回值

  • bool:若为 'pymysql' 则返回 True,否则 False

示例

if MySqlor.isMe('pymysql'):
    print("This is MySQL")

实例方法

grammar(self)

⚠️ 当前存在语法错误!

此方法尝试返回一个包含 select 语句模板的字典,但引用了未定义的变量 select_stmt。

代码问题

def grammar(self):
    return {
        'select': select_stmt,  # ❌ NameError: name 'select_stmt' is not defined
    }

建议修复

应确保 select_stmt 已在作用域内定义,或改为字符串形式:

def grammar(self):
    return {
        'select': 'SELECT $[fields]$ FROM $[table]$ WHERE $[where]$',
    }

placeHolder(self, varname, pos=None)

返回参数占位符格式(用于预编译 SQL)。

参数

  • varname (str):变量名
  • pos (int, optional):位置参数索引(未使用)

返回值

  • 若 varname == '__mainsql__',返回空字符串 ''
  • 其他情况返回标准占位符 '%s'(适配 pymysql)

用途

用于构建参数化查询,防止 SQL 注入。

示例

cursor.execute(sql, values)  # values 将以 %s 替代

dataConvert(self, dataList)

将输入数据标准化为元组格式,供 SQL 执行使用。

参数

  • dataList (dict 或 list[dict]):待转换的数据

返回值

  • tuple:提取出的值组成的元组

行为逻辑

  • 如果是字典 → 提取 .values()
  • 如果是字典列表 → 提取每个元素的 'value' 字段
  • 最终转为 tuple

示例

data1 = {'a': 1, 'b': 2}
# 结果: (1, 2)

data2 = [{'value': 1}, {'value': 2}]
# 结果: (1, 2)

pagingSQLmodel(self)

返回 MySQL 分页查询模板(基于 LIMIT offset, count)。

当前代码问题

def pagingSQLmodel(self):
    return """..."""
    return """..."""  # ❌ 第二个 return 永远不会执行

正确版本(推荐)

def pagingSQLmodel(self):
    return """
        SELECT * FROM (%s) A 
        ORDER BY $[sort]$
        LIMIT $[from_line]$, $[rows]$
    """

占位符说明

占位符 含义
%s 子查询原始 SQL
$[sort]$ 排序字段(如 id ASC)
$[from_line]$ 起始行偏移量(offset)
$[rows]$ 每页记录数(limit)

示例输出

SELECT * FROM (
    SELECT id, name FROM users
) A
ORDER BY id DESC
LIMIT 10, 20

tablesSQL(self)

生成查询当前数据库所有表名及其注释的 SQL。

返回值

  • str:查询 INFORMATION_SCHEMA.TABLES 的 SQL 语句

SQL 内容

SELECT 
    lower(TABLE_NAME) AS name, 
    lower(TABLE_COMMENT) AS title 
FROM INFORMATION_SCHEMA.TABLES 
WHERE TABLE_SCHEMA = 'your_db_name'

动态填充

  • 使用 self.dbdesc.get('dbname', 'unknown') 获取数据库名

输出字段

字段 说明
name 小写表名
title 表注释(小写)

fieldsSQL(self, tablename=None)

查询指定表的所有字段元信息。

参数

  • tablename (str, optional):表名,若不传则查询所有表

返回值

  • str:查询 information_schema.columns 的 SQL

SQL 片段

SELECT
    lower(column_name) AS name,
    data_type AS type,
    CASE 
        WHEN character_maximum_length IS NULL THEN NUMERIC_PRECISION
        ELSE character_maximum_length 
    END AS length,
    NUMERIC_SCALE AS dec,
    lower(is_nullable) AS nullable,
    column_comment AS title,
    lower(table_name) AS table_name
FROM information_schema.columns
WHERE lower(TABLE_SCHEMA) = 'your_dbname'
  AND lower(table_name) = 'your_table'  -- 可选

输出字段说明

字段 说明
name 字段名(小写)
type 数据类型
length 长度或精度
dec 小数位数
nullable 是否可为空(yes/no)
title 字段注释
table_name 所属表名(小写)

fkSQL(self, tablename=None)

查询外键约束信息。

参数

  • tablename (str, optional):仅查询与该表相关的外键

返回值

  • str:查询外键关系的 SQL

SQL 逻辑

联查三张系统表:

  • KEY_COLUMN_USAGE
  • TABLES
  • REFERENTIAL_CONSTRAINTS

查询内容

字段 说明
拥有者 Schema 名称
父表名称 被引用表
父表字段 被引用列
子表名称 引用表
子表字段 引用列
约束名 外键约束名称
表注释 子表的注释
约束更新规则 ON UPDATE 规则
约束删除规则 ON DELETE 规则

过滤条件:只返回 REFERENCED_TABLE_NAME IS NOT NULL 的记录(即真正的外键)


pkSQL(self, tablename=None)

查询指定表的主键字段。

参数

  • tablename (str):必须传入表名

返回值

  • str:查询主键字段的 SQL

SQL

SELECT DISTINCT column_name AS name 
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE 
WHERE table_name='your_table' 
  AND constraint_name='PRIMARY'

注意事项

  • table_name 会被强制转为小写
  • 使用 DISTINCT 避免重复

indexesSQL(self, tablename=None)

查询索引信息(包括唯一索引)。

参数

  • tablename (str, optional):指定表名

返回值

  • str:获取索引元数据的 SQL

SQL

SELECT DISTINCT
    lower(index_name) AS index_name,
    CASE NON_UNIQUE
        WHEN 1 THEN 'unique'
        ELSE ''
    END AS is_unique,
    lower(column_name) AS column_name
FROM information_schema.statistics
WHERE table_schema = 'your_dbname'
  AND table_name = 'your_table'  -- 可选

输出字段

字段 说明
index_name 索引名称(小写)
is_unique 是否唯一索引(值为 'unique' 或空)
column_name 索引包含的字段(单个字段一行)

注意:复合索引会拆分为多行显示。


使用示例

# 初始化 MySqlor 实例
dbdesc = {'dbname': 'testdb'}
mysqlor = MySqlor(dbdesc=dbdesc)

# 获取所有表
sql_tables = mysqlor.tablesSQL()
print(sql_tables)

# 获取某表字段
sql_fields = mysqlor.fieldsSQL('users')
print(sql_fields)

# 获取主键
sql_pk = mysqlor.pkSQL('users')

# 分页模板
paging_model = mysqlor.pagingSQLmodel()
final_sql = paging_model % "(SELECT * FROM users)" \
    .replace("$[sort]$", "id DESC") \
    .replace("$[from_line]$", "0") \
    .replace("$[rows]$", "10")

已知问题与改进建议

问题 描述 建议
grammar() 方法报错 引用了未定义的 select_stmt 定义常量或抛出 NotImplementedError
pagingSQLmodel() 多余返回 第二个 return 不可达 删除无效行
dataConvert() 缺少健壮性检查 对非 dict/list 输入无保护 添加类型校验和异常处理
placeHolder 忽略 pos 参数 参数未使用 可移除或用于未来扩展

总结

MySqlor 是一个功能完整的 MySQL 元数据操作类,具备以下能力:

✅ 类型双向映射
✅ 表/字段/主键/外键/索引信息提取
✅ 分页 SQL 模板支持
✅ 参数占位符兼容 pymysql
✅ 支持模型驱动开发(MDD / ORM)

建议结合模板引擎(如 Jinja2)进一步提升 SQL 拼接灵活性。


📝 文档版本:v1.0
📅 更新时间:2025-04-05
© 项目公共组件库团队