本文主要研究一下flink Table的OrderBy及Limithtml
Table in = tableEnv.fromDataSet(ds, "a, b, c"); Table result = in.orderBy("a.asc"); Table in = tableEnv.fromDataSet(ds, "a, b, c"); // returns the first 5 records from the sorted result Table result1 = in.orderBy("a.asc").fetch(5); // skips the first 3 records and returns all following records from the sorted result Table result2 = in.orderBy("a.asc").offset(3); // skips the first 10 records and returns the next 5 records from the sorted result Table result3 = in.orderBy("a.asc").offset(10).fetch(5);
flink-table_2.11-1.7.0-sources.jar!/org/apache/flink/table/api/table.scalasql
class Table( private[flink] val tableEnv: TableEnvironment, private[flink] val logicalPlan: LogicalNode) { //...... def orderBy(fields: String): Table = { val parsedFields = ExpressionParser.parseExpressionList(fields) orderBy(parsedFields: _*) } def orderBy(fields: Expression*): Table = { val order: Seq[Ordering] = fields.map { case o: Ordering => o case e => Asc(e) } new Table(tableEnv, Sort(order, logicalPlan).validate(tableEnv)) } def offset(offset: Int): Table = { new Table(tableEnv, Limit(offset, -1, logicalPlan).validate(tableEnv)) } def fetch(fetch: Int): Table = { if (fetch < 0) { throw new ValidationException("FETCH count must be equal or larger than 0.") } this.logicalPlan match { case Limit(o, -1, c) => // replace LIMIT without FETCH by LIMIT with FETCH new Table(tableEnv, Limit(o, fetch, c).validate(tableEnv)) case Limit(_, _, _) => throw new ValidationException("FETCH is already defined.") case _ => new Table(tableEnv, Limit(0, fetch, logicalPlan).validate(tableEnv)) } } //...... }
offset方法建立的Limit其fetch爲-1;fetch方法若是以前沒有指定offset則建立的Limit的offset爲0
)flink-table_2.11-1.7.0-sources.jar!/org/apache/flink/table/plan/logical/operators.scalaexpress
case class Sort(order: Seq[Ordering], child: LogicalNode) extends UnaryNode { override def output: Seq[Attribute] = child.output override protected[logical] def construct(relBuilder: RelBuilder): RelBuilder = { child.construct(relBuilder) relBuilder.sort(order.map(_.toRexNode(relBuilder)).asJava) } override def validate(tableEnv: TableEnvironment): LogicalNode = { if (tableEnv.isInstanceOf[StreamTableEnvironment]) { failValidation(s"Sort on stream tables is currently not supported.") } super.validate(tableEnv) } }
flink-table_2.11-1.7.0-sources.jar!/org/apache/flink/table/expressions/ordering.scalaapache
abstract class Ordering extends UnaryExpression { override private[flink] def validateInput(): ValidationResult = { if (!child.isInstanceOf[NamedExpression]) { ValidationFailure(s"Sort should only based on field reference") } else { ValidationSuccess } } } case class Asc(child: Expression) extends Ordering { override def toString: String = s"($child).asc" override private[flink] def toRexNode(implicit relBuilder: RelBuilder): RexNode = { child.toRexNode } override private[flink] def resultType: TypeInformation[_] = child.resultType } case class Desc(child: Expression) extends Ordering { override def toString: String = s"($child).desc" override private[flink] def toRexNode(implicit relBuilder: RelBuilder): RexNode = { relBuilder.desc(child.toRexNode) } override private[flink] def resultType: TypeInformation[_] = child.resultType }
flink-table_2.11-1.7.0-sources.jar!/org/apache/flink/table/plan/logical/operators.scalaapi
case class Limit(offset: Int, fetch: Int = -1, child: LogicalNode) extends UnaryNode { override def output: Seq[Attribute] = child.output override protected[logical] def construct(relBuilder: RelBuilder): RelBuilder = { child.construct(relBuilder) relBuilder.limit(offset, fetch) } override def validate(tableEnv: TableEnvironment): LogicalNode = { if (tableEnv.isInstanceOf[StreamTableEnvironment]) { failValidation(s"Limit on stream tables is currently not supported.") } if (!child.isInstanceOf[Sort]) { failValidation(s"Limit operator must be preceded by an OrderBy operator.") } if (offset < 0) { failValidation(s"Offset should be greater than or equal to zero.") } super.validate(tableEnv) } }
offset方法建立的Limit其fetch爲-1;fetch方法若是以前沒有指定offset則建立的Limit的offset爲0
)