SparkSQL——UnresolvedPlan生成

plan创建的方法入口是SparkSession的sql方法中的parsePlan方法调用

parse方法将sql转换成语法树(使用的antlr),使用SqlBaseLexer、SqlBaseParser进行词法解析和语法解析。调用toResult函数从语法树生成plan。
生成plan的入口是astBuilder.visitSingleStatement(parser.singleStatement())


parse生成的语法树如下(sql:SELECT name FROM student
WHERE age>10 ):

生成未解析计划
parser.singleStatement()返回SingleStatementContext,对应语法树的顶点singleStatement

astBuilder.visitSingleStatement方法中是获取SingleStatementContext的statement,返回LogicalPlan

一般语法树上的节点对应的类是后面加Context,比如singleStatement对应类是SingleStatementContext。还有就是这种statement:statementDefault,是statement有多个实现,冒号后面就是对应的实现,statement对应的类是StatementDefaultContext.

visit(ctx.statement)
这里使用了观察者模式。
先看ctx.statement是获取的StatementContext,对应的实现类是StatementDefaultContext


再看visit方法,是调用对应tree的accept方法,这里就是StatementDefaultContext的accept

StatementDefaultContext的accept是调用对应visitor的visitStatementDefault方法。

visitStatementDefault方法是调用visitChildren

visitChildren方式是遍历子节点,调用对应的accept方法,最后聚合结果返回。
statement节点下面只有一个query节点,所以是调用query节点的accept方法。

QueryContext的accept方法是调用visitor的visitQuery方法

visitQuery方法调用plan方法创建了LogicalPlan。这里分别处理了queryTerm、queryOrganization、ctes。
queryTerm是单个查询的基本单元
queryOrganization是SQL查询中组织查询项的方式,例如排序、分组等
ctes是SQL中一种特殊的查询结构,用于定义临时的结果集

这里query节点只有queryTerm、queryOrganization

plan方法就是调用了typedVisit方法。就是调用对应的节点的accept方法将放回结果转换成LogicalPlan


queryTerm节点的accept方法对应就是QueryTermDefaultContext的accept方法,就是visitor的visitQueryTermDefault方法。

visitQueryTermDefault跟上面类似也是调用visitChildren方法

visitQueryTermDefault的子节点是queryPrimary,所以是调用对应实现类QueryPrimaryDefaultContext的accept方法。

QueryPrimaryDefaultContext的accept方法是调用visitor的visitQueryPrimaryDefault方法。

visitQueryPrimaryDefault同样是调用visitChildren,它的子节点是querySpecification。
调用的是RegularQuerySpecificationContext的accept方法,即visitor的visitRegularQuerySpecification


visitRegularQuerySpecification这个方法的返回值是LogicalPlan。
这个方法处理了全部子节点
selectClause、lateralView、whereClause、aggregationClause、havingClause、windowClause、fromClause,最后生成plan。
这个例子是只有selectClause、fromClause、whereClause三个节点。


fromClause下面的relation节点下面的relationPrimary节点调用plan方法,上面也说到plan方法,是调用visit的对应的方法。这里是调用visitTableName方法。


visitTableName处理了multipartIdentifier子节点。
multipartIdentifier用于明确指定数据库对象的完整路径,包括库名、表名和列名。

visitMultipartIdentifier方法中是获取parts节点的内容。parts是ErrorCapturingIdentifierContext集合。


只有一个ErrorCapturingIdentifierContext子节点,调用它的getText方法。

getText方法就不断向下遍历子节点并调用对应的getText,合并到一起。这里不就在往下track了。
ErrorCapturingIdentifierContext在这里结果就是 student

所以visitTableName中tableId就是 student。生成UnresolvedRelation对象。UnresolvedRelation的含义是没有和catalog关联的表,它是LogicalPlan的子类。

到这里,visitRegularQuerySpecification中from节点处理完成了。
然后调用withSelectQuerySpecification处理剩下的select和where

withSelectQuerySpecification是中withWhereClause处理where、visitNamedExpressionSeq处理select。
流程基本和处理from一样。

最后生成了一个Project对象(LogicalPlan子类)。
UnresolvedPlan生成流程如下图

  • 24
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值