Skip to content
Closed
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ class SqlParser extends StandardTokenParsers with PackratParsers {
protected val SUBSTRING = Keyword("SUBSTRING")
protected val SQRT = Keyword("SQRT")
protected val ABS = Keyword("ABS")
protected val ADD = Keyword("ADD")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will remove it


// Use reflection to find the reserved words defined in this class.
protected val reservedWords =
Expand All @@ -151,7 +152,7 @@ class SqlParser extends StandardTokenParsers with PackratParsers {
EXCEPT ^^^ { (q1: LogicalPlan, q2: LogicalPlan) => Except(q1, q2)} |
UNION ~ opt(DISTINCT) ^^^ { (q1: LogicalPlan, q2: LogicalPlan) => Distinct(Union(q1, q2)) }
)
| insert | cache
| insert | cache | unCache
)

protected lazy val select: Parser[LogicalPlan] =
Expand Down Expand Up @@ -181,11 +182,25 @@ class SqlParser extends StandardTokenParsers with PackratParsers {
val overwrite: Boolean = o.getOrElse("") == "OVERWRITE"
InsertIntoTable(r, Map[String, Option[String]](), s, overwrite)
}

protected lazy val addCache: Parser[LogicalPlan] =
ADD ~ CACHE ~ TABLE ~> ident ~ AS ~ select <~ opt(";") ^^ {
case tableName ~ as ~ s =>
CacheTableAsSelectCommand(tableName,s)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be removed, as mentioned by @marmbrus in this comment.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will remove it


protected lazy val cache: Parser[LogicalPlan] =
(CACHE ^^^ true | UNCACHE ^^^ false) ~ TABLE ~ ident ^^ {
case doCache ~ _ ~ tableName => CacheCommand(tableName, doCache)
CACHE ~ TABLE ~> ident ~ opt(AS) ~ opt(select) <~ opt(";") ^^ {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think opt(AS ~ select) would be better here? Otherwise illegal statements like CACHE TABLE AS and CACHE TABLE SELECT * FROM t would both be allowed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually opt(AS ~> select), since we don't care the semantic value returned by AS.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your comments. Yes,It is better to add as opt(AS ~> select)

case tableName ~ None ~ None =>
CacheCommand(tableName, true)
case tableName ~ as ~ Some(plan) =>
CacheTableAsSelectCommand(tableName,plan)
}

protected lazy val unCache: Parser[LogicalPlan] =
UNCACHE ~ TABLE ~> ident <~ opt(";") ^^ {
case tableName => CacheCommand(tableName, false)
}

protected lazy val projections: Parser[Seq[Expression]] = repsep(projection, ",")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,8 @@ case class DescribeCommand(
AttributeReference("data_type", StringType, nullable = false)(),
AttributeReference("comment", StringType, nullable = false)())
}

/**
* Returned for the "ADD CACHE TABLE tableName AS SELECT .." command.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove "ADD".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will remove it

*/
case class CacheTableAsSelectCommand(tableName: String, plan: LogicalPlan) extends Command
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,8 @@ private[sql] abstract class SparkStrategies extends QueryPlanner[SparkPlan] {
Seq(execution.ExplainCommand(logicalPlan, plan.output, extended)(context))
case logical.CacheCommand(tableName, cache) =>
Seq(execution.CacheCommand(tableName, cache)(context))
case logical.CacheTableAsSelectCommand(tableName,plan) =>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Space after comma please.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will update

Seq(execution.CacheTableAsSelectCommand(tableName, plan))
case _ => Nil
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,3 +166,22 @@ case class DescribeCommand(child: SparkPlan, output: Seq[Attribute])(
child.output.map(field => Row(field.name, field.dataType.toString, null))
}
}

/**
* :: DeveloperApi ::
*/
@DeveloperApi
case class CacheTableAsSelectCommand(tableName: String, plan: LogicalPlan)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm thinking about merging CacheCommand into this class, since the former can be a special case of this one once we make them consistent with each other in laziness. But this can be addressed in a follow up PR.

extends LeafNode with Command {

override protected[sql] lazy val sideEffectResult = {
sqlContext.catalog.registerTable(None, tableName, sqlContext.executePlan(plan).analyzed)
sqlContext.cacheTable(tableName)
// It does the caching eager.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@marmbrus I've seen your comments in SPARK-2594, I'd be OK with both being lazy or eager, but I think this statement should be consistent with CACHE TABLE <name> and SQLContext.cacheTable, which are now lazy. Otherwise it would be rather confusing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Either way is OK. But eager caching is existed only for this feature, so it may look inconsistent compared to other caching commands.

sqlContext.table(tableName).count
Seq.empty[Row]
}

override def output: Seq[Attribute] = Seq.empty

}
Original file line number Diff line number Diff line change
Expand Up @@ -119,4 +119,16 @@ class CachedTableSuite extends QueryTest {
}
assert(!TestSQLContext.isCached("testData"), "Table 'testData' should not be cached")
}

test("CACHE TABLE tableName AS SELECT Star Table") {
TestSQLContext.sql("CACHE TABLE testCacheTable AS SELECT * FROM testData")
TestSQLContext.sql("SELECT * FROM testCacheTable WHERE key = 1").collect()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be better to assert testCacheTable is cached here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will add

TestSQLContext.uncacheTable("testCacheTable")
}

test("'CACHE TABLE tableName AS SELECT ..'") {
TestSQLContext.sql("CACHE TABLE testCacheTable AS SELECT * FROM testData")
assert(TestSQLContext.isCached("testCacheTable"), "Table 'testCacheTable' should be cached")
TestSQLContext.uncacheTable("testCacheTable")
}
}
36 changes: 24 additions & 12 deletions sql/hive/src/main/scala/org/apache/spark/sql/hive/HiveQl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ private[hive] object HiveQl {
*/
def getAst(sql: String): ASTNode = ParseUtils.findRootNonNullToken((new ParseDriver).parse(sql))


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove this redundant new line.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for trouble. I am new to git,so added accidently

/** Returns a LogicalPlan for a given HiveQL string. */
def parseSql(sql: String): LogicalPlan = {
try {
Expand All @@ -229,11 +230,17 @@ private[hive] object HiveQl {
SetCommand(Some(key), Some(value))
}
} else if (sql.trim.toLowerCase.startsWith("cache table")) {
CacheCommand(sql.trim.drop(12).trim, true)
sql.trim.drop(12).trim.split(" ").toSeq match {
case Seq(tableName) =>
CacheCommand(tableName, true)
case Seq(tableName,as, select@_*) =>
CacheTableAsSelectCommand(tableName,
createPlan(sql.trim.drop(12 + tableName.length() + as.length() + 2)))
}
} else if (sql.trim.toLowerCase.startsWith("uncache table")) {
CacheCommand(sql.trim.drop(14).trim, false)
} else if (sql.trim.toLowerCase.startsWith("add jar")) {
AddJar(sql.trim.drop(8).trim)
NativeCommand(sql)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I guess you probably rebased to an older version of master? We definitely shouldn't revert AddJar support here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for trouble. I am new to git,so added accidently

} else if (sql.trim.toLowerCase.startsWith("add file")) {
AddFile(sql.trim.drop(9))
} else if (sql.trim.toLowerCase.startsWith("dfs")) {
Expand All @@ -243,15 +250,7 @@ private[hive] object HiveQl {
} else if (sql.trim.startsWith("!")) {
ShellCommand(sql.drop(1))
} else {
val tree = getAst(sql)
if (nativeCommands contains tree.getText) {
NativeCommand(sql)
} else {
nodeToPlan(tree) match {
case NativePlaceholder => NativeCommand(sql)
case other => other
}
}
createPlan(sql)
}
} catch {
case e: Exception => throw new ParseException(sql, e)
Expand All @@ -262,6 +261,19 @@ private[hive] object HiveQl {
""".stripMargin)
}
}

/** Creates LogicalPlan for a given HiveQL string. */
def createPlan(sql: String) = {
val tree = getAst(sql)
if (nativeCommands contains tree.getText) {
NativeCommand(sql)
} else {
nodeToPlan(tree) match {
case NativePlaceholder => NativeCommand(sql)
case other => other
}
}
}

def parseDdl(ddl: String): Seq[Attribute] = {
val tree =
Expand Down Expand Up @@ -1097,7 +1109,7 @@ private[hive] object HiveQl {

case Token("TOK_FUNCTION", Token(functionName, Nil) :: children) =>
HiveGenericUdtf(functionName, attributes, children.map(nodeToExpr))

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove these spaces

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok

case a: ASTNode =>
throw new NotImplementedError(
s"""No parse rules for ASTNode type: ${a.getType}, text: ${a.getText}, tree:
Expand Down