2021SC@SDUSC
目录
概述:
前面我们主要通过关注SemanticAnalyzerFactory工厂类中get(conf, tree)这一方法获得对应的语义分析器sem的操作,总结了每次会话中SessionState对象的CommandType类型如何定义以及与语法分析器的对应关系。
接下来的主要分析主要基于通用的语义分析器SemanticAnalyzer进行,这也是处理大部分查询的语义分析器。在看SemanticAnalyzer之前,先关注一下BaseSemanticAnalyzer这个类。
BaseSemanticAnalyzer类
上文最后我们在验证时提到,BaseSemanticAnalyzer类是众多语义分析器,包括SemanticAnalyzer的抽象基类,不可以被实例化。其主要成员数据如下:
public abstract class BaseSemanticAnalyzer {
protected static final Logger STATIC_LOG = LoggerFactory.getLogger(BaseSemanticAnalyzer.class.getName());
protected final Hive db;
protected final HiveConf conf;
protected final QueryState queryState;
protected List<Task<?>> rootTasks;
protected FetchTask fetchTask;
protected final Logger LOG;
protected final LogHelper console;
…………
}
根据代码的官方注释可以知道对于每个查询都有一个单线程编译的实例。
该类之后定义了一系列与子类可能用到的通用变量(公共信息),如hive db、queryState等
另外,其他成员数据的含义分析如下:
//以符合ACID的方式写入的一组filesinkoperator。
程序此时需要记住它们,因为当我们构建时,我们还不知道id,需要在实际开始运行查询时返回并设置它。此外还包含只可以插入的sink。
protected Set<FileSinkDesc> acidFileSinks = new HashSet<FileSinkDesc>();
//查询是否包含ACID表或Insert-only (mm)表
//它们都需要DbTxnManager,都需要recordValidTxns来获取驱动程序中的锁
protected boolean transactionalInQuery;
protected HiveTxnManager txnManager;
public static final int HIVE_COLUMN_ORDER_ASC = 1;
public static final int HIVE_COLUMN_ORDER_DESC = 0;
public static final int HIVE_COLUMN_NULLS_FIRST = 0;
public static final int HIVE_COLUMN_NULLS_LAST = 1;
//传递给hooks的ReadEntities
protected HashSet<ReadEntity> inputs;
//传递给hooks的WriteEntities列表。
protected HashSet<WriteEntity> outputs;
//查询的沿袭信息。
protected LineageInfo linfo;
protected TableAccessInfo tableAccessInfo;
protected ColumnAccessInfo columnAccessInfo;
protected CacheUsage cacheUsage;
//被更新访问的列
protected ColumnAccessInfo updateColumnAccessInfo;
//set autocommit的值为true|false,它是一个对象,以确保它是{@code null},如果解析语句不是'set autocommit…'
private Boolean autoCommitValue;
下面来看一个重要的函数
public void analyze(ASTNode ast, Context ctx) throws SemanticException {
initCtx(ctx);
init(true);
analyzeInternal(ast);
}
这个函数它定义了语义分析器的入口:analyze(ASTNode,Context)。
可以看出,该入口函数做两件事:
一,把Context保存在成员变量ctx中;
二,调用analyzeInternal(ASTNode)完成分析工作,这个函数是抽象函数,应该被各个子类分别override,以完成相应的分析逻辑。
BaseSemanticAnalyzer类还定义了一些嵌套类,根据其名称和主要函数的内容可以大致知道,这涉及一些共用的数据结构及操作。如RowFormatParams类,它用来分析HQL中指定行格式的子树。
class RowFormatParams {
String fieldDelim = null;
String fieldEscape = null;
String collItemDelim = null;
…………
protected void analyzeRowFormat(ASTNode child) throws SemanticException {
child = (ASTNode) child.getChild(0);
int numChildRowFormat = child.getChildCount();
for (int numC = 0; numC < numChildRowFormat; numC++) {
ASTNode rowChild = (ASTNode) child.getChild(numC);
switch (rowChild.getToken().getType()) {
case HiveParser.TOK_TABLEROWFORMATFIELD:
case HiveParser.TOK_TABLEROWFORMATCOLLITEMS:
collItemDelim = unescapeSQLString(rowChild
.getChild(0).getText());
break;
……………………………
}
小结:
BaseSemanticAnalyzer这是一个抽象基类,不可以被实例化。
它定义了语义分析器的入口:analyze(ASTNode,Context),把Context保存在成员变量ctx中并调用analyzeInternal(ASTNode)完成分析工作,这个函数是抽象函数,应该被各个子类分别override,以完成相应的分析逻辑。
在该类中还维护了一些公共的信息,如Hive对象(主要包含了IMetaStoreClient的一个实现实例以及针对元数据的一些操作)、HiveConf对象、LOG对象等。该类定义了一些嵌套类,都是一些共用的数据结构及操作。如RowFormatParams类, StorageFormat类等,用来分析HQL中指定行格式的子树。
该类的最后还定义了一些工具函数,如操作字符串转义/反转义、获取列信息等。