2024-12-31 03:09:33 +00:00
package com.taosdata.flink.example ;
2025-03-26 12:37:48 +00:00
import com.example.ResultBean ;
2024-12-31 03:09:33 +00:00
import com.taosdata.flink.common.TDengineConfigParams ;
import com.taosdata.flink.sink.TDengineSink ;
import com.taosdata.jdbc.TSDBDriver ;
2025-03-26 12:37:48 +00:00
import org.apache.flink.streaming.api.datastream.DataStream ;
2024-12-31 03:09:33 +00:00
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment ;
2025-03-26 12:37:48 +00:00
import org.apache.flink.table.api.* ;
import org.apache.flink.table.data.GenericRowData ;
2024-12-31 03:09:33 +00:00
import org.apache.flink.table.data.RowData ;
2025-03-26 12:37:48 +00:00
import org.apache.flink.table.data.StringData ;
import org.apache.flink.table.data.TimestampData ;
import org.apache.flink.types.Row ;
2024-12-31 03:09:33 +00:00
2025-03-26 12:37:48 +00:00
import java.sql.* ;
import java.util.* ;
2024-12-31 03:09:33 +00:00
public class Main {
static String jdbcUrl = " jdbc:TAOS-WS://localhost:6041?user=root&password=taosdata " ;
static void prepare ( ) throws ClassNotFoundException , SQLException {
Properties properties = new Properties ( ) ;
properties . setProperty ( TSDBDriver . PROPERTY_KEY_ENABLE_AUTO_RECONNECT , " true " ) ;
properties . setProperty ( TSDBDriver . PROPERTY_KEY_CHARSET , " UTF-8 " ) ;
properties . setProperty ( TSDBDriver . PROPERTY_KEY_TIME_ZONE , " UTC-8 " ) ;
Class . forName ( " com.taosdata.jdbc.ws.WebSocketDriver " ) ;
try ( Connection connection = DriverManager . getConnection ( jdbcUrl , properties ) ;
Statement stmt = connection . createStatement ( ) ) {
stmt . executeUpdate ( " DROP database IF EXISTS power_sink " ) ;
// create database
stmt . executeUpdate ( " CREATE DATABASE IF NOT EXISTS power_sink vgroups 5 " ) ;
stmt . executeUpdate ( " use power_sink " ) ;
2025-03-26 12:37:48 +00:00
2024-12-31 03:09:33 +00:00
// create table
stmt . executeUpdate ( " CREATE STABLE IF NOT EXISTS sink_meters (ts timestamp, current float, voltage int, phase float) TAGS (location binary(64), groupId int); " ) ;
// you can check rowsAffected here
stmt . executeUpdate ( " CREATE TABLE IF NOT EXISTS sink_normal (ts timestamp, current float, voltage int, phase float); " ) ;
// you can check rowsAffected here
} catch ( Exception ex ) {
// please refer to the JDBC specifications for detailed exceptions info
2025-03-26 12:37:48 +00:00
System . out . printf ( " Failed to create database power_sink or stable meters, %sErrMessage: %s%n " ,
2024-12-31 03:09:33 +00:00
ex instanceof SQLException ? " ErrCode: " + ( ( SQLException ) ex ) . getErrorCode ( ) + " , " : " " ,
ex . getMessage ( ) ) ;
// Print stack trace for context in examples. Use logging in production.
throw ex ;
}
}
public static void main ( String [ ] args ) throws Exception {
prepare ( ) ;
2025-03-26 12:37:48 +00:00
if ( args ! = null & & args . length > 0 & & args [ 0 ] . equals ( " sink " ) ) {
testRowDataToSuperTable ( ) ;
testRowDataToNormalTable ( ) ;
testCustomTypeToSink ( ) ;
2024-12-31 03:09:33 +00:00
} else if ( args ! = null & & args . length > 0 & & args [ 0 ] . equals ( " table " ) ) {
2025-03-26 12:37:48 +00:00
testTableSqlToSink ( ) ;
testTableRowToSink ( ) ;
2024-12-31 03:09:33 +00:00
}
}
2025-03-26 12:37:48 +00:00
//ANCHOR: RowDataToSuperTable
static void testRowDataToSuperTable ( ) throws Exception {
2024-12-31 03:09:33 +00:00
StreamExecutionEnvironment env = StreamExecutionEnvironment . getExecutionEnvironment ( ) ;
env . setParallelism ( 1 ) ;
2025-03-26 12:37:48 +00:00
RowData [ ] rowDatas = new GenericRowData [ 10 ] ;
Random random = new Random ( System . currentTimeMillis ( ) ) ;
for ( int i = 0 ; i < 10 ; i + + ) {
GenericRowData row = new GenericRowData ( 7 ) ;
long current = System . currentTimeMillis ( ) + i * 1000 ;
row . setField ( 0 , TimestampData . fromEpochMillis ( current ) ) ; // ts
row . setField ( 1 , random . nextFloat ( ) * 30 ) ; // current
row . setField ( 2 , 300 + ( i + 1 ) ) ; // voltage
row . setField ( 3 , random . nextFloat ( ) ) ; // phase
row . setField ( 4 , StringData . fromString ( " location_ " + i ) ) ; // location
row . setField ( 5 , i ) ; // groupid
row . setField ( 6 , StringData . fromString ( " d0 " + i ) ) ; // tbname
rowDatas [ i ] = row ;
}
DataStream < RowData > dataStream = env . fromElements ( RowData . class , rowDatas ) ;
2024-12-31 03:09:33 +00:00
Properties sinkProps = new Properties ( ) ;
2025-03-26 12:37:48 +00:00
sinkProps . setProperty ( TSDBDriver . PROPERTY_KEY_ENABLE_AUTO_RECONNECT , " true " ) ;
sinkProps . setProperty ( TSDBDriver . PROPERTY_KEY_CHARSET , " UTF-8 " ) ;
sinkProps . setProperty ( TSDBDriver . PROPERTY_KEY_TIME_ZONE , " UTC-8 " ) ;
2024-12-31 03:09:33 +00:00
sinkProps . setProperty ( TDengineConfigParams . VALUE_DESERIALIZER , " RowData " ) ;
2025-03-26 12:37:48 +00:00
sinkProps . setProperty ( TDengineConfigParams . PROPERTY_KEY_DBNAME , " power_sink " ) ;
2024-12-31 03:09:33 +00:00
sinkProps . setProperty ( TDengineConfigParams . TD_SUPERTABLE_NAME , " sink_meters " ) ;
sinkProps . setProperty ( TDengineConfigParams . TD_JDBC_URL , " jdbc:TAOS-WS://localhost:6041/power_sink?user=root&password=taosdata " ) ;
sinkProps . setProperty ( TDengineConfigParams . TD_BATCH_SIZE , " 2000 " ) ;
2025-03-26 12:37:48 +00:00
TDengineSink < RowData > sink = new TDengineSink < > ( sinkProps , Arrays . asList ( " ts " , " current " , " voltage " , " phase " , " location " , " groupid " , " tbname " ) ) ;
dataStream . sinkTo ( sink ) ;
env . execute ( " flink tdengine sink " ) ;
2024-12-31 03:09:33 +00:00
}
2025-03-26 12:37:48 +00:00
//ANCHOR_END: RowDataToSuperTable
2024-12-31 03:09:33 +00:00
2025-03-26 12:37:48 +00:00
//ANCHOR: RowDataToNormalTable
static void testRowDataToNormalTable ( ) throws Exception {
2024-12-31 03:09:33 +00:00
StreamExecutionEnvironment env = StreamExecutionEnvironment . getExecutionEnvironment ( ) ;
2025-03-26 12:37:48 +00:00
env . setParallelism ( 1 ) ;
RowData [ ] rowDatas = new GenericRowData [ 10 ] ;
Random random = new Random ( System . currentTimeMillis ( ) ) ;
for ( int i = 0 ; i < 10 ; i + + ) {
GenericRowData row = new GenericRowData ( 4 ) ;
long current = System . currentTimeMillis ( ) + i * 1000 ;
row . setField ( 0 , TimestampData . fromEpochMillis ( current ) ) ; // ts
row . setField ( 1 , random . nextFloat ( ) * 30 ) ; // current
row . setField ( 2 , 300 + ( i + 1 ) ) ; // voltage
row . setField ( 3 , random . nextFloat ( ) ) ; // phase
rowDatas [ i ] = row ;
}
DataStream < RowData > dataStream = env . fromElements ( RowData . class , rowDatas ) ;
2024-12-31 03:09:33 +00:00
Properties sinkProps = new Properties ( ) ;
sinkProps . setProperty ( TSDBDriver . PROPERTY_KEY_ENABLE_AUTO_RECONNECT , " true " ) ;
2025-03-26 12:37:48 +00:00
sinkProps . setProperty ( TSDBDriver . PROPERTY_KEY_CHARSET , " UTF-8 " ) ;
2024-12-31 03:09:33 +00:00
sinkProps . setProperty ( TSDBDriver . PROPERTY_KEY_TIME_ZONE , " UTC-8 " ) ;
sinkProps . setProperty ( TDengineConfigParams . VALUE_DESERIALIZER , " RowData " ) ;
2025-03-26 12:37:48 +00:00
sinkProps . setProperty ( TDengineConfigParams . PROPERTY_KEY_DBNAME , " power_sink " ) ;
sinkProps . setProperty ( TDengineConfigParams . TD_TABLE_NAME , " sink_normal " ) ;
sinkProps . setProperty ( TDengineConfigParams . TD_JDBC_URL , " jdbc:TAOS-WS://localhost:6041/power_sink?user=root&password=taosdata " ) ;
2024-12-31 03:09:33 +00:00
sinkProps . setProperty ( TDengineConfigParams . TD_BATCH_SIZE , " 2000 " ) ;
2025-03-26 12:37:48 +00:00
TDengineSink < RowData > sink = new TDengineSink < > ( sinkProps , Arrays . asList ( " ts " , " current " , " voltage " , " phase " ) ) ;
dataStream . sinkTo ( sink ) ;
env . execute ( " flink tdengine sink " ) ;
2024-12-31 03:09:33 +00:00
}
2025-03-26 12:37:48 +00:00
//ANCHOR_END: RowDataToNormalTable
2024-12-31 03:09:33 +00:00
2025-03-26 12:37:48 +00:00
//ANCHOR: CustomTypeToNormalTable
static void testCustomTypeToSink ( ) throws Exception {
2024-12-31 03:09:33 +00:00
StreamExecutionEnvironment env = StreamExecutionEnvironment . getExecutionEnvironment ( ) ;
2025-03-26 12:37:48 +00:00
env . setParallelism ( 1 ) ;
ResultBean [ ] rowDatas = new ResultBean [ 10 ] ;
Random random = new Random ( System . currentTimeMillis ( ) ) ;
for ( int i = 0 ; i < 10 ; i + + ) {
ResultBean rowData = new ResultBean ( ) ;
long current = System . currentTimeMillis ( ) + i * 1000 ;
rowData . setTs ( new Timestamp ( current ) ) ;
rowData . setCurrent ( random . nextFloat ( ) * 30 ) ;
rowData . setVoltage ( 300 + ( i + 1 ) ) ;
rowData . setPhase ( random . nextFloat ( ) ) ;
rowData . setLocation ( " location_ " + i ) ;
rowData . setGroupid ( i ) ;
rowData . setTbname ( " d0 " + i ) ;
rowDatas [ i ] = rowData ;
}
2024-12-31 03:09:33 +00:00
2025-03-26 12:37:48 +00:00
DataStream < ResultBean > dataStream = env . fromElements ( ResultBean . class , rowDatas ) ;
2024-12-31 03:09:33 +00:00
2025-03-26 12:37:48 +00:00
Properties sinkProps = new Properties ( ) ;
sinkProps . setProperty ( TDengineConfigParams . PROPERTY_KEY_ENABLE_AUTO_RECONNECT , " true " ) ;
sinkProps . setProperty ( TDengineConfigParams . PROPERTY_KEY_CHARSET , " UTF-8 " ) ;
sinkProps . setProperty ( TSDBDriver . PROPERTY_KEY_TIME_ZONE , " UTC-8 " ) ;
sinkProps . setProperty ( TDengineConfigParams . VALUE_DESERIALIZER , " com.taosdata.flink.entity.ResultBeanSinkSerializer " ) ;
sinkProps . setProperty ( TDengineConfigParams . PROPERTY_KEY_DBNAME , " power_sink " ) ;
sinkProps . setProperty ( TDengineConfigParams . TD_SUPERTABLE_NAME , " sink_meters " ) ;
sinkProps . setProperty ( TDengineConfigParams . TD_JDBC_URL , " jdbc:TAOS-WS://localhost:6041/power_sink?user=root&password=taosdata " ) ;
sinkProps . setProperty ( TDengineConfigParams . TD_BATCH_SIZE , " 2000 " ) ;
TDengineSink < ResultBean > sink = new TDengineSink < > ( sinkProps , Arrays . asList ( " ts " , " current " , " voltage " , " phase " , " location " , " groupid " , " tbname " ) ) ;
dataStream . sinkTo ( sink ) ;
env . execute ( " flink tdengine sink " ) ;
}
//ANCHOR_END: CustomTypeToNormalTable
//ANCHOR: TableSqlToSink
static void testTableSqlToSink ( ) throws Exception {
EnvironmentSettings settings = EnvironmentSettings . newInstance ( ) . inStreamingMode ( ) . build ( ) ;
TableEnvironment tEnv = TableEnvironment . create ( settings ) ;
2024-12-31 03:09:33 +00:00
String tdengineSinkTableDDL = " CREATE TABLE `sink_meters` ( " +
" ts TIMESTAMP, " +
" `current` FLOAT, " +
" voltage INT, " +
" phase FLOAT, " +
2025-02-17 03:50:38 +00:00
" location VARCHAR(255), " +
2024-12-31 03:09:33 +00:00
" groupid INT, " +
2025-02-17 03:50:38 +00:00
" tbname VARCHAR(255) " +
2024-12-31 03:09:33 +00:00
" ) WITH ( " +
" 'connector' = 'tdengine-connector', " +
" 'td.jdbc.mode' = 'sink', " +
" 'td.jdbc.url' = 'jdbc:TAOS-WS://localhost:6041/power_sink?user=root&password=taosdata', " +
" 'sink.db.name' = 'power_sink', " +
" 'sink.supertable.name' = 'sink_meters' " +
" ) " ;
2025-03-26 12:37:48 +00:00
tEnv . executeSql ( tdengineSinkTableDDL ) ;
2024-12-31 03:09:33 +00:00
2025-03-26 12:37:48 +00:00
String insertQuery = " INSERT INTO sink_meters " +
" VALUES " +
" (CAST('2024-12-19 19:12:45' AS TIMESTAMP(6)), 50.30000, 201, 3.31003, 'California.SanFrancisco', 1, 'd1001'), " +
" (CAST('2024-12-19 19:12:46' AS TIMESTAMP(6)), 82.60000, 202, 0.33000, 'California.SanFrancisco', 1, 'd1001'), " +
" (CAST('2024-12-19 19:12:47' AS TIMESTAMP(6)), 92.30000, 203, 0.31000, 'California.SanFrancisco', 1, 'd1001'), " +
" (CAST('2024-12-19 19:12:45' AS TIMESTAMP(6)), 50.30000, 204, 3.25003, 'Alabama.Montgomery', 2, 'd1002'), " +
" (CAST('2024-12-19 19:12:46' AS TIMESTAMP(6)), 62.60000, 205, 0.33000, 'Alabama.Montgomery', 2, 'd1002'), " +
" (CAST('2024-12-19 19:12:47' AS TIMESTAMP(6)), 72.30000, 206, 0.31000, 'Alabama.Montgomery', 2, 'd1002'); " ;
TableResult tableResult = tEnv . executeSql ( insertQuery ) ;
tableResult . await ( ) ;
2024-12-31 03:09:33 +00:00
}
2025-03-26 12:37:48 +00:00
//ANCHOR_END: TableSqlToSink
//ANCHOR: NormalTableSqlToSink
static void testNormalTableSqlToSink ( ) throws Exception {
EnvironmentSettings settings = EnvironmentSettings . newInstance ( ) . inStreamingMode ( ) . build ( ) ;
TableEnvironment tEnv = TableEnvironment . create ( settings ) ;
2024-12-31 03:09:33 +00:00
2025-03-26 12:37:48 +00:00
String tdengineSinkTableDDL = " CREATE TABLE `sink_normal` ( " +
2024-12-31 03:09:33 +00:00
" ts TIMESTAMP, " +
" `current` FLOAT, " +
" voltage INT, " +
2025-03-26 12:37:48 +00:00
" phase FLOAT "
2024-12-31 03:09:33 +00:00
" ) WITH ( " +
" 'connector' = 'tdengine-connector', " +
2025-03-26 12:37:48 +00:00
" 'td.jdbc.mode' = 'sink', " +
" 'td.jdbc.url' = 'jdbc:TAOS-WS://localhost:6041/power_sink?user=root&password=taosdata', " +
" 'sink.db.name' = 'power_sink', " +
" 'sink.table.name' = 'sink_normal' " +
2024-12-31 03:09:33 +00:00
" ) " ;
2025-03-26 12:37:48 +00:00
tEnv . executeSql ( tdengineSinkTableDDL ) ;
String insertQuery = " INSERT INTO sink_normal " +
" VALUES " +
" (CAST('2024-12-19 19:12:45' AS TIMESTAMP(6)), 50.30000, 201, 3.31003), " +
" (CAST('2024-12-19 19:12:46' AS TIMESTAMP(6)), 82.60000, 202, 0.33000), " +
" (CAST('2024-12-19 19:12:47' AS TIMESTAMP(6)), 92.30000, 203, 0.31000), " +
" (CAST('2024-12-19 19:12:45' AS TIMESTAMP(6)), 50.30000, 204, 3.25003), " +
" (CAST('2024-12-19 19:12:46' AS TIMESTAMP(6)), 62.60000, 205, 0.33000), " +
" (CAST('2024-12-19 19:12:47' AS TIMESTAMP(6)), 72.30000, 206, 0.31000); " ;
TableResult tableResult = tEnv . executeSql ( insertQuery ) ;
tableResult . await ( ) ;
}
//ANCHOR_END: NormalTableSqlToSink
2024-12-31 03:09:33 +00:00
2025-03-26 12:37:48 +00:00
//ANCHOR: TableRowToSink
static void testTableRowToSink ( ) throws Exception {
EnvironmentSettings settings = EnvironmentSettings . newInstance ( ) . inBatchMode ( ) . build ( ) ;
TableEnvironment tEnv = TableEnvironment . create ( settings ) ;
2024-12-31 03:09:33 +00:00
String tdengineSinkTableDDL = " CREATE TABLE `sink_meters` ( " +
" ts TIMESTAMP, " +
" `current` FLOAT, " +
" voltage INT, " +
" phase FLOAT, " +
2025-02-17 03:50:38 +00:00
" location VARCHAR(255), " +
2024-12-31 03:09:33 +00:00
" groupid INT, " +
2025-02-17 03:50:38 +00:00
" tbname VARCHAR(255) " +
2024-12-31 03:09:33 +00:00
" ) WITH ( " +
" 'connector' = 'tdengine-connector', " +
2025-02-10 09:07:45 +00:00
" 'td.jdbc.mode' = 'sink', " +
2024-12-31 03:09:33 +00:00
" 'td.jdbc.url' = 'jdbc:TAOS-WS://localhost:6041/power_sink?user=root&password=taosdata', " +
" 'sink.db.name' = 'power_sink', " +
" 'sink.supertable.name' = 'sink_meters' " +
" ) " ;
2025-03-26 12:37:48 +00:00
tEnv . executeSql ( tdengineSinkTableDDL ) ;
int sum = 0 ;
String tbname = " d001 " ;
int groupId = 1 ;
String location = " California.SanFrancisco " ;
List < Row > rowDatas = new ArrayList < > ( ) ;
Random random = new Random ( System . currentTimeMillis ( ) ) ;
for ( int i = 0 ; i < 50 ; i + + ) {
sum + = 300 + ( i + 1 ) ;
long timestampInMillis = System . currentTimeMillis ( ) + i * 1000 ;
Row row = Row . of (
new Timestamp ( timestampInMillis ) , // ts
random . nextFloat ( ) * 30 , // current
300 + ( i + 1 ) , // voltage
random . nextFloat ( ) , // phase
location ,
groupId ,
tbname
) ;
rowDatas . add ( row ) ;
}
Table inputTable = tEnv . fromValues (
DataTypes . ROW (
DataTypes . FIELD ( " ts " , DataTypes . TIMESTAMP ( 6 ) ) ,
DataTypes . FIELD ( " current " , DataTypes . FLOAT ( ) ) ,
DataTypes . FIELD ( " voltage " , DataTypes . INT ( ) ) ,
DataTypes . FIELD ( " phase " , DataTypes . FLOAT ( ) ) ,
DataTypes . FIELD ( " location " , DataTypes . STRING ( ) ) ,
DataTypes . FIELD ( " groupid " , DataTypes . INT ( ) ) ,
DataTypes . FIELD ( " tbname " , DataTypes . STRING ( ) )
) ,
rowDatas
) ;
TableResult result = inputTable . executeInsert ( " sink_meters " ) ;
result . await ( ) ; // waiting for task completion
2024-12-31 03:09:33 +00:00
}
2025-03-26 12:37:48 +00:00
//ANCHOR_END: TableRowToSink
2024-12-31 03:09:33 +00:00
}