org.apache.flink.table.api.Table Maven / Gradle / Ivy
Show all versions of flink-table-api-java Show documentation
/*
* 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.table.api;
import org.apache.flink.annotation.PublicEvolving;
import org.apache.flink.table.catalog.ResolvedSchema;
import org.apache.flink.table.connector.sink.DynamicTableSink;
import org.apache.flink.table.connector.source.DynamicTableSource;
import org.apache.flink.table.expressions.Expression;
import org.apache.flink.table.functions.TableFunction;
import org.apache.flink.table.functions.TemporalTableFunction;
import org.apache.flink.table.operations.QueryOperation;
import org.apache.flink.table.types.DataType;
/**
* The {@link Table} object is the core abstraction of the Table API. Similar to how the DataStream
* API has {@code DataStream}s, the Table API is built around {@link Table}s.
*
* A {@link Table} object describes a pipeline of data transformations. It does not contain the
* data itself in any way. Instead, it describes how to read data from a {@link DynamicTableSource}
* and how to eventually write data to a {@link DynamicTableSink}. The declared pipeline can be
* printed, optimized, and eventually executed in a cluster. The pipeline can work with bounded or
* unbounded streams which enables both streaming and batch scenarios.
*
*
By the definition above, a {@link Table} object can actually be considered as a view in
* SQL terms.
*
*
The initial {@link Table} object is constructed by a {@link TableEnvironment}. For example,
* {@link TableEnvironment#from(String)}) obtains a table from a catalog. Every {@link Table} object
* has a schema that is available through {@link #getResolvedSchema()}. A {@link Table} object is
* always associated with its original table environment during programming.
*
*
Every transformation (i.e. {@link #select(Expression...)} or {@link #filter(Expression)}) on a
* {@link Table} object leads to a new {@link Table} object.
*
*
Use {@link #execute()} to execute the pipeline and retrieve the transformed data locally
* during development. Otherwise, use {@link #executeInsert(String)} to write the data into a table
* sink.
*
*
Many methods of this class take one or more {@link Expression}s as parameters. For fluent
* definition of expressions and easier readability, we recommend to add a star import:
*
*
* import static org.apache.flink.table.api.Expressions.*;
*
*
* Check the documentation for more programming language specific APIs, for example, by using
* Scala implicits.
*
*
The following example shows how to work with a {@link Table} object.
*
*
Java Example (with static import for expressions):
*
*
{@code
* TableEnvironment tableEnv = TableEnvironment.create(...);
*
* Table table = tableEnv.from("MyTable").select($("colA").trim(), $("colB").plus(12));
*
* table.execute().print();
* }
*
* Scala Example (with implicits for expressions):
*
*
{@code
* val tableEnv = TableEnvironment.create(...)
*
* val table = tableEnv.from("MyTable").select($"colA".trim(), $"colB" + 12)
*
* table.execute().print()
* }
*/
@PublicEvolving
public interface Table extends Explainable, Executable {
/**
* Returns the schema of this table.
*
* @deprecated This method has been deprecated as part of FLIP-164. {@link TableSchema} has been
* replaced by two more dedicated classes {@link Schema} and {@link ResolvedSchema}. Use
* {@link Schema} for declaration in APIs. {@link ResolvedSchema} is offered by the
* framework after resolution and validation.
*/
@Deprecated
default TableSchema getSchema() {
return TableSchema.fromResolvedSchema(getResolvedSchema());
}
/** Returns the resolved schema of this table. */
ResolvedSchema getResolvedSchema();
/** Prints the schema of this table to the console in a summary format. */
void printSchema();
/** Returns underlying logical representation of this table. */
QueryOperation getQueryOperation();
/**
* Performs a selection operation. Similar to a SQL SELECT statement. The field expressions can
* contain complex expressions and aggregations.
*
* Java Example:
*
*
{@code
* tab.select($("key"), $("value").avg().plus(" The average").as("average"));
* }
*
* Scala Example:
*
*
{@code
* tab.select($"key", $"value".avg + " The average" as "average")
* }
*/
Table select(Expression... fields);
/**
* Creates {@link TemporalTableFunction} backed up by this table as a history table. Temporal
* Tables represent a concept of a table that changes over time and for which Flink keeps track
* of those changes. {@link TemporalTableFunction} provides a way how to access those data.
*
* For more information please check Flink's documentation on Temporal Tables.
*
*
Currently {@link TemporalTableFunction}s are only supported in streaming.
*
* @param timeAttribute Must points to a time indicator. Provides a way to compare which records
* are a newer or older version.
* @param primaryKey Defines the primary key. With primary key it is possible to update a row or
* to delete it.
* @return {@link TemporalTableFunction} which is an instance of {@link TableFunction}. It takes
* one single argument, the {@code timeAttribute}, for which it returns matching version of
* the {@link Table}, from which {@link TemporalTableFunction} was created.
*/
TemporalTableFunction createTemporalTableFunction(
Expression timeAttribute, Expression primaryKey);
/**
* Renames the fields of the expression result. Use this to disambiguate fields before joining
* to operations.
*
*
Example:
*
*
{@code
* tab.as("a", "b")
* }
*/
Table as(String field, String... fields);
/**
* Renames the fields of the expression result. Use this to disambiguate fields before joining
* to operations.
*
* Java Example:
*
*
{@code
* tab.as($("a"), $("b"))
* }
*
* Scala Example:
*
*
{@code
* tab.as($"a", $"b")
* }
*
* @deprecated use {@link #as(String, String...)}
*/
@Deprecated
Table as(Expression... fields);
/**
* Filters out elements that don't pass the filter predicate. Similar to a SQL WHERE clause.
*
* Java Example:
*
*
{@code
* tab.filter($("name").isEqual("Fred"));
* }
*
* Scala Example:
*
*
{@code
* tab.filter($"name" === "Fred")
* }
*/
Table filter(Expression predicate);
/**
* Filters out elements that don't pass the filter predicate. Similar to a SQL WHERE clause.
*
* Java Example:
*
*
{@code
* tab.where($("name").isEqual("Fred"));
* }
*
* Scala Example:
*
*
{@code
* tab.where($"name" === "Fred")
* }
*/
Table where(Expression 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.
*
* Java Example:
*
*
{@code
* tab.groupBy($("key")).select($("key"), $("value").avg());
* }
*
* Scala Example:
*
*
{@code
* tab.groupBy($"key").select($"key", $"value".avg)
* }
*/
GroupedTable groupBy(Expression... fields);
/**
* Removes duplicate values and returns only distinct (different) values.
*
* Example:
*
*
{@code
* tab.select($("key"), $("value")).distinct();
* }
*/
Table distinct();
/**
* Joins two {@link Table}s. Similar to a SQL join. The fields of the two joined operations must
* not overlap, use {@code as} to rename fields if necessary. You can use where and select
* clauses after a join to further specify the behaviour of the join.
*
* Note: Both tables must be bound to the same {@code TableEnvironment} .
*
*
Example:
*
*
{@code
* left.join(right)
* .where($("a").isEqual($("b")).and($("c").isGreater(3))
* .select($("a"), $("b"), $("d"));
* }
*/
Table join(Table right);
/**
* Joins two {@link Table}s. Similar to a SQL join. The fields of the two joined operations must
* not overlap, use {@code as} to rename fields if necessary.
*
* Note: Both tables must be bound to the same {@code TableEnvironment} .
*
*
Java Example:
*
*
{@code
* left.join(right, $("a").isEqual($("b")))
* .select($("a"), $("b"), $("d"));
* }
*
* Scala Example:
*
*
{@code
* left.join(right, $"a" === $"b")
* .select($"a", $"b", $"d")
* }
*/
Table join(Table right, Expression joinPredicate);
/**
* Joins two {@link Table}s. Similar to a SQL left outer join. The fields of the two joined
* operations must not overlap, use {@code as} to rename fields if necessary.
*
* Note: Both tables must be bound to the same {@code TableEnvironment} and its {@code
* TableConfig} must have null check enabled (default).
*
*
Example:
*
*
{@code
* left.leftOuterJoin(right)
* .select($("a"), $("b"), $("d"));
* }
*/
Table leftOuterJoin(Table right);
/**
* Joins two {@link Table}s. Similar to a SQL left outer join. The fields of the two joined
* operations must not overlap, use {@code as} to rename fields if necessary.
*
* Note: Both tables must be bound to the same {@code TableEnvironment} and its {@code
* TableConfig} must have null check enabled (default).
*
*
Java Example:
*
*
{@code
* left.leftOuterJoin(right, $("a").isEqual($("b")))
* .select($("a"), $("b"), $("d"));
* }
*
* Scala Example:
*
*
{@code
* left.leftOuterJoin(right, $"a" === $"b")
* .select($"a", $"b", $"d")
* }
*/
Table leftOuterJoin(Table right, Expression joinPredicate);
/**
* Joins two {@link Table}s. Similar to a SQL right outer join. The fields of the two joined
* operations must not overlap, use {@code as} to rename fields if necessary.
*
* Note: Both tables must be bound to the same {@code TableEnvironment} and its {@code
* TableConfig} must have null check enabled (default).
*
*
Java Example:
*
*
{@code
* left.rightOuterJoin(right, $("a").isEqual($("b")))
* .select($("a"), $("b"), $("d"));
* }
*
* Scala Example:
*
*
{@code
* left.rightOuterJoin(right, $"a" === $"b")
* .select($"a", $"b", $"d")
* }
*/
Table rightOuterJoin(Table right, Expression joinPredicate);
/**
* Joins two {@link Table}s. Similar to a SQL full outer join. The fields of the two joined
* operations must not overlap, use {@code as} to rename fields if necessary.
*
* Note: Both tables must be bound to the same {@code TableEnvironment} and its {@code
* TableConfig} must have null check enabled (default).
*
*
Java Example:
*
*
{@code
* left.fullOuterJoin(right, $("a").isEqual($("b")))
* .select($("a"), $("b"), $("d"));
* }
*
* Scala Example:
*
*
{@code
* left.fullOuterJoin(right, $"a" === $"b")
* .select($"a", $"b", $"d")
* }
*/
Table fullOuterJoin(Table right, Expression joinPredicate);
/**
* Joins this {@link Table} with an user-defined {@link TableFunction}. This join is similar to
* a SQL inner join with ON TRUE predicate but works with a table function. Each row of the
* table is joined with all rows produced by the table function.
*
* Java Example:
*
*
{@code
* class MySplitUDTF extends TableFunction {
* public void eval(String str) {
* str.split("#").forEach(this::collect);
* }
* }
*
* table.joinLateral(call(MySplitUDTF.class, $("c")).as("s"))
* .select($("a"), $("b"), $("c"), $("s"));
* }
*
* Scala Example:
*
*
{@code
* class MySplitUDTF extends TableFunction[String] {
* def eval(str: String): Unit = {
* str.split("#").foreach(collect)
* }
* }
*
* val split = new MySplitUDTF()
* table.joinLateral(split($"c") as "s")
* .select($"a", $"b", $"c", $"s")
* }
*/
Table joinLateral(Expression tableFunctionCall);
/**
* Joins this {@link Table} with an user-defined {@link TableFunction}. This join is similar to
* a SQL inner join but works with a table function. Each row of the table is joined with all
* rows produced by the table function.
*
* Java Example:
*
*
{@code
* class MySplitUDTF extends TableFunction {
* public void eval(String str) {
* str.split("#").forEach(this::collect);
* }
* }
*
* table.joinLateral(call(MySplitUDTF.class, $("c")).as("s"), $("a").isEqual($("s")))
* .select($("a"), $("b"), $("c"), $("s"));
* }
*
* Scala Example:
*
*
{@code
* class MySplitUDTF extends TableFunction[String] {
* def eval(str: String): Unit = {
* str.split("#").foreach(collect)
* }
* }
*
* val split = new MySplitUDTF()
* table.joinLateral(split($"c") as "s", $"a" === $"s")
* .select($"a", $"b", $"c", $"s")
* }
*/
Table joinLateral(Expression tableFunctionCall, Expression joinPredicate);
/**
* Joins this {@link Table} with an user-defined {@link TableFunction}. This join is similar to
* a SQL left outer join with ON TRUE predicate but works with a table function. Each row of the
* table is joined with all rows produced by the table function. If the table function does not
* produce any row, the outer row is padded with nulls.
*
* Java Example:
*
*
{@code
* class MySplitUDTF extends TableFunction {
* public void eval(String str) {
* str.split("#").forEach(this::collect);
* }
* }
*
* table.leftOuterJoinLateral(call(MySplitUDTF.class, $("c")).as("s"))
* .select($("a"), $("b"), $("c"), $("s"));
* }
*
* Scala Example:
*
*
{@code
* class MySplitUDTF extends TableFunction[String] {
* def eval(str: String): Unit = {
* str.split("#").foreach(collect)
* }
* }
*
* val split = new MySplitUDTF()
* table.leftOuterJoinLateral(split($"c") as "s")
* .select($"a", $"b", $"c", $"s")
* }
*/
Table leftOuterJoinLateral(Expression tableFunctionCall);
/**
* Joins this {@link Table} with an user-defined {@link TableFunction}. This join is similar to
* a SQL left outer join with ON TRUE predicate but works with a table function. Each row of the
* table is joined with all rows produced by the table function. If the table function does not
* produce any row, the outer row is padded with nulls.
*
* Java Example:
*
*
{@code
* class MySplitUDTF extends TableFunction {
* public void eval(String str) {
* str.split("#").forEach(this::collect);
* }
* }
*
* table.leftOuterJoinLateral(call(MySplitUDTF.class, $("c")).as("s"), $("a").isEqual($("s")))
* .select($("a"), $("b"), $("c"), $("s"));
* }
*
* Scala Example:
*
*
{@code
* class MySplitUDTF extends TableFunction[String] {
* def eval(str: String): Unit = {
* str.split("#").foreach(collect)
* }
* }
*
* val split = new MySplitUDTF()
* table.leftOuterJoinLateral(split($"c") as "s", $"a" === $"s")
* .select($"a", $"b", $"c", $"s")
* }
*/
Table leftOuterJoinLateral(Expression tableFunctionCall, Expression joinPredicate);
/**
* Minus of two {@link Table}s with duplicate records removed. Similar to a SQL EXCEPT clause.
* Minus returns records from the left table that do not exist in the right table. Duplicate
* records in the left table are returned exactly once, i.e., duplicates are removed. Both
* tables must have identical field types.
*
* Note: Both tables must be bound to the same {@code TableEnvironment}.
*
*
Example:
*
*
{@code
* left.minus(right);
* }
*/
Table minus(Table right);
/**
* Minus of two {@link Table}s. Similar to a SQL EXCEPT ALL. Similar to a SQL EXCEPT ALL clause.
* MinusAll returns the records that do not exist in the right table. A record that is present n
* times in the left table and m times in the right table is returned (n - m) times, i.e., as
* many duplicates as are present in the right table are removed. Both tables must have
* identical field types.
*
* Note: Both tables must be bound to the same {@code TableEnvironment}.
*
*
Example:
*
*
{@code
* left.minusAll(right);
* }
*/
Table minusAll(Table right);
/**
* Unions two {@link Table}s with duplicate records removed. Similar to a SQL UNION. The fields
* of the two union operations must fully overlap.
*
* Note: Both tables must be bound to the same {@code TableEnvironment}.
*
*
Example:
*
*
{@code
* left.union(right);
* }
*/
Table union(Table right);
/**
* Unions two {@link Table}s. Similar to a SQL UNION ALL. The fields of the two union operations
* must fully overlap.
*
* Note: Both tables must be bound to the same {@code TableEnvironment}.
*
*
Example:
*
*
{@code
* left.unionAll(right);
* }
*/
Table unionAll(Table right);
/**
* Intersects two {@link Table}s with duplicate records removed. Intersect returns records that
* exist in both tables. If a record is present in one or both tables more than once, it is
* returned just once, i.e., the resulting table has no duplicate records. Similar to a SQL
* INTERSECT. The fields of the two intersect operations must fully overlap.
*
* Note: Both tables must be bound to the same {@code TableEnvironment}.
*
*
Example:
*
*
{@code
* left.intersect(right);
* }
*/
Table intersect(Table right);
/**
* Intersects two {@link Table}s. IntersectAll returns records that exist in both tables. If a
* record is present in both tables more than once, it is returned as many times as it is
* present in both tables, i.e., the resulting table might have duplicate records. Similar to an
* SQL INTERSECT ALL. The fields of the two intersect operations must fully overlap.
*
* Note: Both tables must be bound to the same {@code TableEnvironment}.
*
*
Example:
*
*
{@code
* left.intersectAll(right);
* }
*/
Table intersectAll(Table right);
/**
* Sorts the given {@link Table}. Similar to SQL {@code ORDER BY}.
*
* The resulting Table is globally sorted across all parallel partitions.
*
*
Java Example:
*
*
{@code
* tab.orderBy($("name").desc());
* }
*
* Scala Example:
*
*
{@code
* tab.orderBy($"name".desc)
* }
*
* For unbounded tables, this operation requires a sorting on a time attribute or a
* subsequent fetch operation.
*/
Table orderBy(Expression... fields);
/**
* Limits a (possibly sorted) result from an offset position.
*
*
This method can be combined with a preceding {@link #orderBy(Expression...)} call for a
* deterministic order and a subsequent {@link #fetch(int)} call to return n rows after skipping
* the first o rows.
*
*
{@code
* // skips the first 3 rows and returns all following rows.
* tab.orderBy($("name").desc()).offset(3);
* // skips the first 10 rows and returns the next 5 rows.
* tab.orderBy($("name").desc()).offset(10).fetch(5);
* }
*
* For unbounded tables, this operation requires a subsequent fetch operation.
*
* @param offset number of records to skip
*/
Table offset(int offset);
/**
* Limits a (possibly sorted) result to the first n rows.
*
*
This method can be combined with a preceding {@link #orderBy(Expression...)} call for a
* deterministic order and {@link #offset(int)} call to return n rows after skipping the first o
* rows.
*
*
{@code
* // returns the first 3 records.
* tab.orderBy($("name").desc()).fetch(3);
* // skips the first 10 rows and returns the next 5 rows.
* tab.orderBy($("name").desc()).offset(10).fetch(5);
* }
*
* @param fetch the number of records to return. Fetch must be >= 0.
*/
Table fetch(int fetch);
/**
* Limits a (possibly sorted) result to the first n rows.
*
* This method is a synonym for {@link #fetch(int)}.
*/
default Table limit(int fetch) {
return fetch(fetch);
}
/**
* Limits a (possibly sorted) result to the first n rows from an offset position.
*
*
This method is a synonym for {@link #offset(int)} followed by {@link #fetch(int)}.
*/
default Table limit(int offset, int fetch) {
return offset(offset).fetch(fetch);
}
/**
* Groups the records of a table by assigning them to windows defined by a time or row interval.
*
*
For streaming tables of infinite size, grouping into windows is required to define finite
* groups on which group-based aggregates can be computed.
*
*
For batch tables of finite size, windowing essentially provides shortcuts for time-based
* groupBy.
*
*
Note: Computing windowed aggregates on a streaming table is only a parallel
* operation if additional grouping attributes are added to the {@code groupBy(...)} clause. If
* the {@code groupBy(...)} only references a GroupWindow alias, the streamed table will be
* processed by a single task, i.e., with parallelism 1.
*
* @param groupWindow groupWindow that specifies how elements are grouped.
* @return A windowed table.
*/
GroupWindowedTable window(GroupWindow groupWindow);
/**
* Defines over-windows on the records of a table.
*
*
An over-window defines for each record an interval of records over which aggregation
* functions can be computed.
*
*
Java Example:
*
*
{@code
* table
* .window(Over.partitionBy($("c")).orderBy($("rowTime")).preceding(lit(10).seconds()).as("ow")
* .select($("c"), $("b").count().over($("ow")), $("e").sum().over($("ow")));
* }
*
* Scala Example:
*
*
{@code
* table
* .window(Over partitionBy $"c" orderBy $"rowTime" preceding 10.seconds as "ow")
* .select($"c", $"b".count over $"ow", $"e".sum over $"ow")
* }
*
* Note: Computing over window aggregates on a streaming table is only a parallel
* operation if the window is partitioned. Otherwise, the whole stream will be processed by a
* single task, i.e., with parallelism 1.
*
*
Note: Over-windows for batch tables are currently not supported.
*
* @param overWindows windows that specify the record interval over which aggregations are
* computed.
* @return An OverWindowedTable to specify the aggregations.
*/
OverWindowedTable window(OverWindow... overWindows);
/**
* Adds additional columns. Similar to a SQL SELECT statement. The field expressions can contain
* complex expressions, but can not contain aggregations. It will throw an exception if the
* added fields already exist.
*
*
Java Example:
*
*
{@code
* tab.addColumns(
* $("a").plus(1).as("a1"),
* concat($("b"), "sunny").as("b1")
* );
* }
*
* Scala Example:
*
*
{@code
* tab.addColumns(
* $"a" + 1 as "a1",
* concat($"b", "sunny") as "b1"
* )
* }
*/
Table addColumns(Expression... fields);
/**
* Adds additional columns. Similar to a SQL SELECT statement. The field expressions can contain
* complex expressions, but can not contain aggregations. Existing fields will be replaced. If
* the added fields have duplicate field name, then the last one is used.
*
* Java Example:
*
*
{@code
* tab.addOrReplaceColumns(
* $("a").plus(1).as("a1"),
* concat($("b"), "sunny").as("b1")
* );
* }
*
* Scala Example:
*
*
{@code
* tab.addOrReplaceColumns(
* $"a" + 1 as "a1",
* concat($"b", "sunny") as "b1"
* )
* }
*/
Table addOrReplaceColumns(Expression... fields);
/**
* Renames existing columns. Similar to a field alias statement. The field expressions should be
* alias expressions, and only the existing fields can be renamed.
*
* Java Example:
*
*
{@code
* tab.renameColumns(
* $("a").as("a1"),
* $("b").as("b1")
* );
* }
*
* Scala Example:
*
*
{@code
* tab.renameColumns(
* $"a" as "a1",
* $"b" as "b1"
* )
* }
*/
Table renameColumns(Expression... fields);
/**
* Drops existing columns. The field expressions should be field reference expressions.
*
* Java Example:
*
*
{@code
* tab.dropColumns($("a"), $("b"));
* }
*
* Scala Example:
*
*
{@code
* tab.dropColumns($"a", $"b")
* }
*/
Table dropColumns(Expression... fields);
/**
* Performs a map operation with an user-defined scalar function or built-in scalar function.
* The output will be flattened if the output type is a composite type.
*
* Java Example:
*
*
{@code
* tab.map(call(MyMapFunction.class, $("c")))
* }
*
* Scala Example:
*
*
{@code
* val func = new MyMapFunction()
* tab.map(func($"c"))
* }
*/
Table map(Expression mapFunction);
/**
* Performs a flatMap operation with an user-defined table function or built-in table function.
* The output will be flattened if the output type is a composite type.
*
* Java Example:
*
*
{@code
* tab.flatMap(call(MyFlatMapFunction.class, $("c")))
* }
*
* Scala Example:
*
*
{@code
* val func = new MyFlatMapFunction()
* tab.flatMap(func($"c"))
* }
*/
Table flatMap(Expression tableFunction);
/**
* Performs a global aggregate operation with an aggregate function. You have to close the
* {@link #aggregate(Expression)} with a select statement. The output will be flattened if the
* output type is a composite type.
*
* Java Example:
*
*
{@code
* tab.aggregate(call(MyAggregateFunction.class, $("a"), $("b")).as("f0", "f1", "f2"))
* .select($("f0"), $("f1"));
* }
*
* Scala Example:
*
*
{@code
* val aggFunc = new MyAggregateFunction
* table.aggregate(aggFunc($"a", $"b") as ("f0", "f1", "f2"))
* .select($"f0", $"f1")
* }
*/
AggregatedTable aggregate(Expression aggregateFunction);
/**
* Perform a global flatAggregate without groupBy. FlatAggregate takes a TableAggregateFunction
* which returns multiple rows. Use a selection after the flatAggregate.
*
* Java Example:
*
*
{@code
* tab.flatAggregate(call(MyTableAggregateFunction.class, $("a"), $("b")).as("x", "y", "z"))
* .select($("x"), $("y"), $("z"));
* }
*
* Scala Example:
*
*
{@code
* val tableAggFunc: TableAggregateFunction = new MyTableAggregateFunction
* tab.flatAggregate(tableAggFunc($"a", $"b") as ("x", "y", "z"))
* .select($"x", $"y", $"z")
* }
*/
FlatAggregateTable flatAggregate(Expression tableAggregateFunction);
/**
* Declares that the pipeline defined by the given {@link Table} object should be written to a
* table (backed by a {@link DynamicTableSink}) that was registered under the specified path.
*
* See the documentation of {@link TableEnvironment#useDatabase(String)} or {@link
* TableEnvironment#useCatalog(String)} for the rules on the path resolution.
*
*
Example:
*
*
{@code
* Table table = tableEnv.sqlQuery("SELECT * FROM MyTable");
* TablePipeline tablePipeline = table.insertInto("MySinkTable");
* TableResult tableResult = tablePipeline.execute();
* tableResult.await();
* }
*
* One can execute the returned {@link TablePipeline} using {@link TablePipeline#execute()},
* or compile it to a {@link CompiledPlan} using {@link TablePipeline#compilePlan()}.
*
*
If multiple pipelines should insert data into one or more sink tables as part of a single
* execution, use a {@link StatementSet} (see {@link TableEnvironment#createStatementSet()}).
*
* @param tablePath The path of the registered table (backed by a {@link DynamicTableSink}).
* @return The complete pipeline from one or more source tables to a sink table.
*/
TablePipeline insertInto(String tablePath);
/**
* Declares that the pipeline defined by the given {@link Table} object should be written to a
* table (backed by a {@link DynamicTableSink}) that was registered under the specified path.
*
*
See the documentation of {@link TableEnvironment#useDatabase(String)} or {@link
* TableEnvironment#useCatalog(String)} for the rules on the path resolution.
*
*
Example:
*
*
{@code
* Table table = tableEnv.sqlQuery("SELECT * FROM MyTable");
* TablePipeline tablePipeline = table.insertInto("MySinkTable", true);
* TableResult tableResult = tablePipeline.execute();
* tableResult.await();
* }
*
* One can execute the returned {@link TablePipeline} using {@link TablePipeline#execute()},
* or compile it to a {@link CompiledPlan} using {@link TablePipeline#compilePlan()}.
*
*
If multiple pipelines should insert data into one or more sink tables as part of a single
* execution, use a {@link StatementSet} (see {@link TableEnvironment#createStatementSet()}).
*
* @param tablePath The path of the registered table (backed by a {@link DynamicTableSink}).
* @param overwrite Indicates whether existing data should be overwritten.
* @return The complete pipeline from one or more source tables to a sink table.
*/
TablePipeline insertInto(String tablePath, boolean overwrite);
/**
* Declares that the pipeline defined by the given {@link Table} object should be written to a
* table (backed by a {@link DynamicTableSink}) expressed via the given {@link TableDescriptor}.
*
*
The {@link TableDescriptor descriptor} won't be registered in the catalog, but it will be
* propagated directly in the operation tree. Note that calling this method multiple times, even
* with the same descriptor, results in multiple sink tables instances.
*
*
This method allows to declare a {@link Schema} for the sink descriptor. The declaration is
* similar to a {@code CREATE TABLE} DDL in SQL and allows to:
*
*
* - overwrite automatically derived columns with a custom {@link DataType}
*
- add metadata columns next to the physical columns
*
- declare a primary key
*
*
* It is possible to declare a schema without physical/regular columns. In this case, those
* columns will be automatically derived and implicitly put at the beginning of the schema
* declaration.
*
*
Examples:
*
*
{@code
* Schema schema = Schema.newBuilder()
* .column("f0", DataTypes.STRING())
* .build();
*
* Table table = tableEnv.from(TableDescriptor.forConnector("datagen")
* .schema(schema)
* .build());
*
* table.insertInto(TableDescriptor.forConnector("blackhole")
* .schema(schema)
* .build());
* }
*
* One can execute the returned {@link TablePipeline} using {@link TablePipeline#execute()},
* or compile it to a {@link CompiledPlan} using {@link TablePipeline#compilePlan()}.
*
*
If multiple pipelines should insert data into one or more sink tables as part of a single
* execution, use a {@link StatementSet} (see {@link TableEnvironment#createStatementSet()}).
*
* @param descriptor Descriptor describing the sink table into which data should be inserted.
* @return The complete pipeline from one or more source tables to a sink table.
*/
TablePipeline insertInto(TableDescriptor descriptor);
/**
* Declares that the pipeline defined by the given {@link Table} object should be written to a
* table (backed by a {@link DynamicTableSink}) expressed via the given {@link TableDescriptor}.
*
*
The {@link TableDescriptor descriptor} won't be registered in the catalog, but it will be
* propagated directly in the operation tree. Note that calling this method multiple times, even
* with the same descriptor, results in multiple sink tables being registered.
*
*
This method allows to declare a {@link Schema} for the sink descriptor. The declaration is
* similar to a {@code CREATE TABLE} DDL in SQL and allows to:
*
*
* - overwrite automatically derived columns with a custom {@link DataType}
*
- add metadata columns next to the physical columns
*
- declare a primary key
*
*
* It is possible to declare a schema without physical/regular columns. In this case, those
* columns will be automatically derived and implicitly put at the beginning of the schema
* declaration.
*
*
Examples:
*
*
{@code
* Schema schema = Schema.newBuilder()
* .column("f0", DataTypes.STRING())
* .build();
*
* Table table = tableEnv.from(TableDescriptor.forConnector("datagen")
* .schema(schema)
* .build());
*
* table.insertInto(TableDescriptor.forConnector("blackhole")
* .schema(schema)
* .build(), true);
* }
*
* One can execute the returned {@link TablePipeline} using {@link TablePipeline#execute()},
* or compile it to a {@link CompiledPlan} using {@link TablePipeline#compilePlan()}.
*
*
If multiple pipelines should insert data into one or more sink tables as part of a single
* execution, use a {@link StatementSet} (see {@link TableEnvironment#createStatementSet()}).
*
* @param descriptor Descriptor describing the sink table into which data should be inserted.
* @param overwrite Indicates whether existing data should be overwritten.
* @return The complete pipeline from one or more source tables to a sink table.
*/
TablePipeline insertInto(TableDescriptor descriptor, boolean overwrite);
/**
* Shorthand for {@code tableEnv.insertInto(tablePath).execute()}.
*
* @see #insertInto(String)
* @see TablePipeline#execute()
*/
default TableResult executeInsert(String tablePath) {
return insertInto(tablePath).execute();
}
/**
* Shorthand for {@code tableEnv.insertInto(tablePath, overwrite).execute()}.
*
* @see #insertInto(String, boolean)
* @see TablePipeline#execute()
*/
default TableResult executeInsert(String tablePath, boolean overwrite) {
return insertInto(tablePath, overwrite).execute();
}
/**
* Shorthand for {@code tableEnv.insertInto(descriptor).execute()}.
*
* @see #insertInto(TableDescriptor)
* @see TablePipeline#execute()
*/
default TableResult executeInsert(TableDescriptor descriptor) {
return insertInto(descriptor).execute();
}
/**
* Shorthand for {@code tableEnv.insertInto(descriptor, overwrite).execute()}.
*
* @see #insertInto(TableDescriptor, boolean)
* @see TablePipeline#execute()
*/
default TableResult executeInsert(TableDescriptor descriptor, boolean overwrite) {
return insertInto(descriptor, overwrite).execute();
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy