一、示例代码
我们从一句常用的sql开始分析
import spark.implicits._
import spark.sql
sql("SELECT * FROM ods.personal_info limit 10").show()
其中包含两个函数调用,sql()和show(),我们依次来分析下
二、sql()
1、SparkSession
它是使用Dataset和DataFrame API对Spark编程的入口点
//使用Spark执行SQL查询,将结果作为“DataFrame”返回。
def sql(sqlText: String): DataFrame = {
Dataset.ofRows(self, sessionState.sqlParser.parsePlan(sqlText))
}
这里要分析来两处:
1、sessionState.sqlParser.parsePlan(sqlText)
2、Dataset.ofRows()
我们先看下第1处,它是通过ParserInterface调用其子类AbstractSqlParser来实现
2、AbstractSqlParser
//为给定的SQL字符串创建逻辑计划
override def parsePlan(sqlText: String): LogicalPlan = parse(sqlText) { parser =>
//获取将ParseTree转换为AST的构建器(访问者)
//这里用到了ANTLR的知识
astBuilder.visitSingleStatement(parser.singleStatement()) match {
case plan: LogicalPlan => plan
case _ =>
val position = Origin(None, None)
throw QueryParsingErrors.sqlStatementUnsupportedError(sqlText, position)
}
}
protected def parse[T](command: String)(toResult: SqlBaseParser => T): T = {
logDebug(s"Parsing command: $command")
//1、将sql转换成字符流
//2、将字符流全部转换成大写,这大大简化了对流的词法分析,同时我们可以保持原始命令
//3、词法分析是基于Hive的org.apache.hadoop.hive.ql.parse.ParseDriver.ANTLRNoCaseStringStream
//4、Hive词法分析是基于ANTLR4
val lexer = new SqlBaseLexer(new UpperCaseCharStream(CharStreams.fromString(command)))
lexer.removeErrorListeners()
lexer.addErrorListener(ParseErrorListener)
//使用指定的令牌源和默认令牌通道 构造一个新的 CommonTokenStream
val tokenStream = new CommonTokenStream(lexer)
//解析
val parser = new SqlBaseParser(tokenStream)
parser.addParseListener(PostProcessor)
parser.removeErrorListeners()
parser.addErrorListener(ParseErrorListener)
//spark.sql.legacy.setopsPrecedence.enabled 默认false
//当设置为true并且括号未指定求值顺序时,设置操作将在查询中从左向右执行。当设置为false且括号未指定求值顺序时,INTERSECT操作将在任何UNION、EXCEPT和MINUS操作之前执行。
parser.legacy_setops_precedence_enabled = conf.setOpsPrecedenceEnforced
//spark.sql.legacy.exponentLiteralAsDecimal.enabled 默认值 false
//当设置为true时,具有指数的文字(例如1E-30)将被解析为Decimal而不是Double。
parser.legacy_exponent_literal_as_decimal_enabled = conf.exponentLiteralAsDecimalEnabled
//spark.sql.ansi.enabled 默认 false
//如果为true,Spark SQL将使用符合ANSI的方言,而不是符合Hive的方言。
//
parser.SQL_standard_keyword_behavior = conf.ansiEnabled
try {
try {
// 首先,尝试使用可能更快的SLL模式进行解析
parser.getInterpreter.setPredictionMode(Pre

最低0.47元/天 解锁文章
1675

被折叠的 条评论
为什么被折叠?



