mysql实现vpd_基于JDBC实现VPD:SQL解析篇

本文介绍了如何基于JDBC和Apache Calcite解析MySQL SQL,以实现虚拟专用数据库(VPD)。通过构建SQL解析器和AST树,遍历并处理不同类型的SQL语句,如SELECT、INSERT、UPDATE等,为VPD的实现打下基础。
摘要由CSDN通过智能技术生成

接着之前的文章《浅谈基于JDBC实现虚拟专用数据库(VPD)》的内容,今天我们重点来说一下SQL解析的问题。

从架构上我们可以看出来,如果要基于JDBC做VPD,不能绕开的一个问题,就是要解析SQL,那么如何解析SQL呢?其实可供选择的方案还是很多的,比如JSqlParser、Saprk的Catalyst,亦或是直接使用Antlr,不过这里我还是更推荐使用Apache的Calcite。

首先,我们需要构建一个解析器,这里为了方便,使用Mysql语法

SqlParser.Config config = SqlParser.configBuilder()

.setLex(Lex.MYSQL) //使用mysql 语法

.build();

String sql = "select id,name,age FROM orders";

SqlParser sqlParser = SqlParser

.create(sql, config);

然后,构建一颗AST树

SqlNode sqlNode = sqlParser.parseStmt();

接下来,就需要各种分支判断,来对这个语法树进行遍历,举个简单的例子,我们将标示,以及select项打印出来。

if(SqlKind.SELECT.equals(sqlNode.getKind())){

SqlSelect sqlSelect = (SqlSelect) sqlNode;

SqlNode from=sqlSelect.getFrom();

SqlNode where=sqlSelect.getWhere();

SqlNodeList selectList=sqlSelect.getSelectList();

if(SqlKind.IDENTIFIER.equals(from.getKind())){

System.out.println(from.toString());

}

selectList.getList().forEach(x->{

System.out.println("==> "+x);

});

}

所有的SQL语法都会被转换,我们的demo使用select语句,类似的,还有SqlInsert,SqlUpdate,SqlJoin等,解析Sql是一个非常细致的工作,有兴趣的同学也可以读一下Antlr的Sql语法文件,也很有意思。

解析Sql只是整个VPD中的一环,我们还需要进行Sql的构建。举个简单,我们来构建一个简单的sql查询

SqlParserPos sqlParserPos = new SqlParserPos(1, 1);

SqlIdentifier all = new SqlIdentifier("*", null, sqlParserPos);

SqlIdentifier o = new SqlIdentifier("o", null, sqlParserPos);

SqlNodeList snl = new SqlNodeList(sqlParserPos);

snl.add(all);

SqlSelect sqls = new SqlSelect(sqlParserPos,null,snl,o,null,null,null,null,null,null,null);

System.out.println(sqls);

完整代码如下:

package cn.flinkhub.bigdata;

import org.apache.calcite.config.Lex;

import org.apache.calcite.sql.*;

import org.apache.calcite.sql.parser.SqlParseException;

import org.apache.calcite.sql.parser.SqlParser;

import org.apache.calcite.sql.parser.SqlParserPos;

public class VPDDemo {

public static void main(String[] args) {

SqlParser.Config config = SqlParser.configBuilder()

.setLex(Lex.MYSQL) //使用mysql 语法

.build();

String sql = "select id,name,age FROM orders";

SqlParser sqlParser = SqlParser

.create(sql, config);

SqlNode sqlNode = null;

try {

System.out.println("sql = "+ sql);

sqlNode = sqlParser.parseStmt();

if(SqlKind.SELECT.equals(sqlNode.getKind())){

SqlSelect sqlSelect = (SqlSelect) sqlNode;

SqlNode from=sqlSelect.getFrom();

SqlNode where=sqlSelect.getWhere();

SqlNodeList selectList=sqlSelect.getSelectList();

if(SqlKind.IDENTIFIER.equals(from.getKind())){

System.out.println(from.toString());

}

selectList.getList().forEach(x->{

System.out.println("==> "+x);

});

}

} catch (SqlParseException e) {

throw new RuntimeException("", e);

}

SqlParserPos sqlParserPos = new SqlParserPos(1, 1);

SqlIdentifier all = new SqlIdentifier("*", null, sqlParserPos);

SqlIdentifier o = new SqlIdentifier("o", null, sqlParserPos);

SqlNodeList snl = new SqlNodeList(sqlParserPos);

snl.add(all);

SqlSelect sqls = new SqlSelect(sqlParserPos,null,snl,o,null,null,null,null,null,null,null);

System.out.println(sqls);

}

}

好了,今天就写到这了,希望对大家能有所启发,如果你对Calcite有兴趣,可以与我讨论,接下来,也许会进一步说说构建Sql的事...

作为延伸阅读,推荐大家读读王蒙大神的BLOG。非常有帮助,我以前也转过他的文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值