Hive代码分析报告(六): 语义分析①

2021SC@SDUSC

目录

概述

代码分析

小结


概述

经过前面的分析,我们知道,Hive处理一条HQL语句,分前端和编译器部分,前端(Cli)主要负责接受用户在命令行上输入的信息,然后准备执行并将执行的结果返回。而后面的工作由Compiler完成。

编译流程的第一步主要由HiveParser部分完成,该类是编译的入口,入参是一条字符串的sql输出是一棵抽象语法树,ASTNode 是树的头结点,前面的分析知道,其拥有树相关操作、获取孩子节点等方法。

之后编译阶段的任务是语义分析,语义分析首先将抽象语法树,解析为一个QB(query block),这个过程主要由SemanticAnalyzer.java (语义分析器)完成

SemanticAnalyzer.java代码量超10000行,可见其内容的丰富性。根据粗略的浏览,发现与之有密切关系的类还有SemanticAnalyzerFactory.java,BaseSemanticAnalyzer.java等十几个类。

代码分析

根据前面生成AST后的调用顺序,之后AST树会作为参数,被SemanticAnalyzerFactory.get()方法调用,下面我们来分析一下这个函数

public static BaseSemanticAnalyzer get(QueryState queryState, ASTNode tree) throws SemanticException {

    BaseSemanticAnalyzer sem = getInternal(queryState, tree);

    if(queryState.getHiveOperation() == null) {

      String query = queryState.getQueryString();

      if(query != null && query.length() > 30) {

        query = query.substring(0, 30);

      }

      String msg = "Unknown HiveOperation for query='" + query + "' queryId=" + queryState.getQueryId();

      //throw new IllegalStateException(msg);

      LOG.debug(msg);

    }

    return sem;

  }

首先,我们注意到,这个函数的返回类型是一个BaseSemanticAnalyzer类对象sem,然后是对query语句的一些字符串处理。

其中这个过程的关键是调用getInternal函数,直接来看这个函数

private static BaseSemanticAnalyzer getInternal(QueryState queryState, ASTNode tree)

      throws SemanticException {

    if (tree.getToken() == null) {

      throw new RuntimeException("Empty Syntax Tree");

    } else {

      HiveOperation opType = commandType.get(tree.getType());

      queryState.setCommandType(opType);

      switch (tree.getType()) {

      case HiveParser.TOK_EXPLAIN:

        return new ExplainSemanticAnalyzer(queryState);

      case HiveParser.TOK_EXPLAIN_SQ_REWRITE:

        return new ExplainSQRewriteSemanticAnalyzer(queryState);

      case HiveParser.TOK_LOAD:

        return new LoadSemanticAnalyzer(queryState);

      case HiveParser.TOK_EXPORT:

        if (UpdateDeleteSemanticAnalyzer.isAcidExport(tree)) {

          return new UpdateDeleteSemanticAnalyzer(queryState);

        }

        return new ExportSemanticAnalyzer(queryState);

      case HiveParser.TOK_IMPORT:

        return new ImportSemanticAnalyzer(queryState);

      case HiveParser.TOK_REPL_DUMP:

        return new ReplicationSemanticAnalyzer(queryState);

      …………………………………………………………略

     

这个函数的主体部分很明确,主要通过连续的多个switch case条件选择语句来确定返回SemanticAnalyzer语法分析器的类型。

综合来看,经过分析,这两个函数的主要作用是

I.设置本次会话SessionState对象的CommandType,这些类型定义为常量HiveOperation.XXX;

II.创建并返回一个合适的语法分析器(都继承自BasicSemanticAnalyzer),经过对照和分析,主要的对应关系如下表所示

类型

对应语义分析器

TOK_EXPLAIN

ExplainSemanticAnalyzer

TOK_LOAD

LoadSemanticAnalyzer

TOK_CREATEDATABASE/DROPDATABASE/ SWITCHDATABASE/DROPTABLE/ DROPVIEW/DESCDATABASE/ DESCTABLE/DESCFUNCTION/ MSCK/ALTERXXX_XXX/ SHOWXXX/CREATEINDEX/ DROPINDEX/LOCKTABLE/ UNLOCKTABLE/CREATEROLE/ DROPROLE/ GRANT/REVOKE/ GRANT_ROLE/ REVOKE_ROLE

SemanticAnalyzer

TOK_CREATEFUNCTION/DROPFUNCTION

FunctionSemanticAnalyzer

其它

SemanticAnalyzer

再回过头来看BaseSemanticAnalyzer sem = getInternal(queryState, tree);这句

因为getInternal()函数中,它的返回对象实际上并不只是BaseSemanticAnalyzer这么简单,根据读入AST的不同会有多种类型,再结合BaseSemanticAnalyzer sem,再结合该类的命名,可以推测,上表中的各种类型,都是由BaseSemanticAnalyzer派生而来。再查阅这些类的内容,发现,推测完全正确。

BaseSemanticAnalyzer 开头部分代码:

public abstract class BaseSemanticAnalyzer {

  protected static final Logger STATIC_LOG = LoggerFactory.getLogger(BaseSemanticAnalyzer.class.getName());

  // Assumes one instance of this + single-threaded compilation for each query.

  protected final Hive db;

  protected final HiveConf conf;

  protected final QueryState queryState;

  protected List<Task<?>> rootTasks;

  protected FetchTask fetchTask;

…………………………………………

…………………………………………

关于这个BaseSemanticAnalyzer类,我将在之后进行探讨。不过可以暂时知道该类是语义分析器的抽象基类,不可以被实例化。

小结

由此总结结论如下:

一、BaseSemanticAnalyzer,它是所有语义分析器的基类;

二、SemanticAnalyzerFactory工厂类,它能根据AST的根节点构造出合适的语义分析器。

三、而SemanticAnalyzer实际上是一个通用的语义分析器,这也是处理大部分查询的语义分析器。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值