Skip to content

SQLGraphExplorer‐8

Xin edited this page Dec 19, 2023 · 4 revisions

Simplifier

使用 antlr4 匹配各种布尔代数公式,简化并转换成 SOP 格式

  1. 简化布尔代数:(B=b AND B=b) -> (B=b)
  2. 理论需要:上次说的模糊之处,selection 的运算需要将过滤条件标准化成 sop
  3. 冗余过滤:无关项置为 TRUE

Spliter

使用 antlr4 匹配 SOP 格式,并进行切分

CKTuples -> Sql

CKTuples -> RA

简单地实现了一下,举个例子:

  • 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 -> Sql

之前给的 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。

JITRAX.png

  1. 它使用 antlr4 来解析 Relational Algebra 语法,并将其转换为 sql 语句。
  2. 上面这部分被称为 Realtional Algebra Interpreter,是我需要的,它是一个独立的模块,可以直接摘下来用。
  3. 于是我将其摘下来,并进行了一些魔改后,放入 Tools 工具箱中。

修改后的简略介绍

raCustomErrorListener.java		#ErrorListenerRelationalAlgebraInterpreter.java	#RA -> Sql,是一个Wrapper,封装了相关方法
│
├─adt	# DataBase的模拟Attribute.javaDatabase.javaDataType.javaDatum.javaQuery.javaRow.javaTable.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

Example

输入的 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;

Sql -> Expression

在原来的框架中加入了 Expression 生成过程。

Test-Case

目前跑通所有 (Sql -> Expression -> inverse() -> CKTuples -> RA -> Sql) 的 Test-Case:

test-case-0

输入:

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);

test-case-1

输入:

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、复杂嵌套等

Clone this wiki locally