[
https://issues.apache.org/jira/browse/FLINK-3192?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15081348#comment-15081348
]
ASF GitHub Bot commented on FLINK-3192:
---------------------------------------
Github user fhueske commented on a diff in the pull request:
https://github.com/apache/flink/pull/1477#discussion_r48751597
--- Diff:
flink-staging/flink-table/src/main/scala/org/apache/flink/api/table/Table.scala
---
@@ -1,271 +1,291 @@
-/*
- * 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.flink.api.table
-
-import org.apache.flink.api.table.expressions.analysis.{GroupByAnalyzer,
PredicateAnalyzer, SelectionAnalyzer}
-import org.apache.flink.api.table.expressions.{Expression,
ResolvedFieldReference, UnresolvedFieldReference}
-import org.apache.flink.api.table.parser.ExpressionParser
-import org.apache.flink.api.table.plan._
-
-/**
- * The abstraction for writing Table API programs. Similar to how the
batch and streaming APIs
- * have [[org.apache.flink.api.scala.DataSet]] and
- * [[org.apache.flink.streaming.api.scala.DataStream]].
- *
- * Use the methods of [[Table]] to transform data. Use
- * [[org.apache.flink.api.java.table.TableEnvironment]] to convert a
[[Table]] back to a DataSet
- * or DataStream.
- *
- * When using Scala a [[Table]] can also be converted using implicit
conversions.
- *
- * Example:
- *
- * {{{
- * val table = set.toTable('a, 'b)
- * ...
- * val table2 = ...
- * val set = table2.toDataSet[MyType]
- * }}}
- *
- * Operations such as [[join]], [[select]], [[where]] and [[groupBy]]
either take arguments
- * in a Scala DSL or as an expression String. Please refer to the
documentation for the expression
- * syntax.
- */
-case class Table(private[flink] val operation: PlanNode) {
-
- /**
- * Performs a selection operation. Similar to an SQL SELECT statement.
The field expressions
- * can contain complex expressions and aggregations.
- *
- * Example:
- *
- * {{{
- * in.select('key, 'value.avg + " The average" as 'average,
'other.substring(0, 10))
- * }}}
- */
- def select(fields: Expression*): Table = {
- val analyzer = new SelectionAnalyzer(operation.outputFields)
- val analyzedFields = fields.map(analyzer.analyze)
- val fieldNames = analyzedFields map(_.name)
- if (fieldNames.toSet.size != fieldNames.size) {
- throw new ExpressionException(s"Resulting fields names are not
unique in expression" +
- s""" "${fields.mkString(", ")}".""")
- }
- this.copy(operation = Select(operation, analyzedFields))
- }
-
- /**
- * Performs a selection operation. Similar to an SQL SELECT statement.
The field expressions
- * can contain complex expressions and aggregations.
- *
- * Example:
- *
- * {{{
- * in.select("key, value.avg + " The average" as average,
other.substring(0, 10)")
- * }}}
- */
- def select(fields: String): Table = {
- val fieldExprs = ExpressionParser.parseExpressionList(fields)
- select(fieldExprs: _*)
- }
-
- /**
- * Renames the fields of the expression result. Use this to disambiguate
fields before
- * joining to operations.
- *
- * Example:
- *
- * {{{
- * in.as('a, 'b)
- * }}}
- */
- def as(fields: Expression*): Table = {
- fields forall {
- f => f.isInstanceOf[UnresolvedFieldReference]
- } match {
- case true =>
- case false => throw new ExpressionException("Only field expression
allowed in as().")
- }
- this.copy(operation = As(operation, fields.toArray map { _.name }))
- }
-
- /**
- * Renames the fields of the expression result. Use this to disambiguate
fields before
- * joining to operations.
- *
- * Example:
- *
- * {{{
- * in.as("a, b")
- * }}}
- */
- def as(fields: String): Table = {
- val fieldExprs = ExpressionParser.parseExpressionList(fields)
- as(fieldExprs: _*)
- }
-
- /**
- * Filters out elements that don't pass the filter predicate. Similar to
a SQL WHERE
- * clause.
- *
- * Example:
- *
- * {{{
- * in.filter('name === "Fred")
- * }}}
- */
- def filter(predicate: Expression): Table = {
- val analyzer = new PredicateAnalyzer(operation.outputFields)
- val analyzedPredicate = analyzer.analyze(predicate)
- this.copy(operation = Filter(operation, analyzedPredicate))
- }
-
- /**
- * Filters out elements that don't pass the filter predicate. Similar to
a SQL WHERE
- * clause.
- *
- * Example:
- *
- * {{{
- * in.filter("name = 'Fred'")
- * }}}
- */
- def filter(predicate: String): Table = {
- val predicateExpr = ExpressionParser.parseExpression(predicate)
- filter(predicateExpr)
- }
-
- /**
- * Filters out elements that don't pass the filter predicate. Similar to
a SQL WHERE
- * clause.
- *
- * Example:
- *
- * {{{
- * in.where('name === "Fred")
- * }}}
- */
- def where(predicate: Expression): Table = {
- filter(predicate)
- }
-
- /**
- * Filters out elements that don't pass the filter predicate. Similar to
a SQL WHERE
- * clause.
- *
- * Example:
- *
- * {{{
- * in.where("name = 'Fred'")
- * }}}
- */
- def where(predicate: String): Table = {
- filter(predicate)
- }
-
- /**
- * Groups the elements on some grouping keys. Use this before a
selection with aggregations
- * to perform the aggregation on a per-group basis. Similar to a SQL
GROUP BY statement.
- *
- * Example:
- *
- * {{{
- * in.groupBy('key).select('key, 'value.avg)
- * }}}
- */
- def groupBy(fields: Expression*): Table = {
- val analyzer = new GroupByAnalyzer(operation.outputFields)
- val analyzedFields = fields.map(analyzer.analyze)
-
- val illegalKeys = analyzedFields filter {
- case fe: ResolvedFieldReference => false // OK
- case e => true
- }
-
- if (illegalKeys.nonEmpty) {
- throw new ExpressionException("Illegal key expressions: " +
illegalKeys.mkString(", "))
- }
-
- this.copy(operation = GroupBy(operation, analyzedFields))
- }
-
- /**
- * Groups the elements on some grouping keys. Use this before a
selection with aggregations
- * to perform the aggregation on a per-group basis. Similar to a SQL
GROUP BY statement.
- *
- * Example:
- *
- * {{{
- * in.groupBy("key").select("key, value.avg")
- * }}}
- */
- def groupBy(fields: String): Table = {
- val fieldsExpr = ExpressionParser.parseExpressionList(fields)
- groupBy(fieldsExpr: _*)
- }
-
- /**
- * Joins two [[Table]]s. Similar to an SQL join. The fields of the two
joined
- * operations must not overlap, use [[as]] to rename fields if
necessary. You can use
- * where and select clauses after a join to further specify the
behaviour of the join.
- *
- * Example:
- *
- * {{{
- * left.join(right).where('a === 'b && 'c > 3).select('a, 'b, 'd)
- * }}}
- */
- def join(right: Table): Table = {
- val leftInputNames = operation.outputFields.map(_._1).toSet
- val rightInputNames = right.operation.outputFields.map(_._1).toSet
- if (leftInputNames.intersect(rightInputNames).nonEmpty) {
- throw new ExpressionException(
- "Overlapping fields names on join input, result would be
ambiguous: " +
- operation.outputFields.mkString(", ") +
- " and " +
- right.operation.outputFields.mkString(", ") )
- }
- this.copy(operation = Join(operation, right.operation))
- }
-
- /**
- * Union two[[Table]]s. Similar to an SQL UNION ALL. The fields of the
two union operations
- * must fully overlap.
- *
- * Example:
- *
- * {{{
- * left.unionAll(right)
- * }}}
- */
- def unionAll(right: Table): Table = {
- val leftInputFields = operation.outputFields
- val rightInputFields = right.operation.outputFields
- if (!leftInputFields.equals(rightInputFields)) {
- throw new ExpressionException(
- "The fields names of join inputs should be fully overlapped, left
inputs fields:" +
- operation.outputFields.mkString(", ") +
- " and right inputs fields" +
- right.operation.outputFields.mkString(", ")
- )
- }
- this.copy(operation = UnionAll(operation, right.operation))
- }
-
- override def toString: String = s"Expression($operation)"
-}
+/*
+ * 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.flink.api.table
+
+import org.apache.flink.api.java.io.DiscardingOutputFormat
+import org.apache.flink.api.table.expressions.analysis.{GroupByAnalyzer,
PredicateAnalyzer, SelectionAnalyzer}
+import org.apache.flink.api.table.expressions.{Expression,
ResolvedFieldReference, UnresolvedFieldReference}
+import org.apache.flink.api.table.parser.ExpressionParser
+import org.apache.flink.api.table.plan._
+import org.apache.flink.api.scala._
+import org.apache.flink.api.scala.table._
+
+/**
+ * The abstraction for writing Table API programs. Similar to how the
batch and streaming APIs
+ * have [[org.apache.flink.api.scala.DataSet]] and
+ * [[org.apache.flink.streaming.api.scala.DataStream]].
+ *
+ * Use the methods of [[Table]] to transform data. Use
+ * [[org.apache.flink.api.java.table.TableEnvironment]] to convert a
[[Table]] back to a DataSet
+ * or DataStream.
+ *
+ * When using Scala a [[Table]] can also be converted using implicit
conversions.
+ *
+ * Example:
+ *
+ * {{{
+ * val table = set.toTable('a, 'b)
+ * ...
+ * val table2 = ...
+ * val set = table2.toDataSet[MyType]
+ * }}}
+ *
+ * Operations such as [[join]], [[select]], [[where]] and [[groupBy]]
either take arguments
+ * in a Scala DSL or as an expression String. Please refer to the
documentation for the expression
+ * syntax.
+ */
+case class Table(private[flink] val operation: PlanNode) {
+
+ /**
+ * Performs a selection operation. Similar to an SQL SELECT statement.
The field expressions
+ * can contain complex expressions and aggregations.
+ *
+ * Example:
+ *
+ * {{{
+ * in.select('key, 'value.avg + " The average" as 'average,
'other.substring(0, 10))
+ * }}}
+ */
+ def select(fields: Expression*): Table = {
+ val analyzer = new SelectionAnalyzer(operation.outputFields)
+ val analyzedFields = fields.map(analyzer.analyze)
+ val fieldNames = analyzedFields map(_.name)
+ if (fieldNames.toSet.size != fieldNames.size) {
+ throw new ExpressionException(s"Resulting fields names are not
unique in expression" +
+ s""" "${fields.mkString(", ")}".""")
+ }
+ this.copy(operation = Select(operation, analyzedFields))
+ }
+
+ /**
+ * Performs a selection operation. Similar to an SQL SELECT statement.
The field expressions
+ * can contain complex expressions and aggregations.
+ *
+ * Example:
+ *
+ * {{{
+ * in.select("key, value.avg + " The average" as average,
other.substring(0, 10)")
+ * }}}
+ */
+ def select(fields: String): Table = {
+ val fieldExprs = ExpressionParser.parseExpressionList(fields)
+ select(fieldExprs: _*)
+ }
+
+ /**
+ * Renames the fields of the expression result. Use this to disambiguate
fields before
+ * joining to operations.
+ *
+ * Example:
+ *
+ * {{{
+ * in.as('a, 'b)
+ * }}}
+ */
+ def as(fields: Expression*): Table = {
+ fields forall {
+ f => f.isInstanceOf[UnresolvedFieldReference]
+ } match {
+ case true =>
+ case false => throw new ExpressionException("Only field expression
allowed in as().")
+ }
+ this.copy(operation = As(operation, fields.toArray map { _.name }))
+ }
+
+ /**
+ * Renames the fields of the expression result. Use this to disambiguate
fields before
+ * joining to operations.
+ *
+ * Example:
+ *
+ * {{{
+ * in.as("a, b")
+ * }}}
+ */
+ def as(fields: String): Table = {
+ val fieldExprs = ExpressionParser.parseExpressionList(fields)
+ as(fieldExprs: _*)
+ }
+
+ /**
+ * Filters out elements that don't pass the filter predicate. Similar to
a SQL WHERE
+ * clause.
+ *
+ * Example:
+ *
+ * {{{
+ * in.filter('name === "Fred")
+ * }}}
+ */
+ def filter(predicate: Expression): Table = {
+ val analyzer = new PredicateAnalyzer(operation.outputFields)
+ val analyzedPredicate = analyzer.analyze(predicate)
+ this.copy(operation = Filter(operation, analyzedPredicate))
+ }
+
+ /**
+ * Filters out elements that don't pass the filter predicate. Similar to
a SQL WHERE
+ * clause.
+ *
+ * Example:
+ *
+ * {{{
+ * in.filter("name = 'Fred'")
+ * }}}
+ */
+ def filter(predicate: String): Table = {
+ val predicateExpr = ExpressionParser.parseExpression(predicate)
+ filter(predicateExpr)
+ }
+
+ /**
+ * Filters out elements that don't pass the filter predicate. Similar to
a SQL WHERE
+ * clause.
+ *
+ * Example:
+ *
+ * {{{
+ * in.where('name === "Fred")
+ * }}}
+ */
+ def where(predicate: Expression): Table = {
+ filter(predicate)
+ }
+
+ /**
+ * Filters out elements that don't pass the filter predicate. Similar to
a SQL WHERE
+ * clause.
+ *
+ * Example:
+ *
+ * {{{
+ * in.where("name = 'Fred'")
+ * }}}
+ */
+ def where(predicate: String): Table = {
+ filter(predicate)
+ }
+
+ /**
+ * Groups the elements on some grouping keys. Use this before a
selection with aggregations
+ * to perform the aggregation on a per-group basis. Similar to a SQL
GROUP BY statement.
+ *
+ * Example:
+ *
+ * {{{
+ * in.groupBy('key).select('key, 'value.avg)
+ * }}}
+ */
+ def groupBy(fields: Expression*): Table = {
+ val analyzer = new GroupByAnalyzer(operation.outputFields)
+ val analyzedFields = fields.map(analyzer.analyze)
+
+ val illegalKeys = analyzedFields filter {
+ case fe: ResolvedFieldReference => false // OK
+ case e => true
+ }
+
+ if (illegalKeys.nonEmpty) {
+ throw new ExpressionException("Illegal key expressions: " +
illegalKeys.mkString(", "))
+ }
+
+ this.copy(operation = GroupBy(operation, analyzedFields))
+ }
+
+ /**
+ * Groups the elements on some grouping keys. Use this before a
selection with aggregations
+ * to perform the aggregation on a per-group basis. Similar to a SQL
GROUP BY statement.
+ *
+ * Example:
+ *
+ * {{{
+ * in.groupBy("key").select("key, value.avg")
+ * }}}
+ */
+ def groupBy(fields: String): Table = {
+ val fieldsExpr = ExpressionParser.parseExpressionList(fields)
+ groupBy(fieldsExpr: _*)
+ }
+
+ /**
+ * Joins two [[Table]]s. Similar to an SQL join. The fields of the two
joined
+ * operations must not overlap, use [[as]] to rename fields if
necessary. You can use
+ * where and select clauses after a join to further specify the
behaviour of the join.
+ *
+ * Example:
+ *
+ * {{{
+ * left.join(right).where('a === 'b && 'c > 3).select('a, 'b, 'd)
+ * }}}
+ */
+ def join(right: Table): Table = {
+ val leftInputNames = operation.outputFields.map(_._1).toSet
+ val rightInputNames = right.operation.outputFields.map(_._1).toSet
+ if (leftInputNames.intersect(rightInputNames).nonEmpty) {
+ throw new ExpressionException(
+ "Overlapping fields names on join input, result would be
ambiguous: " +
+ operation.outputFields.mkString(", ") +
+ " and " +
+ right.operation.outputFields.mkString(", ") )
+ }
+ this.copy(operation = Join(operation, right.operation))
+ }
+
+ /**
+ * Union two[[Table]]s. Similar to an SQL UNION ALL. The fields of the
two union operations
+ * must fully overlap.
+ *
+ * Example:
+ *
+ * {{{
+ * left.unionAll(right)
+ * }}}
+ */
+ def unionAll(right: Table): Table = {
+ val leftInputFields = operation.outputFields
+ val rightInputFields = right.operation.outputFields
+ if (!leftInputFields.equals(rightInputFields)) {
+ throw new ExpressionException(
+ "The fields names of join inputs should be fully overlapped, left
inputs fields:" +
+ operation.outputFields.mkString(", ") +
+ " and right inputs fields" +
+ right.operation.outputFields.mkString(", ")
+ )
+ }
+ this.copy(operation = UnionAll(operation, right.operation))
+ }
+
+ /**
+ * Get the process of the sql parsing, print AST and physical execution
plan.The AST
+ * show the structure of the supplied statement. The execution plan
shows how the table
+ * referenced by the statement will be scanned.
+ */
+ def explain(extended: Boolean): String = {
--- End diff --
It looks like you add only this method.
Can you check why the whole file is marked as changed?
> Add explain support to print ast and sql physical execution plan.
> ------------------------------------------------------------------
>
> Key: FLINK-3192
> URL: https://issues.apache.org/jira/browse/FLINK-3192
> Project: Flink
> Issue Type: New Feature
> Components: Table API
> Reporter: GaoLun
> Assignee: GaoLun
> Priority: Minor
> Labels: features
>
> Table API doesn't support sql-explanation now. Add the explain support to
> print ast (abstract syntax tree) and the physical execution plan of sql.
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)