自定义SQL解析器,实现HBase的SQL访问

2019-04-27  本文已影响0人  星辰fml

hbase是什么

hbase是一个列式存储的no-sql数据库,是google的bigtable的开源实现,能实现在hdfs数据的快速访问,但hbase只提供了java api和restapi来访问其的数据,既然是数据库,那能否提供sql方式来访问呢?

自定义sql解析器

自定义sql解析器主要包含以下步骤:

  1. 安装和启动hbase
  2. 定义sql语法文件
  3. 实现sql语句解析器
  4. 访问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语法解析器

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等操作,还有很多没有实现,但基本的思路是有了。

上一篇下一篇

猜你喜欢

热点阅读