이 기사는 java에 대한 관련 지식을 제공합니다. Java 어휘 분석기의 DDL 재귀 응용 프로그램에 대한 자세한 설명을 주로 소개합니다. 도움이 필요한 친구들에게 도움이 되길 바랍니다. 모든 사람.
추천 학습: "java 비디오 튜토리얼"
기성 도구가 없으므로 직접 작성하세요
우리는 주로 PyCharm
을 개발에 사용한다는 점을 고려하여 , 마침 jetbrains
에서는 플러그인 개발을 위한 SDK
도 제공하므로 UI
수준을 고려할 필요가 없습니다. 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
Python
에 필요한 모델
코드를 생성하려면 DDL
문만 가져오면 됩니다. 예를 들어 다음 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
`userName` varchar(20) DEFAULT NULL COMMENT '用户名', `password` varchar(100) DEFAULT NULL COMMENT '密码',
Python
에 필요한 템플릿으로 변환하는 것입니다. 🎜🎜시작하기 전에는 문자열을 구문 분석하는 것 이상으로 간단하다고 생각했지만, 실제로 시작하고 보니 주요 문제점은 다음과 같습니다. 🎜🎜x = 20🎜🎜우리의 일반적인 개발 경험에 따르면 이 명령문은 다음 부분: 🎜
x
는 변수를 나타냅니다.=
는 할당 기호를 나타냅니다. 20
할당 결과를 나타냅니다.🎜VAR x🎜🎜GE =🎜🎜VAL 100🎜🎜This 구문 분석 프로세스는 컴파일 중입니다. 이 원칙을 "어휘 구문 분석"이라고 합니다. 지금 스크립트에 대해 "컴파일 원칙"이라는 단어를 들으면 혼란스러울 수 있습니다. 이러한 구문을 생성하는 매우 간단한 어휘 구문 분석기를 작성할 수 있습니다. 결과. 🎜
VAR
는 변수를 나타내고 GE
는 할당 기호를 나타냅니다. "=" 및 VAL
은 할당 결과를 나타냅니다. 이제 이 세 가지 상태를 기억하는 데 집중해야 합니다. 🎜🎜문자를 순차적으로 읽고 구문 분석할 때 프로그램은 아래와 같이 이러한 상태 사이를 앞뒤로 전환합니다. 🎜🎜
VAR
상태에 들어갑니다. GE
상태로 들어갑니다. 🎜🎜마찬가지로 이러한 상태가 만족되지 않으면 초기 상태로 돌아가서 새로운 상태를 다시 확인하게 됩니다. 🎜🎜그림만 보면 다소 추상적이므로 핵심 코드를 직접 살펴보겠습니다. 🎜
} else if (value == '`' && pStatus == Status.BASE_INIT) { result.tokenType = DDLTokenType.FI; result.text.append(value); }
TokenType
은 다음의 세 가지 상태에 해당합니다. 그림은 열거형 값으로 간단히 표현됩니다. 🎜`userName` varchar(20) DEFAULT NULL COMMENT '用户名',
TokenType
을 정의해야 합니다. 🎜🎜🎜는 그림에 설명된 프로세스와 일치합니다. 상태에 따라 현재 문자만 결정하면 됩니다. 🎜🎜두 번째 그림은 상태 간 전환입니다. 🎜
🎜🎜는 여러 상태에 따라 다른 case
를 입력하고 다른 case
에서 다른 상태로 점프해야 하는지 여부를 판단합니다(INIT
상태 입력 상태 나중에 다시 생성됩니다.) 🎜🎜예: x = 20
:🎜🎜첫 번째 선택은 VAR
상태로 들어가고 그 다음 문자는 당연히 공백이 다시 입력됩니다. 38행의 초기 상태로 인해 다음 문자 =
를 다시 확인하여 GE
상태로 들어갑니다. 🎜🎜스크립트가 ab = 30
인 경우:
첫 번째 문자는 역시 VAR
상태로 들어가는 a이고, 두 번째 문자는 b입니다. 여전히 문자이므로 36행을 입력하면 상태가 변경되지 않고 문자 b가 추가됩니다. 후속 단계는 이전 예와 동일합니다. 🎜🎜더 이상 말할 필요가 없습니다. 단일 테스트를 직접 실행해 보시면 이해하실 것입니다. 🎜
简单的解析完成后来看看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
原理类似,首先还是要看出规律(也就是语法):
CREATE TABLE
开头。)
结尾。根据我们需要解析的数据种类,我这里定义了这个枚举:
然后在初始化类型时进行判断赋值:
由于需要解析的数据不少,所以这里的判断条件自然也就多了。
针对于DDL
的语法规则,我们这里还有需要有特殊处理的地方;比如解析具体字段信息时如何关联起来?
举个例子:
`userName` varchar(20) DEFAULT NULL COMMENT '用户名', `password` varchar(100) DEFAULT NULL COMMENT '密码',
这里我们解析出来的数据得有一个映射关系:
所以我们只能一个字段的全部信息解析完成并且关联好之后才能解析下一个字段。
于是这里我采用了递归的方式进行解析(不一定是最好的,欢迎大家提出更优的方案)。
} else if (value == '`' && pStatus == Status.BASE_INIT) { result.tokenType = DDLTokenType.FI; result.text.append(value); }
当当前字符为 ”`“ 符号时,将状态置为 “FI”(FieldInfo),同时当解析到为 “,” 符号时便进入递归处理。
可以理解为将这一段字符串单独提取出来处理:
`userName` varchar(20) DEFAULT NULL COMMENT '用户名',
接着再将这段字符递归调用当前方法再次进行解析,这时便按照字段名称、类型、长度、注释的规则解析即可。
同时既然存在递归,还需要将子递归的数据关联起来,所以我在返回结果中新增了一个pid
的字段,这个也容易理解。
默认值为 0,一旦递归后便自增 +1,保证每次递归的数据都是唯一的。
用同样的方法在解析主键时也是先将整个字符串提取出来:
PRIMARY KEY (`id`)
只不过是 “P” 打头 “)” 结尾。
} else if (value == 'P' && pStatus == Status.BASE_INIT) { result.tokenType = DDLTokenType.P_K; result.text.append(value); }
也是将整段字符串递归解析,再递归的过程中进行状态切换P_K ---> P_K_V
最终获取到主键。
所以通过对刚才那段DDL
解析得到的结果如下:
这样每个字段也通过了pid
进行了区分关联。
所以现在只需要对这个词法解析器进行封装,便可以提供一个简单的API
来获取表中的数据了。
推荐学习:《java视频教程》
위 내용은 자바 어휘 분석기 DDL 재귀 애플리케이션의 상세 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!