mysql实现vpd_基于JDBC实现VPD:SQL解析篇
接著之前的文章《淺談基于JDBC實現(xiàn)虛擬專用數(shù)據(jù)庫(VPD)》的內(nèi)容,今天我們重點來說一下SQL解析的問題。
從架構(gòu)上我們可以看出來,如果要基于JDBC做VPD,不能繞開的一個問題,就是要解析SQL,那么如何解析SQL呢?其實可供選擇的方案還是很多的,比如JSqlParser、Saprk的Catalyst,亦或是直接使用Antlr,不過這里我還是更推薦使用Apache的Calcite。
首先,我們需要構(gòu)建一個解析器,這里為了方便,使用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);
然后,構(gòu)建一顆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語法都會被轉(zhuǎn)換,我們的demo使用select語句,類似的,還有SqlInsert,SqlUpdate,SqlJoin等,解析Sql是一個非常細致的工作,有興趣的同學(xué)也可以讀一下Antlr的Sql語法文件,也很有意思。
解析Sql只是整個VPD中的一環(huán),我們還需要進行Sql的構(gòu)建。舉個簡單,我們來構(gòu)建一個簡單的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);
}
}
好了,今天就寫到這了,希望對大家能有所啟發(fā),如果你對Calcite有興趣,可以與我討論,接下來,也許會進一步說說構(gòu)建Sql的事...
作為延伸閱讀,推薦大家讀讀王蒙大神的BLOG。非常有幫助,我以前也轉(zhuǎn)過他的文章
總結(jié)
以上是生活随笔為你收集整理的mysql实现vpd_基于JDBC实现VPD:SQL解析篇的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 在大城市工作几年才可以整租房屋
- 下一篇: mysql 事务sqlserver_MY