-
Notifications
You must be signed in to change notification settings - Fork 0
SQLGraphExplorer‐8
使用 antlr4 匹配各种布尔代数公式,简化并转换成 SOP 格式
- 简化布尔代数:(B=b AND B=b) -> (B=b)
- 理论需要:上次说的模糊之处,selection 的运算需要将过滤条件标准化成 sop
- 冗余过滤:无关项置为 TRUE
使用 antlr4 匹配 SOP 格式,并进行切分
简单地实现了一下,举个例子:
-
CKTuples:
$[(ax_B,x_Bc),x_B=b]$ -
RA:
$\Pi_{A,B}(\sigma_{A=a\ AND\ B=b}(R1))$ ;$\Pi_{A,B}(\sigma_{B=b\ AND\ C=c}(R2))$
之前给的 RA,是用旧的 antlr 来写的?我想稍微改造一下,具体讲可以不用连接数据库,直接实现 relational algebra -> sql,但没成功,于是我想找个相似工具,于是找到了这个:
-
JITRAX(Java Interpretation Tool for Relational Algebra Expressions, 关系代数表达式的 Java 解释工具)是一个用 Java 编写的关系代数的解释器,旨在改善那些开始学习关系数据库的学生的学习过程。
-
JITRAX 没有在关系代数中实现任何查询引擎。为了可视化查询的结果,使用了一种更巧妙的技术:将用关系代数编写的表达式转换为 SQL 中的等价表达式,并在 PostgreSQL 管理系统上运行后者。这不是很棒吗?
-
该工具是拉古纳大学 Tguayco Gutiérrez González 在 JesúS M.Jorge Santiso 指导下在拉古纳大学研究生工作中开发的。
-
支持关系代数的下列运算符:projection、selection、union、diff、intersection、cartesian production、division。

- 它使用 antlr4 来解析 Relational Algebra 语法,并将其转换为 sql 语句。
- 上面这部分被称为 Realtional Algebra Interpreter,是我需要的,它是一个独立的模块,可以直接摘下来用。
- 于是我将其摘下来,并进行了一些魔改后,放入 Tools 工具箱中。
ra
│ CustomErrorListener.java #ErrorListener
│ RelationalAlgebraInterpreter.java #RA -> Sql,是一个Wrapper,封装了相关方法
│
├─adt # DataBase的模拟
│ Attribute.java
│ Database.java
│ DataType.java
│ Datum.java
│ Query.java
│ Row.java
│ Table.java
│
└─grammar
PreprocessingEvalVisitor.java #将RA进行预处理
RelationalAlgebra.g4 #RA语法文件
RelationalAlgebra.interp
RelationalAlgebra.tokens
RelationalAlgebraBaseListener.java
RelationalAlgebraBaseVisitor.java
RelationalAlgebraEvalVisitor.java #执行RA -> Sql的具体转换
RelationalAlgebraLexer.interp
RelationalAlgebraLexer.java
RelationalAlgebraLexer.tokens
RelationalAlgebraListener.java
RelationalAlgebraParser.java
RelationalAlgebraVisitor.java输入的 Relational Algebra:
PROJECT [Course, Section] (
Course *
(PROJECT [InstructorID] (
SELECT [name = "Bailes"] (
(Instructor))))
);
执行转换的 Java 代码
String ra = "PROJECT [Course, Section] (Course * (PROJECT [InstructorID] (SELECT [name = \"Bailes\"] ((Instructor)))));";
String sql = "SELECT Course, Section FROM Course NATURAL JOIN ((SELECT InstructorID FROM Instructor WHERE (name = 'Bailes'))) AS q1;";
RelationalAlgebraInterpreter interpreter = new RelationalAlgebraInterpreter(new Database("defaultDatabase"));
Assert.assertEquals(sql, interpreter.translate(ra));得到的 Sql 结果:
SELECT Course, Section FROM Course NATURAL JOIN ((SELECT InstructorID FROM Instructor WHERE (name = 'Bailes'))) AS q1;在原来的框架中加入了 Expression 生成过程。
目前跑通所有 (Sql -> Expression -> inverse() -> CKTuples -> RA -> Sql) 的 Test-Case:
输入:
create table R1
A VARCHAR2(255),
B VARCHAR2(255)
) tablespace USERS pctfree 10 initrans 1 maxtrans 255 storage (
initial 64K next 1M minextents 1 maxextents unlimited\n
);
create table R2
B VARCHAR2(255),
C VARCHAR2(255)
) tablespace USERS pctfree 10 initrans 1 maxtrans 255 storage (
initial 64K next 1M minextents 1 maxextents unlimited\n
);
create table R3
A VARCHAR2(255),
C VARCHAR2(255)
) tablespace USERS pctfree 10 initrans 1 maxtrans 255 storage (
initial 64K next 1M minextents 1 maxextents unlimited\n
);
SELECT A,C FROM R1 JOIN R2 WHERE B=b;输出:
SELECT R1.A, R1.B FROM R1 WHERE (R1.A = R3.A) AND (B = b);
SELECT R2.C, R2.B FROM R2 WHERE (R2.C = R3.C) AND (B = b);输入:
create table A1 (
A11 VARCHAR2(255),
A12 VARCHAR2(255),
A13 VARCHAR2(255),
A14 VARCHAR2(255),
A15 VARCHAR2(255),
A16 VARCHAR2(255),
B11 VARCHAR2(255)
) tablespace USERS pctfree 10 initrans 1 maxtrans 255 storage (
initial 64K next 1M minextents 1 maxextents unlimited
);
create table A2 (
A21 VARCHAR2(255),
A22 VARCHAR2(255),
A23 VARCHAR2(255),
A24 VARCHAR2(255),
A25 VARCHAR2(255),
A26 VARCHAR2(255),
B21 VARCHAR2(255)
) tablespace USERS pctfree 10 initrans 1 maxtrans 255 storage (
initial 64K next 1M minextents 1 maxextents unlimited
);
create table B (
B01 VARCHAR2(255),
B02 VARCHAR2(255),
B03 VARCHAR2(255),
B04 VARCHAR2(255)
) tablespace USERS pctfree 10 initrans 1 maxtrans 255 storage (
initial 64K next 1M minextents 1 maxextents unlimited
);
create table C (
GH VARCHAR2(255),
XM VARCHAR2(255),
GJ VARCHAR2(255)
) tablespace USERS pctfree 10 initrans 1 maxtrans 255 storage (
initial 64K next 1M minextents 1 maxextents unlimited
);
SELECT
A1.A11 AS GH, /*工号*/
A1.A12 AS XM, /*姓名*/
A1.A13 AS GJ /*国籍*/
FROM
A1 /*在职人员基本信息*/
JOIN B /*机构基本情况*/
ON A1.B11 = B.B01
AND B.B02 <= '#{ETL_DT}'
AND B.B03 > '#{ETL_DT}'
WHERE
LENGTH (NVL (A1.A11, '')) > 0 /*员工编号有值的数据*/
AND A1.A14 <= '#{ETL_DT}'
AND A1.A15 > '#{ETL_DT}'
UNION ALL --从减员人员基本信息表中获取除了状态为'非正常在岗'的人员信息
SELECT
A2.A21 AS GH, /*工号*/
A2.A22 AS XM, /*姓名*/
A2.A23 AS GJ /*国籍*/
FROM
A2
JOIN B /*机构基本情况*/
ON A2.B21 = B.B01
AND B.B02 <= '#{ETL_DT}'
AND B.B03 > '#{ETL_DT}'
WHERE
LENGTH (NVL (A2.A21, '')) > 0 /*员工编号有值的数据*/
AND A2.A24 <= '#{ETL_DT}'
AND A2.A25 > '#{ETL_DT}'
AND A2.A26 <> '0101';输出:
SELECT
A1.A11, A1.A13, A1.B11, A1.A15, A1.A14, A1.A16, A1.A12
FROM
A1
WHERE
(A1.A11 = C.GH)
AND (A1.A13 = C.GJ)
AND (A1.A12 = C.XM)
AND (LENGTH(NVL(A1.A11,'')) > 0)
AND (A1.A14 <= '#{ETL_DT}')
AND (A1.A15 > '#{ETL_DT}');
SELECT
A2.A22, A2.A21, A2.A23, A2.B21, A2.A25, A2.A24, A2.A26
FROM
A2
WHERE
(A2.A22 = C.XM)
AND (A2.A21 = C.GH)
AND (A2.A23 = C.GJ)
AND (LENGTH(NVL(A2.A21,'')) > 0)
AND (A2.A24 <= '#{ETL_DT}')
AND (A2.A25 > '#{ETL_DT}')
AND (A2.A26 <> '0101');
AND (B.B03 > '#{ETL_DT}');- 结果sql仅是打印出来,并没有显示在图中
- 还有些部分尚未覆盖:CASE、Function、复杂嵌套等