自定义SQL解析器,实现HBase的SQL访问
2019-04-27 本文已影响0人
星辰fml
hbase是什么
hbase是一个列式存储的no-sql数据库,是google的bigtable的开源实现,能实现在hdfs数据的快速访问,但hbase只提供了java api和restapi来访问其的数据,既然是数据库,那能否提供sql方式来访问呢?
- 开源的apache phoenix
- 自定义sql解析器
抛开重复造轮子的思维,下面利用antlr4来实现一个sql解析器,访问hbase的数据
自定义sql解析器
自定义sql解析器主要包含以下步骤:
- 安装和启动hbase
- 定义sql语法文件
- 实现sql语句解析器
- 访问hbase
antlr
antlr是一款很强大的语法分析器,mysql、hive、spark、flink等都利用她来实现sql解析,antlr4更可以实现ALL(*)的语法分析。默认在antlr4中使用贪婪匹配原则。antlr
在以上的步骤中,安装和启动hbase就不进行讲解了,很简单,网上也有很多资料可以实现快速安装,我们直接从第2步开始
定义sql语法文件
grammar HBaseSQL ;
stat : selectSql
| deleteSql
;
selectSql : select column from table nl ;
deleteSql : delete from table (where condition)? nl ;
select : 'select' | 'SELECT' ;
delete : 'delete' | 'DELETE' ;
column : '*'
| col (',' col)*
;
col : STRING '.' STRING ;
from : 'from' | 'FROM' ;
table : STRING;
where : 'where' | 'WHERE' ;
condition : col op value ;
op : '>'
| '<'
| '='
| '!='
;
value : STRING
| INT
;
nl : ';'
| nl '\r'? '\n';
STRING : [a-zA-Z_]+ ;
INT : [0-9]+ ;
WS : [ \t] -> skip ;
上面的sql语法中只定义来select和delete语法,其他语法实现类似。
定义sql语法解析器
-
首先第一步是将上面的sql语法翻译成antlr的语句
configuration
generate -
实现监听器来监听antlr的节点解析
package com.antlr.hbasesql.listener;
import com.antlr.hbasesql.HBaseSQLBaseListener;
import com.antlr.hbasesql.HBaseSQLParser;
import com.antlr.hbasesql.client.SqlSchema;
/**
* @author zap
* @version 1.0, 2019/04/25
*/
public class HBaseSqlTreeListener extends HBaseSQLBaseListener {
private SqlSchema sqlSchema;
@Override
public void enterSelectSql(HBaseSQLParser.SelectSqlContext ctx) {
sqlSchema = new SqlSchema(ctx.select().getText());
}
@Override
public void enterColumn(HBaseSQLParser.ColumnContext ctx) {
sqlSchema.setColumns(ctx.getText());
}
@Override
public void enterTable(HBaseSQLParser.TableContext ctx) {
sqlSchema.setTable(ctx.getText());
}
public SqlSchema sqlSchema() {
return this.sqlSchema;
}
}
sql语法解析,并注册监听器
package com.antlr.hbasesql.client;
import com.antlr.hbasesql.HBaseSQLLexer;
import com.antlr.hbasesql.HBaseSQLParser;
import com.antlr.hbasesql.listener.HBaseSqlTreeListener;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTreeWalker;
/**
* @author zap
* @version 1.0, 2019/04/25
*/
public class SqlParser {
public static SqlSchema parse(String sql) {
CharStream stream = CharStreams.fromString(sql);
HBaseSQLLexer lexer = new HBaseSQLLexer(stream);
CommonTokenStream token = new CommonTokenStream(lexer);
HBaseSQLParser parser = new HBaseSQLParser(token);
// 开始解析语句,并产生一棵树
HBaseSQLParser.StatContext tree = parser.stat();
ParseTreeWalker walker = new ParseTreeWalker();
// 解析树时的监听器
HBaseSqlTreeListener listener = new HBaseSqlTreeListener();
walker.walk(listener, tree);
// 获取解析的sql信息
return listener.sqlSchema();
}
}
package com.antlr.hbasesql.client;
import com.antlr.hbasesql.hbase.HBaseClient;
import java.io.IOException;
/**
* 使用SQL语句访问HBase库
*
* @author zap
* @version 1.0, 2019/04/25
*/
public class HBaseSqlClient {
public static void main(String[] args) throws IOException {
String sql = "SELECT info.user,info.email FROM users;";
//TODO 解析sql语句
SqlSchema schema = SqlParser.parse(sql);
//TODO 查询HBase数据
HBaseClient hclient = new HBaseClient();
hclient.select(schema);
hclient.close();
}
}
最后
启动hbase,并创建其中的users表,定义info列族,并运行程序即可以看到数据的查询结果
hbase访问结果
如果在输入的sql语句中输入错误,我们来看看结果如何:
错误的sql语句
在未定义异常处理器的情况下,运行错误的sql后,将出现以下的错误:
错误结果
好了,我们的sql解析器就定义完成了,这里只定义来select、delete等操作,还有很多没有实现,但基本的思路是有了。