intellij plugin
既然没有现成的工具那就自己写一个吧,演示效果如下:
考虑到我们主要是用 PyCharm
开发,正好 jetbrains
也提供了 SDK
用于开发插件,所以 UI
层面可以不用额外考虑了。
使用流程很简单,只需要导入 DDL
语句就可以生成 Python
所需要的 Model
代码。
例如导入以下 DDL:
CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `userName` varchar(20) DEFAULT NULL COMMENT '用户名', `password` varchar(100) DEFAULT NULL COMMENT '密码', `roleId` int(11) DEFAULT NULL COMMENT '角色ID', PRIMARY KEY (`id`), ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8
便会生成对应的 Python 代码:
class User(db.Model): __tablename__ = 'user' id = db.Column(db.Integer, primary_key=True, autoincrement=True) userName = db.Column(db.String) # 用户名 password = db.Column(db.String) # 密码 roleId = db.Column(db.Integer) # 角色ID
词法解析
仔细对比源文件及目标代码会很容易找出规律,无非就是解析出表名、字段、及字段的属性(是否为主键、类型、长度),最后再转换为 Python
所需要的模板即可。
在我动手之前我认为是非常简单的,无非就是解析字符串,但实际上手后发现不是那么回事;主要是有以下几个问题:
- 如何识别出表名称?
- 同样的如何识别出字段名称,同时还得关联上该字段的类型、长度、注释。
- 如何识别出主键?
总结一句话,如何通过一系列规则识别出一段字符串中的关键信息,这同样也是 MySQL Server 所做的事情。
在开始真正解析 DDL 之前,先来看下一段简单的脚本如何解析:
x = 20
按照我们平时开发的经验,这条语句分为以下几部分:
x
表示变量
=
表示赋值符号
20
表示赋值结果
所以我们对这段脚本的解析结果应当为:
VAR x GE = VAL 100
这个解析过程在编译原理中称为”词法解析“,可能大家听到编译原理
这几个字就头大(我也是);对于刚才那段脚本我们可以编写一个非常简单的词法解析器生成这样的结果。
状态迁移
再开始之前先捋一下思路,可以看到上文的结果中通过 VAR
表示变量、GE
表示赋值符号 ”=“、VAL
表示赋值结果,现在需要重点记住这三个状态。
在依次读取字符解析时,程序就是在这几个状态中来回切换,如下图:
- 默认为初始状态。
- 当字符为字母时进入
VAR
状态。
- 当字符为 ”=“ 符号时进入
GE
状态。
同理,当不满足这几个状态时候又会回到初始从而再次确认新的状态。
光看图有点抽象,直接来看核心代码:
public class Result{ public TokenType tokenType ; public StringBuilder text = new StringBuilder(); }
首先定义了一个结果类,收集最终的解析结果;其中的 TokenType
就对应了图中的三种状态,简单的用枚举值来表示。
public enum TokenType { INIT, VAR, GE, VAL }
首先对应到第一张图:初始化状态。
需要对当前解析的字符定义一个 TokenType
:
和图中描述的流程一致,判断当前字符给定一个状态即可。
接着对应到第二张图:状态之间的转换。
会根据不同的状态进入不同的 case
,在不同的 case
中判断是否应当跳转到其他状态(进入 INIT
状态后会重新生成状态)。
举个例子: x = 20
:
首选会进入 VAR
状态,接着下一个字符为空格,自然在 38 行中重新进入初始状态,导致再次确定下一个字符 =
进入 GE
状态。
当脚本为 ab = 30
: 第一个字符为 a 也是进入 VAR
状态,第二个字符为 b,依然为字母,所以进入 36 行,状态不会改变,同时将 b 这个字符追加进来;后续步骤就和上一个例子一致了。
多说无益,建议大家自己跑一下单测就会明白:github.com/crossoverJi…