Skip to content
Snippets Groups Projects
Commit 162cf02e authored by gatorsmile's avatar gatorsmile Committed by Herman van Hovell
Browse files

[SPARK-14910][SQL] Native DDL Command Support for Describe Function in Non-identifier Format

#### What changes were proposed in this pull request?
The existing `Describe Function` only support the function name in `identifier`. This is different from what Hive behaves. That is why many test cases `udf_abc` in `HiveCompatibilitySuite` are not using our native DDL support. For example,
- udf_not.q
- udf_bitwise_not.q

This PR is to resolve the issues. Now, we can support the command of `Describe Function` whose function names are in the following format:
- `qualifiedName` (e.g., `db.func1`)
- `STRING` (e.g., `'func1'`)
- `comparisonOperator` (e.g,. `<`)
- `arithmeticOperator` (e.g., `+`)
- `predicateOperator` (e.g., `or`)

Note, before this PR, we only have a native command support when the function name is in the format of `qualifiedName`.
#### How was this patch tested?
Added test cases in `DDLSuite.scala`. Also manually verified all the related test cases in `HiveCompatibilitySuite` passed.

Author: gatorsmile <gatorsmile@gmail.com>

Closes #12679 from gatorsmile/descFunction.
parent b208229b
No related branches found
No related tags found
No related merge requests found
......@@ -107,7 +107,7 @@ statement
| SHOW TBLPROPERTIES table=tableIdentifier
('(' key=tablePropertyKey ')')? #showTblProperties
| SHOW FUNCTIONS (LIKE? (qualifiedName | pattern=STRING))? #showFunctions
| (DESC | DESCRIBE) FUNCTION EXTENDED? qualifiedName #describeFunction
| (DESC | DESCRIBE) FUNCTION EXTENDED? describeFuncName #describeFunction
| (DESC | DESCRIBE) option=(EXTENDED | FORMATTED)?
tableIdentifier partitionSpec? describeColName? #describeTable
| (DESC | DESCRIBE) DATABASE EXTENDED? identifier #describeDatabase
......@@ -220,6 +220,14 @@ partitionVal
: identifier (EQ constant)?
;
describeFuncName
: qualifiedName
| STRING
| comparisonOperator
| arithmeticOperator
| predicateOperator
;
describeColName
: identifier ('.' (identifier | STRING))*
;
......@@ -519,6 +527,14 @@ comparisonOperator
: EQ | NEQ | NEQJ | LT | LTE | GT | GTE | NSEQ
;
arithmeticOperator
: PLUS | MINUS | ASTERISK | SLASH | PERCENT | DIV | TILDE | AMPERSAND | PIPE | HAT
;
predicateOperator
: OR | AND | IN | NOT
;
booleanValue
: TRUE | FALSE
;
......
......@@ -363,6 +363,7 @@ object FunctionRegistry {
expression[Not]("not"),
expression[Or]("or"),
// comparison operators
expression[EqualNullSafe]("<=>"),
expression[EqualTo]("="),
expression[EqualTo]("=="),
......
......@@ -112,8 +112,16 @@ class AstBuilder extends SqlBaseBaseVisitor[AnyRef] with Logging {
* Create a plan for a DESCRIBE FUNCTION command.
*/
override def visitDescribeFunction(ctx: DescribeFunctionContext): LogicalPlan = withOrigin(ctx) {
val functionName = ctx.qualifiedName().identifier().asScala.map(_.getText).mkString(".")
DescribeFunction(functionName, ctx.EXTENDED != null)
import ctx._
val functionName =
if (describeFuncName.STRING() != null) {
string(describeFuncName.STRING())
} else if (describeFuncName.qualifiedName() != null) {
describeFuncName.qualifiedName().identifier().asScala.map(_.getText).mkString(".")
} else {
describeFuncName.getText
}
DescribeFunction(functionName, EXTENDED != null)
}
/**
......
......@@ -716,4 +716,55 @@ class DDLSuite extends QueryTest with SharedSQLContext with BeforeAndAfterEach {
}
}
test("describe function") {
checkAnswer(
sql("DESCRIBE FUNCTION log"),
Row("Class: org.apache.spark.sql.catalyst.expressions.Logarithm") ::
Row("Function: log") ::
Row("Usage: log(b, x) - Returns the logarithm of x with base b.") :: Nil
)
// predicate operator
checkAnswer(
sql("DESCRIBE FUNCTION or"),
Row("Class: org.apache.spark.sql.catalyst.expressions.Or") ::
Row("Function: or") ::
Row("Usage: a or b - Logical OR.") :: Nil
)
checkAnswer(
sql("DESCRIBE FUNCTION !"),
Row("Class: org.apache.spark.sql.catalyst.expressions.Not") ::
Row("Function: !") ::
Row("Usage: ! a - Logical not") :: Nil
)
// arithmetic operators
checkAnswer(
sql("DESCRIBE FUNCTION +"),
Row("Class: org.apache.spark.sql.catalyst.expressions.Add") ::
Row("Function: +") ::
Row("Usage: a + b - Returns a+b.") :: Nil
)
// comparison operators
checkAnswer(
sql("DESCRIBE FUNCTION <"),
Row("Class: org.apache.spark.sql.catalyst.expressions.LessThan") ::
Row("Function: <") ::
Row("Usage: a < b - Returns TRUE if a is less than b.") :: Nil
)
// STRING
checkAnswer(
sql("DESCRIBE FUNCTION 'concat'"),
Row("Class: org.apache.spark.sql.catalyst.expressions.Concat") ::
Row("Function: concat") ::
Row("Usage: concat(str1, str2, ..., strN) " +
"- Returns the concatenation of str1, str2, ..., strN") :: Nil
)
// extended mode
checkAnswer(
sql("DESCRIBE FUNCTION EXTENDED ^"),
Row("Class: org.apache.spark.sql.catalyst.expressions.BitwiseXor") ::
Row("Extended Usage:\n> SELECT 3 ^ 5; 2") ::
Row("Function: ^") ::
Row("Usage: a ^ b - Bitwise exclusive OR.") :: Nil
)
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment