ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Hive代码分析报告(十):语义分析⑤

2021-12-01 19:58:00  阅读:284  来源: 互联网

标签:分析 case qb 语义 Hive CTE QB doPhase1 tab


2021SC@SDUSC

目录

概述

补充说明doPhase1()

getMetaData(QB, ReadEntity)分析


概述

上一篇文章中,我分析了doPhase1()函数,这是语义分析的起始阶段,程序的最终目标是将AST的数据载入QB,doPhase1这一阶段主要思想是递归地遍历AST,建立一些必要的映射关系,从而将一些关键信息传给QB,如表、子查询的别名信息、内部子句的名字、聚合操作信息等,进而上面所有这些映射关系都保存在QB/QBParseInfo 中。

补充说明doPhase1()

再来看一次此处代码的大致结构和工作流程

public boolean doPhase1(ASTNode ast, QB qb, Phase1Ctx ctx_1, PlannerContext plannerCtx)

      throws SemanticException {

            。。。。。。。。。。。。。。。。略。。。。。。。。

        case HiveParser.TOK_SELECT://select类型的token

        qb.countSel();//对qb做标记

        qbp.setSelExprForClause(ctx_1.dest, ast);

        。。。。。。。。。。。。。。。。。略。。。。。。

       case HiveParser.TOK_WHERE://where类型token

       //对where的孩子进行处理,为什么是ast.getChild(0)?这个是和之前的HiveParser.g结构相辅相成的。

        qbp.setWhrExprForClause(ctx_1.dest, ast);

        if (!SubQueryUtils.findSubQueries((ASTNode) ast.getChild(0)).isEmpty())

            queryProperties.setFilterWithSubQuery(true);

        break;

      。。。。。。。。。。。。。。。。略。。。。。。。。

      case HiveParser.TOK_GROUPBY:

      case HiveParser.TOK_ROLLUP_GROUPBY:

      case HiveParser.TOK_CUBE_GROUPBY:

      case HiveParser.TOK_GROUPING_SETS:

      。。。。。。。。。。。。略。。。。。。。。

          if (!skipRecursion) {

      // Iterate over the rest of the children

      int child_count = ast.getChildCount();

      for (int child_pos = 0; child_pos < child_count && phase1Result; ++child_pos) {

        // Recurse

        phase1Result = phase1Result && doPhase1(

            (ASTNode)ast.getChild(child_pos), qb, ctx_1, plannerCtx);

      }

    }

    。。。。。。。。。。。。。。。略。。。。。。。。。

大体过程:

doPhase1对ASTTree中的每个元素的TOK类型进行case,针对于不同的case对节点数据进行填充。for遍历整棵ASTTree,中间对每个元素递归调用doPhase1,这种方式是一种深度优先搜索的算法。

经过一轮深度优先遍历,不带元数据的QB树就生成了。

getMetaData(QB, ReadEntity)分析

doPhase1执行完毕之后得到QB,QB里边的只是一些关键字还有一些表的名字,但是和hdfs的文件路径对应不起来,所以需要元数据metaData映射关系,之后在SemanticAnalyzer中调用了 getMetaData()函数。

private void getMetaData(QB qb, ReadEntity parentInput)

      throws HiveException {

LOG.info("Get metadata for source tables");

根据日志信息,可以知道,该函数的目标是从源头表中获取元数据

List<String> tabAliases = new ArrayList<String>(qb.getTabAliases());

上面这个列表记录了别名,因为别名可能在中间被修改

 Map<String, ObjectPair<String, ReadEntity>> aliasToViewInfo =

        new HashMap<String, ObjectPair<String, ReadEntity>>();

上面这个MAP的作用,我的理解是:

跟踪视图别名,查看名称和读取实体

例如:对于像'select * from V3'的查询,其中V3 -> V2, V2 -> V1, V1 -> T

map用于跟踪输入的依赖项及其父类。
   

 Map<String, String> sqAliasToCTEName = new HashMap<String, String>();

    for (String alias : tabAliases) {

      String tabName = qb.getTabNameForAlias(alias);

      String cteName = tabName.toLowerCase();

      从tabNameToTabObject缓存中获取表的详细信息:

Table tab = getTableObjectByName(tabName, false);

      if (tab != null) {

        // do a deep copy, in case downstream changes it.

        tab = new Table(tab.getTTable().deepCopy());

      }

      if (tab == null ||

          tab.getDbName().equals(SessionState.get().getCurrentDatabase())) {

        Table materializedTab = ctx.getMaterializedTable(cteName);

        if (materializedTab == null) {

          // we first look for this alias from CTE, and then from catalog.

          CTEClause cte = findCTEFromName(qb, cteName);

          if (cte != null) {

            if (!cte.materialize) {

              addCTEAsSubQuery(qb, cteName, alias);

              sqAliasToCTEName.put(alias, cteName);

              continue;

            }

            tab = materializeCTE(cteName, cte);

          }

        } else {

          tab = materializedTab;

        }

      }

      throw new SemanticException(e.getMessage(), e);

    }

  }

这个函数多次出现词CTE,而且程序中有很多涉及CTE的函数,这个CTE是做什么的?查阅资料了解到,CTE是很多数据库系统中常用的一种公用表达式

公用表表达式(CTE)可以被认为是在单个SELECT,INSERT,UPDATE,DELETE或CREATE VIEW语句的执行范围内定义的临时结果集。CTE类似于派生表,因为它不作为对象存储,并且仅在查询期间持续。与派生表不同,CTE可以是自引用的,并且可以在同一查询中多次引用。

CTE由表示CTE的表达式名称,AS关键字和SELECT语句组成。定义CTE后,可以在SELECT,INSERT,UPDATE或DELETE语句中像表或视图一样引用它。CTE也可以在CREATE VIEW语句中用作其定义SELECT语句的一部分。

小结:

getMetaData():获取源表、目标表、的元数据(主要是schema 等信息)
获取的元数据同样存储在QB/QBParseInfo 中。
①获取source table 的元数据,如果一个table 实际上是一个view,将其重写为view 的定义;
②递归的为每个子查询中的源表获得元数据;
③获取所有destination table/dir/local dir 的元数据;

至此,才把比较完整的信息传给QB

标签:分析,case,qb,语义,Hive,CTE,QB,doPhase1,tab
来源: https://blog.csdn.net/weixin_45846560/article/details/121663008

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有