dtenedor commented on code in PR #41007:
URL: https://github.com/apache/spark/pull/41007#discussion_r1194198592
##########
sql/catalyst/src/main/antlr4/org/apache/spark/sql/catalyst/parser/SqlBaseParser.g4:
##########
@@ -434,17 +434,31 @@ resource
dmlStatementNoWith
: insertInto query
#singleInsertQuery
| fromClause multiInsertQueryBody+
#multiInsertQuery
- | DELETE FROM multipartIdentifier tableAlias whereClause?
#deleteFromTable
- | UPDATE multipartIdentifier tableAlias setClause whereClause?
#updateTable
- | MERGE INTO target=multipartIdentifier targetAlias=tableAlias
- USING (source=multipartIdentifier |
+ | DELETE FROM tableReference tableAlias whereClause?
#deleteFromTable
+ | UPDATE tableReference tableAlias setClause whereClause?
#updateTable
+ | MERGE INTO target=tableReference targetAlias=tableAlias
+ USING (source=tableReference |
LEFT_PAREN sourceQuery=query RIGHT_PAREN) sourceAlias=tableAlias
ON mergeCondition=booleanExpression
matchedClause*
notMatchedClause*
notMatchedBySourceClause*
#mergeIntoTable
;
+tableReference
+ : IDENTIFIER_KW LEFT_PAREN expression RIGHT_PAREN
+ | multipartIdentifier
+ ;
+
+identifierReference
+ : IDENTIFIER_KW LEFT_PAREN expression RIGHT_PAREN
+ | multipartIdentifier
+ ;
+identifierReferenceAllowTemp
Review Comment:
This does not seem any different than `identifierReference` above, or
`tableReference`?
##########
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/IdentifierClauseUtil.scala:
##########
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.spark.sql.catalyst.analysis
+
+import org.apache.spark.sql.catalyst.expressions.Expression
+import org.apache.spark.sql.types.StringType
+
+/**
+ * Resolves the catalog of the name parts for table/view/function/namespace.
+ */
+object IdentifierClauseUtil {
+ private def getNotNullFoldableSring(clauseName: String, expr: Expression):
String = {
+ expr match {
+ case e if !e.foldable => expr.failAnalysis(
+ errorClass = "NOT_A_CONSTANT_STRING.NOT_CONSTANT",
+ messageParameters = Map(
+ "name" -> clauseName,
+ "expr" -> expr.sql))
+ case e if e.dataType != StringType => expr.failAnalysis(
+ errorClass = "NOT_A_CONSTANT_STRING.WRONG_TYPE",
+ messageParameters = Map(
+ "name" -> clauseName,
+ "expr" -> expr.sql,
+ "dataType" -> e.dataType.catalogString))
+ case e =>
+ e.eval() match {
+ case null => expr.failAnalysis(
+ errorClass = "NOT_A_CONSTANT_STRING.NULL",
+ messageParameters = Map(
+ "name" -> clauseName,
+ "expr" -> expr.sql))
+ case _ => e.eval().toString // OK
Review Comment:
this makes us perform the `eval` again. I think we can just write `case
other => other // OK` and it should work to reuse it instead.
##########
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/unresolved.scala:
##########
@@ -276,6 +279,138 @@ object UnresolvedAttribute {
}
}
+/**
+ * Holds an identifier clause for an attribute that has yet to be resolved.
+ */
+case class UnresolvedAttributeIdentifierClause(expr: Expression)
+ extends Expression with Unevaluable {
+
+ override def children: Seq[Expression] = Seq(expr)
+
+ override def dataType: DataType = throw new UnresolvedException("dataType")
+ override def nullable: Boolean = throw new UnresolvedException("nullable")
+ override lazy val resolved = false
+ final override val nodePatterns: Seq[TreePattern] =
Seq(UNRESOLVED_IDENTIFIER_CLAUSE)
+
+ override def prettyName: String = "IDENTIFIER"
+ override def toString: String = {
+ s"'(${children.mkString(", ")})"
+ }
+
+ override protected def withNewChildrenInternal(newChildren:
IndexedSeq[Expression]):
+ UnresolvedAttributeIdentifierClause = {
+ copy(expr = newChildren.head)
+ }
+}
+
+case class UnresolvedFunctionIdentifierClause(
+ identExpr: Expression,
+ arguments: Seq[Expression],
+ isDistinct: Boolean,
+ filter: Option[Expression] = None,
+ ignoreNulls: Boolean = false)
+ extends Expression with Unevaluable {
+
+ override def children: Seq[Expression] = arguments ++ filter.toSeq
+
+ override def dataType: DataType = throw new UnresolvedException("dataType")
+ override def nullable: Boolean = throw new UnresolvedException("nullable")
+ override lazy val resolved = false
+ final override val nodePatterns: Seq[TreePattern] =
Seq(UNRESOLVED_IDENTIFIER_CLAUSE)
+
+ override def prettyName: String = identExpr.toString
+ override def toString: String = {
+ val distinct = if (isDistinct) "distinct " else ""
+ s"'${identExpr.toString}($distinct${children.mkString(", ")})"
+ }
+
+ override protected def withNewChildrenInternal
+ (newChildren: IndexedSeq[Expression]): UnresolvedFunctionIdentifierClause = {
+ if (filter.isDefined) {
+ copy(arguments = newChildren.dropRight(1), filter =
Some(newChildren.last))
+ } else {
+ copy(arguments = newChildren)
+ }
+ }
+}
+
+object UnresolvedFunctionIdentifierClause {
Review Comment:
optional: it might be simpler to just add this as another constructor inside
the above case class instead of creating a separate helper object for this
purpose?
##########
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/unresolved.scala:
##########
@@ -276,6 +279,138 @@ object UnresolvedAttribute {
}
}
+/**
+ * Holds an identifier clause for an attribute that has yet to be resolved.
+ */
+case class UnresolvedAttributeIdentifierClause(expr: Expression)
+ extends Expression with Unevaluable {
+
+ override def children: Seq[Expression] = Seq(expr)
+
+ override def dataType: DataType = throw new UnresolvedException("dataType")
+ override def nullable: Boolean = throw new UnresolvedException("nullable")
+ override lazy val resolved = false
+ final override val nodePatterns: Seq[TreePattern] =
Seq(UNRESOLVED_IDENTIFIER_CLAUSE)
+
+ override def prettyName: String = "IDENTIFIER"
+ override def toString: String = {
+ s"'(${children.mkString(", ")})"
+ }
+
+ override protected def withNewChildrenInternal(newChildren:
IndexedSeq[Expression]):
+ UnresolvedAttributeIdentifierClause = {
+ copy(expr = newChildren.head)
+ }
+}
+
+case class UnresolvedFunctionIdentifierClause(
+ identExpr: Expression,
+ arguments: Seq[Expression],
+ isDistinct: Boolean,
+ filter: Option[Expression] = None,
+ ignoreNulls: Boolean = false)
+ extends Expression with Unevaluable {
+
+ override def children: Seq[Expression] = arguments ++ filter.toSeq
+
+ override def dataType: DataType = throw new UnresolvedException("dataType")
+ override def nullable: Boolean = throw new UnresolvedException("nullable")
+ override lazy val resolved = false
+ final override val nodePatterns: Seq[TreePattern] =
Seq(UNRESOLVED_IDENTIFIER_CLAUSE)
+
+ override def prettyName: String = identExpr.toString
+ override def toString: String = {
+ val distinct = if (isDistinct) "distinct " else ""
+ s"'${identExpr.toString}($distinct${children.mkString(", ")})"
+ }
+
+ override protected def withNewChildrenInternal
+ (newChildren: IndexedSeq[Expression]): UnresolvedFunctionIdentifierClause = {
+ if (filter.isDefined) {
+ copy(arguments = newChildren.dropRight(1), filter =
Some(newChildren.last))
+ } else {
+ copy(arguments = newChildren)
+ }
+ }
+}
+
+object UnresolvedFunctionIdentifierClause {
+ def apply(
+ identExpr: Expression,
+ arguments: Seq[Expression],
+ isDistinct: Boolean): UnresolvedFunction = {
+ UnresolvedFunctionIdentifierClause(identExpr, arguments, isDistinct)
+ }
+}
+
+/**
+ * A table-valued function, e.g.
+ * {{{
+ * select id from range(10);
+ * }}}
+ *
+ * @param identExpr user-specified expression with teh name of this
table-value function
+ * @param functionArgs list of function arguments
+ */
+case class UnresolvedTableValuedFunctionIdentifierClause(
+ identExpr: Expression,
+ functionArgs: Seq[Expression])
+ extends LeafNode {
+
+ override def output: Seq[Attribute] = Nil
+
+ override lazy val resolved = false
+
+ final override val nodePatterns: Seq[TreePattern] =
Seq(UNRESOLVED_IDENTIFIER_CLAUSE)
+}
+
+/**
+* A table-valued function with output column aliases, e.g.
+* {{{
+* // Assign alias names
+* select t.a from range(10) t(a);
+* }}}
+*
+* @param identExpr user-specified name of the table-valued function
+* @param child logical plan of the table-valued function
+* @param outputNames alias names of function output columns. The analyzer adds
[[Project]]
+* to rename the output columns.
+*/
+case class UnresolvedTVFAliasesIdentifierClause(
+ identExpr: Expression,
+ child: LogicalPlan,
+ outputNames: Seq[String]) extends UnaryNode {
+
+ override def output: Seq[Attribute] = Nil
+
+ override lazy val resolved = false
+
+ final override val nodePatterns: Seq[TreePattern] =
Seq(UNRESOLVED_IDENTIFIER_CLAUSE)
+
+ override protected def withNewChildInternal(newChild: LogicalPlan):
LogicalPlan =
+ copy(child = newChild)
+}
+
+/**
+ * Holds the name of a relation that has yet to be looked up in a catalog.
+ *
+ * @param expr multipartIdentifier table name
+ */
+case class UnresolvedRelationIdentifierClause(expr: Expression)
+ extends UnresolvedRelationOrIdentifierClause {
+
+ /** Returns a `.` separated name for this relation. */
+ def tableName: String = throw new UnresolvedException("tableName")
Review Comment:
QQ: why do we need this method if it just throws an exception and does not
override anything?
##########
sql/catalyst/src/main/antlr4/org/apache/spark/sql/catalyst/parser/SqlBaseParser.g4:
##########
@@ -907,6 +922,7 @@ primaryExpression
| qualifiedName DOT ASTERISK
#star
| LEFT_PAREN namedExpression (COMMA namedExpression)+ RIGHT_PAREN
#rowConstructor
| LEFT_PAREN query RIGHT_PAREN
#subqueryExpression
+ | IDENTIFIER_KW LEFT_PAREN expression RIGHT_PAREN
#identifierClause
Review Comment:
we might be OK with just this change in the grammar file to introduce the
new IDENTIFIER clause feature, and not any of the other changes? We could
always still do the other changes as well, but it could behoove us to split
that into a separate PR?
##########
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/unresolved.scala:
##########
@@ -276,6 +279,138 @@ object UnresolvedAttribute {
}
}
+/**
+ * Holds an identifier clause for an attribute that has yet to be resolved.
+ */
+case class UnresolvedAttributeIdentifierClause(expr: Expression)
+ extends Expression with Unevaluable {
+
+ override def children: Seq[Expression] = Seq(expr)
+
+ override def dataType: DataType = throw new UnresolvedException("dataType")
+ override def nullable: Boolean = throw new UnresolvedException("nullable")
+ override lazy val resolved = false
+ final override val nodePatterns: Seq[TreePattern] =
Seq(UNRESOLVED_IDENTIFIER_CLAUSE)
+
+ override def prettyName: String = "IDENTIFIER"
+ override def toString: String = {
+ s"'(${children.mkString(", ")})"
+ }
+
+ override protected def withNewChildrenInternal(newChildren:
IndexedSeq[Expression]):
+ UnresolvedAttributeIdentifierClause = {
+ copy(expr = newChildren.head)
+ }
+}
+
+case class UnresolvedFunctionIdentifierClause(
+ identExpr: Expression,
Review Comment:
please fix indentation?
##########
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/unresolved.scala:
##########
@@ -276,6 +279,138 @@ object UnresolvedAttribute {
}
}
+/**
+ * Holds an identifier clause for an attribute that has yet to be resolved.
+ */
+case class UnresolvedAttributeIdentifierClause(expr: Expression)
+ extends Expression with Unevaluable {
+
+ override def children: Seq[Expression] = Seq(expr)
+
+ override def dataType: DataType = throw new UnresolvedException("dataType")
+ override def nullable: Boolean = throw new UnresolvedException("nullable")
+ override lazy val resolved = false
+ final override val nodePatterns: Seq[TreePattern] =
Seq(UNRESOLVED_IDENTIFIER_CLAUSE)
+
+ override def prettyName: String = "IDENTIFIER"
+ override def toString: String = {
+ s"'(${children.mkString(", ")})"
+ }
+
+ override protected def withNewChildrenInternal(newChildren:
IndexedSeq[Expression]):
+ UnresolvedAttributeIdentifierClause = {
+ copy(expr = newChildren.head)
+ }
+}
+
+case class UnresolvedFunctionIdentifierClause(
+ identExpr: Expression,
+ arguments: Seq[Expression],
+ isDistinct: Boolean,
+ filter: Option[Expression] = None,
+ ignoreNulls: Boolean = false)
+ extends Expression with Unevaluable {
+
+ override def children: Seq[Expression] = arguments ++ filter.toSeq
+
+ override def dataType: DataType = throw new UnresolvedException("dataType")
+ override def nullable: Boolean = throw new UnresolvedException("nullable")
+ override lazy val resolved = false
+ final override val nodePatterns: Seq[TreePattern] =
Seq(UNRESOLVED_IDENTIFIER_CLAUSE)
+
+ override def prettyName: String = identExpr.toString
+ override def toString: String = {
+ val distinct = if (isDistinct) "distinct " else ""
+ s"'${identExpr.toString}($distinct${children.mkString(", ")})"
+ }
+
+ override protected def withNewChildrenInternal
+ (newChildren: IndexedSeq[Expression]): UnresolvedFunctionIdentifierClause = {
+ if (filter.isDefined) {
+ copy(arguments = newChildren.dropRight(1), filter =
Some(newChildren.last))
+ } else {
+ copy(arguments = newChildren)
+ }
+ }
+}
+
+object UnresolvedFunctionIdentifierClause {
+ def apply(
+ identExpr: Expression,
+ arguments: Seq[Expression],
+ isDistinct: Boolean): UnresolvedFunction = {
+ UnresolvedFunctionIdentifierClause(identExpr, arguments, isDistinct)
+ }
+}
+
+/**
+ * A table-valued function, e.g.
+ * {{{
+ * select id from range(10);
+ * }}}
+ *
+ * @param identExpr user-specified expression with teh name of this
table-value function
+ * @param functionArgs list of function arguments
+ */
+case class UnresolvedTableValuedFunctionIdentifierClause(
+ identExpr: Expression,
+ functionArgs: Seq[Expression])
+ extends LeafNode {
+
+ override def output: Seq[Attribute] = Nil
+
+ override lazy val resolved = false
+
+ final override val nodePatterns: Seq[TreePattern] =
Seq(UNRESOLVED_IDENTIFIER_CLAUSE)
+}
+
+/**
+* A table-valued function with output column aliases, e.g.
+* {{{
+* // Assign alias names
+* select t.a from range(10) t(a);
+* }}}
+*
+* @param identExpr user-specified name of the table-valued function
+* @param child logical plan of the table-valued function
+* @param outputNames alias names of function output columns. The analyzer adds
[[Project]]
+* to rename the output columns.
+*/
+case class UnresolvedTVFAliasesIdentifierClause(
+ identExpr: Expression,
Review Comment:
please fix indentation?
##########
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/v2ResolutionPlans.scala:
##########
@@ -40,18 +40,34 @@ case class UnresolvedNamespace(multipartIdentifier:
Seq[String]) extends LeafNod
override def output: Seq[Attribute] = Nil
}
+abstract class UnresolvedTableOrIdentifierClause extends LeafNode
+
/**
* Holds the name of a table that has yet to be looked up in a catalog. It
will be resolved to
* [[ResolvedTable]] during analysis.
*/
case class UnresolvedTable(
multipartIdentifier: Seq[String],
commandName: String,
- relationTypeMismatchHint: Option[String]) extends LeafNode {
+ relationTypeMismatchHint: Option[String]) extends
UnresolvedTableOrIdentifierClause {
override lazy val resolved: Boolean = false
override def output: Seq[Attribute] = Nil
}
+/**
+ * Holds the identifier of a tabl ein String form that has yet to be looked up
in a catalog.
+ * It will be resolved to [[UnResolvedTable]] during analysis.
+ */
+case class UnresolvedTableIdentifierClause(
Review Comment:
should this just be in `unresolved.scala` next to the other new unresolved
identifier clause nodes? Same for the others below.
##########
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/Analyzer.scala:
##########
@@ -2108,6 +2123,18 @@ class Analyzer(override val catalogManager:
CatalogManager) extends RuleExecutor
}
}
+ // Resolve IDENTIFIER clause.
+ case u@UnresolvedRelationIdentifierClause(expr) if expr.resolved =>
+ UnresolvedRelation(IdentifierClauseUtil.evalIdentifierClause(expr))
+
+ // Resolve IDENTIFIER clause and reduce to a regular unresolved table
function
+ case u@UnresolvedTableValuedFunctionIdentifierClause(expr, args) if
expr.resolved =>
+
UnresolvedTableValuedFunction(IdentifierClauseUtil.evalIdentifierClause(expr),
args)
+
+ // Resolve IDENTIFIER clause and reduce to a regular unresolved TVF
aliases
Review Comment:
```suggestion
// Resolve IDENTIFIER clause and reduce to a regular unresolved TVF
alias
```
##########
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/unresolved.scala:
##########
@@ -276,6 +279,138 @@ object UnresolvedAttribute {
}
}
+/**
+ * Holds an identifier clause for an attribute that has yet to be resolved.
+ */
+case class UnresolvedAttributeIdentifierClause(expr: Expression)
+ extends Expression with Unevaluable {
+
+ override def children: Seq[Expression] = Seq(expr)
+
+ override def dataType: DataType = throw new UnresolvedException("dataType")
+ override def nullable: Boolean = throw new UnresolvedException("nullable")
+ override lazy val resolved = false
+ final override val nodePatterns: Seq[TreePattern] =
Seq(UNRESOLVED_IDENTIFIER_CLAUSE)
+
+ override def prettyName: String = "IDENTIFIER"
+ override def toString: String = {
+ s"'(${children.mkString(", ")})"
+ }
+
+ override protected def withNewChildrenInternal(newChildren:
IndexedSeq[Expression]):
+ UnresolvedAttributeIdentifierClause = {
+ copy(expr = newChildren.head)
+ }
+}
+
+case class UnresolvedFunctionIdentifierClause(
+ identExpr: Expression,
+ arguments: Seq[Expression],
+ isDistinct: Boolean,
+ filter: Option[Expression] = None,
+ ignoreNulls: Boolean = false)
+ extends Expression with Unevaluable {
+
+ override def children: Seq[Expression] = arguments ++ filter.toSeq
+
+ override def dataType: DataType = throw new UnresolvedException("dataType")
+ override def nullable: Boolean = throw new UnresolvedException("nullable")
+ override lazy val resolved = false
+ final override val nodePatterns: Seq[TreePattern] =
Seq(UNRESOLVED_IDENTIFIER_CLAUSE)
+
+ override def prettyName: String = identExpr.toString
+ override def toString: String = {
+ val distinct = if (isDistinct) "distinct " else ""
+ s"'${identExpr.toString}($distinct${children.mkString(", ")})"
+ }
+
+ override protected def withNewChildrenInternal
+ (newChildren: IndexedSeq[Expression]): UnresolvedFunctionIdentifierClause = {
+ if (filter.isDefined) {
+ copy(arguments = newChildren.dropRight(1), filter =
Some(newChildren.last))
+ } else {
+ copy(arguments = newChildren)
+ }
+ }
+}
+
+object UnresolvedFunctionIdentifierClause {
+ def apply(
+ identExpr: Expression,
+ arguments: Seq[Expression],
+ isDistinct: Boolean): UnresolvedFunction = {
+ UnresolvedFunctionIdentifierClause(identExpr, arguments, isDistinct)
+ }
+}
+
+/**
+ * A table-valued function, e.g.
+ * {{{
+ * select id from range(10);
+ * }}}
+ *
+ * @param identExpr user-specified expression with teh name of this
table-value function
+ * @param functionArgs list of function arguments
+ */
+case class UnresolvedTableValuedFunctionIdentifierClause(
+ identExpr: Expression,
+ functionArgs: Seq[Expression])
+ extends LeafNode {
+
+ override def output: Seq[Attribute] = Nil
+
+ override lazy val resolved = false
+
+ final override val nodePatterns: Seq[TreePattern] =
Seq(UNRESOLVED_IDENTIFIER_CLAUSE)
Review Comment:
optional: do we want to create separate patterns for each of these types of
unresolved identifier clause? Or just combine them all into one? Having
separate ones could grant more flexibility later if needed?
##########
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/unresolved.scala:
##########
@@ -276,6 +279,138 @@ object UnresolvedAttribute {
}
}
+/**
+ * Holds an identifier clause for an attribute that has yet to be resolved.
+ */
+case class UnresolvedAttributeIdentifierClause(expr: Expression)
+ extends Expression with Unevaluable {
+
+ override def children: Seq[Expression] = Seq(expr)
+
+ override def dataType: DataType = throw new UnresolvedException("dataType")
+ override def nullable: Boolean = throw new UnresolvedException("nullable")
+ override lazy val resolved = false
+ final override val nodePatterns: Seq[TreePattern] =
Seq(UNRESOLVED_IDENTIFIER_CLAUSE)
+
+ override def prettyName: String = "IDENTIFIER"
+ override def toString: String = {
+ s"'(${children.mkString(", ")})"
+ }
+
+ override protected def withNewChildrenInternal(newChildren:
IndexedSeq[Expression]):
+ UnresolvedAttributeIdentifierClause = {
+ copy(expr = newChildren.head)
+ }
+}
+
+case class UnresolvedFunctionIdentifierClause(
+ identExpr: Expression,
+ arguments: Seq[Expression],
+ isDistinct: Boolean,
+ filter: Option[Expression] = None,
+ ignoreNulls: Boolean = false)
+ extends Expression with Unevaluable {
+
+ override def children: Seq[Expression] = arguments ++ filter.toSeq
+
+ override def dataType: DataType = throw new UnresolvedException("dataType")
+ override def nullable: Boolean = throw new UnresolvedException("nullable")
+ override lazy val resolved = false
+ final override val nodePatterns: Seq[TreePattern] =
Seq(UNRESOLVED_IDENTIFIER_CLAUSE)
+
+ override def prettyName: String = identExpr.toString
+ override def toString: String = {
+ val distinct = if (isDistinct) "distinct " else ""
+ s"'${identExpr.toString}($distinct${children.mkString(", ")})"
+ }
+
+ override protected def withNewChildrenInternal
+ (newChildren: IndexedSeq[Expression]): UnresolvedFunctionIdentifierClause = {
+ if (filter.isDefined) {
+ copy(arguments = newChildren.dropRight(1), filter =
Some(newChildren.last))
+ } else {
+ copy(arguments = newChildren)
+ }
+ }
+}
+
+object UnresolvedFunctionIdentifierClause {
+ def apply(
+ identExpr: Expression,
Review Comment:
please fix indentation?
##########
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/unresolved.scala:
##########
@@ -276,6 +279,138 @@ object UnresolvedAttribute {
}
}
+/**
+ * Holds an identifier clause for an attribute that has yet to be resolved.
+ */
+case class UnresolvedAttributeIdentifierClause(expr: Expression)
+ extends Expression with Unevaluable {
+
+ override def children: Seq[Expression] = Seq(expr)
+
+ override def dataType: DataType = throw new UnresolvedException("dataType")
+ override def nullable: Boolean = throw new UnresolvedException("nullable")
+ override lazy val resolved = false
+ final override val nodePatterns: Seq[TreePattern] =
Seq(UNRESOLVED_IDENTIFIER_CLAUSE)
+
+ override def prettyName: String = "IDENTIFIER"
+ override def toString: String = {
+ s"'(${children.mkString(", ")})"
+ }
+
+ override protected def withNewChildrenInternal(newChildren:
IndexedSeq[Expression]):
+ UnresolvedAttributeIdentifierClause = {
+ copy(expr = newChildren.head)
+ }
+}
+
+case class UnresolvedFunctionIdentifierClause(
+ identExpr: Expression,
+ arguments: Seq[Expression],
+ isDistinct: Boolean,
+ filter: Option[Expression] = None,
+ ignoreNulls: Boolean = false)
+ extends Expression with Unevaluable {
+
+ override def children: Seq[Expression] = arguments ++ filter.toSeq
+
+ override def dataType: DataType = throw new UnresolvedException("dataType")
+ override def nullable: Boolean = throw new UnresolvedException("nullable")
+ override lazy val resolved = false
+ final override val nodePatterns: Seq[TreePattern] =
Seq(UNRESOLVED_IDENTIFIER_CLAUSE)
+
+ override def prettyName: String = identExpr.toString
+ override def toString: String = {
+ val distinct = if (isDistinct) "distinct " else ""
+ s"'${identExpr.toString}($distinct${children.mkString(", ")})"
+ }
+
+ override protected def withNewChildrenInternal
+ (newChildren: IndexedSeq[Expression]): UnresolvedFunctionIdentifierClause = {
+ if (filter.isDefined) {
+ copy(arguments = newChildren.dropRight(1), filter =
Some(newChildren.last))
+ } else {
+ copy(arguments = newChildren)
+ }
+ }
+}
+
+object UnresolvedFunctionIdentifierClause {
+ def apply(
+ identExpr: Expression,
+ arguments: Seq[Expression],
+ isDistinct: Boolean): UnresolvedFunction = {
+ UnresolvedFunctionIdentifierClause(identExpr, arguments, isDistinct)
+ }
+}
+
+/**
+ * A table-valued function, e.g.
+ * {{{
+ * select id from range(10);
+ * }}}
+ *
+ * @param identExpr user-specified expression with teh name of this
table-value function
+ * @param functionArgs list of function arguments
+ */
+case class UnresolvedTableValuedFunctionIdentifierClause(
+ identExpr: Expression,
Review Comment:
please fix indentation?
##########
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/v2ResolutionPlans.scala:
##########
@@ -40,18 +40,34 @@ case class UnresolvedNamespace(multipartIdentifier:
Seq[String]) extends LeafNod
override def output: Seq[Attribute] = Nil
}
+abstract class UnresolvedTableOrIdentifierClause extends LeafNode
+
/**
* Holds the name of a table that has yet to be looked up in a catalog. It
will be resolved to
* [[ResolvedTable]] during analysis.
*/
case class UnresolvedTable(
multipartIdentifier: Seq[String],
commandName: String,
- relationTypeMismatchHint: Option[String]) extends LeafNode {
+ relationTypeMismatchHint: Option[String]) extends
UnresolvedTableOrIdentifierClause {
override lazy val resolved: Boolean = false
override def output: Seq[Attribute] = Nil
}
+/**
+ * Holds the identifier of a tabl ein String form that has yet to be looked up
in a catalog.
Review Comment:
```suggestion
* Holds the identifier of a table in string form that has yet to be looked
up in a catalog.
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]