美文网首页
自定义SQL解析器,实现HBase的SQL访问

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

作者: 星辰fml | 来源:发表于2019-04-27 06:30 被阅读0次

    hbase是什么

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

    • 开源的apache phoenix
    • 自定义sql解析器
      抛开重复造轮子的思维,下面利用antlr4来实现一个sql解析器,访问hbase的数据

    自定义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语法解析器

    • 首先第一步是将上面的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等操作,还有很多没有实现,但基本的思路是有了。

    相关文章

      网友评论

          本文标题:自定义SQL解析器,实现HBase的SQL访问

          本文链接:https://www.haomeiwen.com/subject/lxqhnqtx.html