diff --git a/.gitignore b/.gitignore index ccb9405fc..a32168f1a 100644 --- a/.gitignore +++ b/.gitignore @@ -8,14 +8,9 @@ target/ *.eclipse.* *.iml plugins/ -sqlplugins/ lib/ .vertx/ .DS_Store bin/nohup.out .DS_Store bin/sideSql.txt -*.keytab -krb5.conf -.gradle -gradle \ No newline at end of file diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index 8be25f51c..000000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -1,22 +0,0 @@ -stages: - - validate - - test - -test-job: - stage: test - script: - - mvn clean org.jacoco:jacoco-maven-plugin:0.7.8:prepare-agent package -Dmaven.test.failure.ignore=true -q - only: - - v1.10.0_dev - tags: - - dt-insight-engine - -validate-job: - stage: validate - script: - - mvn sonar:sonar -Dsonar.projectKey="dt-insight-engine/flinkStreamSQL" -Dsonar.login=11974c5e9a29625efa09fdc3c3fdc031efb1aab1 -Dsonar.host.url=http://172.16.100.198:9000 -Dsonar.jdbc.url=jdbc:postgresql://172.16.100.198:5432/sonar -Dsonar.java.binaries=target/sonar - - sh ci/sonar_notify.sh - only: - - v1.10.0_dev - tags: - - dt-insight-engine diff --git a/README.md b/README.md index 8bdb3d2b7..6474dc052 100644 --- a/README.md +++ b/README.md @@ -1,47 +1,303 @@ -FlinkStreamSQL -============ -[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html) - -## 技术交流 -- 招聘**Flink开发工程师**,如果有兴趣,请联系思枢【微信号ysqwhiletrue】,注明招聘
- Flink开发工程师JD要求:
- 1.负责袋鼠云基于Flink的衍生框架数据同步flinkx和实时计算flinkstreamsql框架的开发;
- 2.调研和把握当前最新大数据实时计算技术,将其中的合适技术引入到平台中,改善产品,提升竞争力;
- 职位要求:
- 1、本科及以上学历,3年及以上的Flink开发经验,精通Java,熟悉Scala、Python优先考虑;
- 2、熟悉Flink原理,有基于Flink做过二次源码的开发,在github上贡献者Flink源码者优先;
- 3、有机器学习、数据挖掘相关经验者优先;
- 4、对新技术有快速学习和上手能力,对代码有一定的洁癖;
- 加分项:
- 1.在GitHub或其他平台上有过开源项目;
- 可以添加本人微信号ysqwhiletrue,注明招聘,如有意者发送简历至sishu@dtstack.com
-- 我们使用[钉钉](https://www.dingtalk.com/)沟通交流,可以搜索群号[**30537511**]或者扫描下面的二维码进入钉钉群 -
- -
- -## 介绍 -* 基于开源的flink,对其实时sql进行扩展 - * 自定义create table 语法(包括源表,输出表,维表) - * 自定义create view 语法 - * 自定义create function 语法 - * 实现了流与维表的join - * 支持原生FlinkSQL所有的语法 - * 扩展了输入和输出的性能指标到Task metrics - -## 目录 - -[ 1.1 demo](docs/demo.md) -[ 1.2 快速开始](docs/quickStart.md) -[ 1.3 参数配置](docs/config.md) -[ 1.4 支持的插件介绍和demo](docs/pluginsInfo.md) -[ 1.5 指标参数](docs/newMetric.md) -[ 1.6 自定义函数](docs/function.md) -[ 1.7 自定义视图](docs/createView.md) - -## 如何贡献FlinkStreamSQL - -[pr规范](docs/pr.md) - -## License -FlinkStreamSQL is under the Apache 2.0 license. See the [LICENSE](http://www.apache.org/licenses/LICENSE-2.0) file for details. \ No newline at end of file +# flinkStreamSQL +> * 基于开源的flink,对其实时sql进行扩展 +> > * 自定义create table 语法(包括源表,输出表,维表) +> > * 自定义create view 语法 +> > * 自定义create function 语法 +> > * 实现了流与维表的join +> > * 支持原生FLinkSQL所有的语法 +> > * 扩展了输入和输出的性能指标到promethus + + ## 新特性: + * 1.kafka源表支持not null语法,支持字符串类型的时间转换。 + * 2.rdb维表与DB建立连接时,周期进行连接,防止连接断开。rdbsink写入时,对连接进行检查。 + * 3.异步维表支持非等值连接,比如:<>,<,>。 + * 4.增加kafka数组解析 + * 5.增加kafka1.0以上版本的支持 + * 6.增加postgresql、kudu、clickhouse维表、结果表的支持 + * 7.支持插件的依赖方式,参考pluginLoadMode参数 + * 8.支持cep处理 + * 9.支持udaf + * 10.支持谓词下移 + + ## BUG修复: + * 1.修复不能解析sql中orderby,union语法。 + * 2.修复yarnPer模式提交失败的异常。 + * 3.一些bug的修复 + +# 已支持 + * 源表:kafka 0.9、0.10、0.11、1.x版本 + * 维表:mysql, SQlServer,oracle, hbase, mongo, redis, cassandra, serversocket, kudu, postgresql, clickhouse + * 结果表:mysql, SQlServer, oracle, hbase, elasticsearch5.x, mongo, redis, cassandra, console, kudu, postgresql, clickhouse + +# 后续开发计划 + * 维表快照 + * kafka avro格式 + * topN + +## 1 快速起步 +### 1.1 运行模式 + + +* 单机模式:对应Flink集群的单机模式 +* standalone模式:对应Flink集群的分布式模式 +* yarn模式:对应Flink集群的yarn模式 + +### 1.2 执行环境 + +* Java: JDK8及以上 +* Flink集群: 1.4,1.5,1.8(单机模式不需要安装Flink集群) +* 操作系统:理论上不限 + +### 1.3 打包 + +进入项目根目录,使用maven打包: + +``` +mvn clean package -Dmaven.test.skip + +打包结束后,项目根目录下会产生plugins目录,plugins目录下存放编译好的数据同步插件包,在lib目下存放job提交的包 +``` + +### 1.4 启动 + +#### 1.4.1 启动命令 + +``` +sh submit.sh -sql D:\sideSql.txt -name xctest -remoteSqlPluginPath /opt/dtstack/150_flinkplugin/sqlplugin -localSqlPluginPath D:\gitspace\flinkStreamSQL\plugins -addjar \["udf.jar\"\] -mode yarn -flinkconf D:\flink_home\kudu150etc -yarnconf D:\hadoop\etc\hadoopkudu -confProp \{\"time.characteristic\":\"EventTime\",\"sql.checkpoint.interval\":10000\} -yarnSessionConf \{\"yid\":\"application_1564971615273_38182\"} +``` + +#### 1.4.2 命令行参数选项 + +* **mode** + * 描述:执行模式,也就是flink集群的工作模式 + * local: 本地模式 + * standalone: 提交到独立部署模式的flink集群 + * yarn: 提交到yarn模式的flink集群(即提交到已有flink集群) + * yarnPer: yarn per_job模式提交(即创建新flink application) + * 必选:否 + * 默认值:local + +* **name** + * 描述:flink 任务对应名称。 + * 必选:是 + * 默认值:无 + +* **sql** + * 描述:执行flink sql 的主体语句。 + * 必选:是 + * 默认值:无 + +* **localSqlPluginPath** + * 描述:本地插件根目录地址,也就是打包后产生的plugins目录。 + * 必选:是 + * 默认值:无 + +* **remoteSqlPluginPath** + * 描述:flink执行集群上的插件根目录地址(将打包好的插件存放到各个flink节点上,如果是yarn集群需要存放到所有的nodemanager上)。 + * 必选:否 + * 默认值:无 + +* **addjar** + * 描述:扩展jar路径,当前主要是UDF定义的jar; + * 格式:json + * 必选:否 + * 默认值:无 + +* **confProp** + * 描述:一些参数设置 + * 格式: json + * 必选:是 (如无参数填写空json即可) + * 默认值:无 + * 可选参数: + * sql.env.parallelism: 默认并行度设置 + * sql.max.env.parallelism: 最大并行度设置 + * time.characteristic: 可选值[ProcessingTime|IngestionTime|EventTime] + * sql.checkpoint.interval: 设置了该参数表明开启checkpoint(ms) + * sql.checkpoint.mode: 可选值[EXACTLY_ONCE|AT_LEAST_ONCE] + * sql.checkpoint.timeout: 生成checkpoint的超时时间(ms) + * sql.max.concurrent.checkpoints: 最大并发生成checkpoint数 + * sql.checkpoint.cleanup.mode: 默认是不会将checkpoint存储到外部存储,[true(任务cancel之后会删除外部存储)|false(外部存储需要手动删除)] + * flinkCheckpointDataURI: 设置checkpoint的外部存储路径,根据实际的需求设定文件路径,hdfs://, file:// + * jobmanager.memory.mb: per_job模式下指定jobmanager的内存大小(单位MB, 默认值:768) + * taskmanager.memory.mb: per_job模式下指定taskmanager的内存大小(单位MB, 默认值:768) + * taskmanager.num: per_job模式下指定taskmanager的实例数(默认1) + * taskmanager.slots:per_job模式下指定每个taskmanager对应的slot数量(默认1) + * [prometheus 相关参数](docs/prometheus.md) per_job可指定metric写入到外部监控组件,以prometheus pushgateway举例 + + +* **flinkconf** + * 描述:flink配置文件所在的目录(单机模式下不需要),如/hadoop/flink-1.4.0/conf + * 必选:否 + * 默认值:无 + +* **yarnconf** + * 描述:Hadoop配置文件(包括hdfs和yarn)所在的目录(单机模式下不需要),如/hadoop/etc/hadoop + * 必选:否 + * 默认值:无 + +* **savePointPath** + * 描述:任务恢复点的路径 + * 必选:否 + * 默认值:无 + +* **allowNonRestoredState** + * 描述:指示保存点是否允许非还原状态的标志 + * 必选:否 + * 默认值:false + +* **flinkJarPath** + * 描述:per_job 模式提交需要指定本地的flink jar存放路径 + * 必选:否 + * 默认值:false + +* **queue** + * 描述:per_job 模式下指定的yarn queue + * 必选:否 + * 默认值:false + +* **pluginLoadMode** + * 描述:per_job 模式下的插件包加载方式。classpath:从每台机器加载插件包,shipfile:将需要插件从提交的节点上传到hdfs,不需要每台安装插件 + * 必选:否 + * 默认值:classpath + +* **yarnSessionConf** + * 描述:yarn session 模式下指定的运行的一些参数,[可参考](https://ci.apache.org/projects/flink/flink-docs-release-1.8/ops/cli.html),目前只支持指定yid + * 必选:否 + * 默认值:false + +## 2 结构 +### 2.1 源表插件 +* [kafka 源表插件](docs/kafkaSource.md) + +### 2.2 结果表插件 +* [elasticsearch 结果表插件](docs/elasticsearchSink.md) +* [hbase 结果表插件](docs/hbaseSink.md) +* [mysql 结果表插件](docs/mysqlSink.md) +* [oracle 结果表插件](docs/oracleSink.md) +* [mongo 结果表插件](docs/mongoSink.md) +* [redis 结果表插件](docs/redisSink.md) +* [cassandra 结果表插件](docs/cassandraSink.md) +* [kudu 结果表插件](docs/kuduSink.md) +* [postgresql 结果表插件](docs/postgresqlSink.md) +* [clickhouse 结果表插件](docs/clickhouseSink.md) + +### 2.3 维表插件 +* [hbase 维表插件](docs/hbaseSide.md) +* [mysql 维表插件](docs/mysqlSide.md) +* [oracle 维表插件](docs/oracleSide.md) +* [mongo 维表插件](docs/mongoSide.md) +* [redis 维表插件](docs/redisSide.md) +* [cassandra 维表插件](docs/cassandraSide.md) +* [kudu 维表插件](docs/kuduSide.md) +* [postgresql 维表插件](docs/postgresqlSide.md) +* [clickhouse 维表插件](docs/clickhouseSide.md) + +## 3 性能指标(新增) + +### kafka插件 +* 业务延迟: flink_taskmanager_job_task_operator_dtEventDelay(单位s) + 数据本身的时间和进入flink的当前时间的差值. + +* 各个输入源的脏数据:flink_taskmanager_job_task_operator_dtDirtyData + 从kafka获取的数据解析失败的视为脏数据 + +* 各Source的数据输入TPS: flink_taskmanager_job_task_operator_dtNumRecordsInRate + kafka接受的记录数(未解析前)/s + +* 各Source的数据输入RPS: flink_taskmanager_job_task_operator_dtNumRecordsInResolveRate + kafka接受的记录数(解析后)/s + +* 各Source的数据输入BPS: flink_taskmanager_job_task_operator_dtNumBytesInRate + kafka接受的字节数/s + +* Kafka作为输入源的各个分区的延迟数: flink_taskmanager_job_task_operator_topic_partition_dtTopicPartitionLag + 当前kafka10,kafka11有采集该指标 + +* 各个输出源RPS: flink_taskmanager_job_task_operator_dtNumRecordsOutRate + 写入的外部记录数/s + + +## 4 样例 + +``` + +CREATE (scala|table|aggregate) FUNCTION CHARACTER_LENGTH WITH com.dtstack.Kun; + + +CREATE TABLE MyTable( + name varchar, + channel varchar, + pv int, + xctime bigint, + CHARACTER_LENGTH(channel) AS timeLeng //自定义的函数 + )WITH( + type ='kafka09', + bootstrapServers ='172.16.8.198:9092', + zookeeperQuorum ='172.16.8.198:2181/kafka', + offsetReset ='latest', + topic ='nbTest1', + parallelism ='1' + ); + +CREATE TABLE MyResult( + channel varchar, + pv varchar + )WITH( + type ='mysql', + url ='jdbc:mysql://172.16.8.104:3306/test?charset=utf8', + userName ='dtstack', + password ='abc123', + tableName ='pv2', + parallelism ='1' + ); + +CREATE TABLE workerinfo( + cast(logtime as TIMESTAMP) AS rtime, + cast(logtime) AS rtime + )WITH( + type ='hbase', + zookeeperQuorum ='rdos1:2181', + tableName ='workerinfo', + rowKey ='ce,de', + parallelism ='1', + zookeeperParent ='/hbase' + ); + +CREATE TABLE sideTable( + cf:name varchar as name, + cf:info varchar as info, + PRIMARY KEY(name), + PERIOD FOR SYSTEM_TIME //维表标识 + )WITH( + type ='hbase', + zookeeperQuorum ='rdos1:2181', + zookeeperParent ='/hbase', + tableName ='workerinfo', + cache ='LRU', + cacheSize ='10000', + cacheTTLMs ='60000', + parallelism ='1' + ); + +insert +into + MyResult + select + d.channel, + d.info + from + ( select + a.*,b.info + from + MyTable a + join + sideTable b + on a.channel=b.name + where + a.channel = 'xc2' + and a.pv=10 ) as d +``` + +# 招聘 +1.大数据平台开发工程师,想了解岗位详细信息可以添加本人微信号ysqwhiletrue,注明招聘,如有意者发送简历至sishu@dtstack.com。 + diff --git a/README.md.back b/README.md.back deleted file mode 100644 index db25164b6..000000000 --- a/README.md.back +++ /dev/null @@ -1,328 +0,0 @@ -# flinkStreamSQL -> * 基于开源的flink,对其实时sql进行扩展 -> > * 自定义create table 语法(包括源表,输出表,维表) -> > * 自定义create view 语法 -> > * 自定义create function 语法 -> > * 实现了流与维表的join -> > * 支持原生FLinkSQL所有的语法 -> > * 扩展了输入和输出的性能指标到promethus - - ## 新特性: - * 1.kafka源表支持not null语法,支持字符串类型的时间转换。 - * 2.rdb维表与DB建立连接时,周期进行连接,防止连接断开。rdbsink写入时,对连接进行检查。 - * 3.异步维表支持非等值连接,比如:<>,<,>。 - * 4.增加kafka数组解析 - * 5.增加kafka1.0以上版本的支持 - * 6.增加postgresql、kudu、clickhouse维表、结果表的支持 - * 7.支持插件的依赖方式,参考pluginLoadMode参数 - * 8.支持cep处理 - * 9.支持udaf - * 10.支持谓词下移 - * 11.支持状态的ttl - - ## BUG修复: - * 1.修复不能解析sql中orderby,union语法。 - * 2.修复yarnPer模式提交失败的异常。 - * 3.一些bug的修复 - -# 已支持 - * 源表:kafka 0.9、0.10、0.11、1.x版本 - * 维表:mysql, SQlServer,oracle, hbase, mongo, redis, cassandra, serversocket, kudu, postgresql, clickhouse, impala, db2, sqlserver - * 结果表:mysql, SQlServer, oracle, hbase, elasticsearch5.x, mongo, redis, cassandra, console, kudu, postgresql, clickhouse, impala, db2, sqlserver - -# 后续开发计划 - * 维表快照 - * kafka avro格式 - * topN - -## 1 快速起步 -### 1.1 运行模式 - - -* 单机模式:对应Flink集群的单机模式 -* standalone模式:对应Flink集群的分布式模式 -* yarn模式:对应Flink集群的yarn模式 - -### 1.2 执行环境 - -* Java: JDK8及以上 -* Flink集群: 1.4,1.5,1.8(单机模式不需要安装Flink集群) -* 操作系统:理论上不限 -* kerberos环境需要在flink-conf.yaml配置security.kerberos.login.keytab以及security.kerberos.login.principal参数,配置案例: -``` -## hadoop配置文件路径 -fs.hdfs.hadoopconf: /Users/maqi/tmp/hadoopconf/hadoop_250 -security.kerberos.login.use-ticket-cache: true -security.kerberos.login.keytab: /Users/maqi/tmp/hadoopconf/hadoop_250/maqi.keytab -security.kerberos.login.principal: maqi@DTSTACK.COM -security.kerberos.login.contexts: Client,KafkaClient -zookeeper.sasl.service-name: zookeeper -zookeeper.sasl.login-context-name: Client - -``` - -### 1.3 打包 - -进入项目根目录,使用maven打包: - -``` -mvn clean package -Dmaven.test.skip - -``` - -打包完成后的包结构: - -> * dt-center-flinkStreamSQL -> > * bin: 任务启动脚本 -> > * lib: launcher包存储路径,是任务提交的入口 -> > * plugins: 插件包存储路径 -> > * ........ : core及插件代码 - -### 1.4 启动 - -#### 1.4.1 启动命令 - -``` -sh submit.sh -sql D:\sideSql.txt -name xctest -remoteSqlPluginPath /opt/dtstack/150_flinkplugin/sqlplugin -localSqlPluginPath D:\gitspace\flinkStreamSQL\plugins -addjar \["udf.jar\"\] -mode yarn -flinkconf D:\flink_home\kudu150etc -yarnconf D:\hadoop\etc\hadoopkudu -confProp \{\"time.characteristic\":\"EventTime\",\"sql.checkpoint.interval\":10000\} -yarnSessionConf \{\"yid\":\"application_1564971615273_38182\"} -``` - -#### 1.4.2 命令行参数选项 - -* **mode** - * 描述:执行模式,也就是flink集群的工作模式 - * local: 本地模式 - * standalone: 提交到独立部署模式的flink集群 - * yarn: 提交到yarn模式的flink集群(即提交到已有flink集群) - * yarnPer: yarn per_job模式提交(即创建新flink application) - * 必选:否 - * 默认值:local - -* **name** - * 描述:flink 任务对应名称。 - * 必选:是 - * 默认值:无 - -* **sql** - * 描述:执行flink sql 的主体语句。 - * 必选:是 - * 默认值:无 - -* **localSqlPluginPath** - * 描述:本地插件根目录地址,也就是打包后产生的plugins目录。 - * 必选:是 - * 默认值:无 - -* **remoteSqlPluginPath** - * 描述:flink执行集群上的插件根目录地址(将打包好的插件存放到各个flink节点上,如果是yarn集群需要存放到所有的nodemanager上)。 - * 必选:否 - * 默认值:无 - -* **addjar** - * 描述:扩展jar路径,当前主要是UDF定义的jar; - * 格式:json - * 必选:否 - * 默认值:无 - -* **confProp** - * 描述:一些参数设置 - * 格式: json - * 必选:是 (如无参数填写空json即可) - * 默认值:无 - * 可选参数: - * sql.ttl.min: 最小过期时间,大于0的整数,如1d、1h(d\D:天,h\H:小时,m\M:分钟,s\s:秒) - * sql.ttl.max: 最大过期时间,大于0的整数,如2d、2h(d\D:天,h\H:小时,m\M:分钟,s\s:秒),需同时设置最小时间,且比最小时间大5分钟 - * state.backend: 任务状态后端,可选为MEMORY,FILESYSTEM,ROCKSDB,默认为flinkconf中的配置。 - * state.checkpoints.dir: FILESYSTEM,ROCKSDB状态后端文件系统存储路径,例如:hdfs://ns1/dtInsight/flink180/checkpoints。 - * state.backend.incremental: ROCKSDB状态后端是否开启增量checkpoint,默认为true。 - * sql.env.parallelism: 默认并行度设置 - * sql.max.env.parallelism: 最大并行度设置 - * time.characteristic: 可选值[ProcessingTime|IngestionTime|EventTime] - * sql.checkpoint.interval: 设置了该参数表明开启checkpoint(ms) - * sql.checkpoint.mode: 可选值[EXACTLY_ONCE|AT_LEAST_ONCE] - * sql.checkpoint.timeout: 生成checkpoint的超时时间(ms) - * sql.max.concurrent.checkpoints: 最大并发生成checkpoint数 - * sql.checkpoint.cleanup.mode: 默认是不会将checkpoint存储到外部存储,[true(任务cancel之后会删除外部存储)|false(外部存储需要手动删除)] - * flinkCheckpointDataURI: 设置checkpoint的外部存储路径,根据实际的需求设定文件路径,hdfs://, file:// - * jobmanager.memory.mb: per_job模式下指定jobmanager的内存大小(单位MB, 默认值:768) - * taskmanager.memory.mb: per_job模式下指定taskmanager的内存大小(单位MB, 默认值:768) - * taskmanager.num: per_job模式下指定taskmanager的实例数(默认1) - * taskmanager.slots:per_job模式下指定每个taskmanager对应的slot数量(默认1) - * savePointPath:任务恢复点的路径(默认无) - * allowNonRestoredState:指示保存点是否允许非还原状态的标志(默认false) - * logLevel: 日志级别动态配置(默认info) - * [prometheus 相关参数](docs/prometheus.md) per_job可指定metric写入到外部监控组件,以prometheus pushgateway举例 - - -* **flinkconf** - * 描述:flink配置文件所在的目录(单机模式下不需要),如/hadoop/flink-1.4.0/conf - * 必选:否 - * 默认值:无 - -* **yarnconf** - * 描述:Hadoop配置文件(包括hdfs和yarn)所在的目录(单机模式下不需要),如/hadoop/etc/hadoop - * 必选:否 - * 默认值:无 - -* **flinkJarPath** - * 描述:per_job 模式提交需要指定本地的flink jar存放路径 - * 必选:否 - * 默认值:false - -* **queue** - * 描述:per_job 模式下指定的yarn queue - * 必选:否 - * 默认值:false - -* **pluginLoadMode** - * 描述:per_job 模式下的插件包加载方式。classpath:从每台机器加载插件包,shipfile:将需要插件从提交的节点上传到hdfs,不需要每台安装插件 - * 必选:否 - * 默认值:classpath - -* **yarnSessionConf** - * 描述:yarn session 模式下指定的运行的一些参数,[可参考](https://ci.apache.org/projects/flink/flink-docs-release-1.8/ops/cli.html),目前只支持指定yid - * 必选:否 - * 默认值:false - - -## 2 结构 -### 2.1 源表插件 -* [kafka 源表插件](docs/kafkaSource.md) - -### 2.2 结果表插件 -* [elasticsearch 结果表插件](docs/elasticsearchSink.md) -* [hbase 结果表插件](docs/hbaseSink.md) -* [mysql 结果表插件](docs/mysqlSink.md) -* [oracle 结果表插件](docs/oracleSink.md) -* [mongo 结果表插件](docs/mongoSink.md) -* [redis 结果表插件](docs/redisSink.md) -* [cassandra 结果表插件](docs/cassandraSink.md) -* [kudu 结果表插件](docs/kuduSink.md) -* [postgresql 结果表插件](docs/postgresqlSink.md) -* [clickhouse 结果表插件](docs/clickhouseSink.md) -* [impala 结果表插件](docs/impalaSink.md) -* [db2 结果表插件](docs/db2Sink.md) -* [sqlserver 结果表插件](docs/sqlserverSink.md) - -### 2.3 维表插件 -* [hbase 维表插件](docs/hbaseSide.md) -* [mysql 维表插件](docs/mysqlSide.md) -* [oracle 维表插件](docs/oracleSide.md) -* [mongo 维表插件](docs/mongoSide.md) -* [redis 维表插件](docs/redisSide.md) -* [cassandra 维表插件](docs/cassandraSide.md) -* [kudu 维表插件](docs/kuduSide.md) -* [postgresql 维表插件](docs/postgresqlSide.md) -* [clickhouse 维表插件](docs/clickhouseSide.md) -* [impala 维表插件](docs/impalaSide.md) -* [db2 维表插件](docs/db2Side.md) -* [sqlserver 维表插件](docs/sqlserverSide.md) - -## 3 性能指标(新增) - -### kafka插件 -* 业务延迟: flink_taskmanager_job_task_operator_dtEventDelay(单位s) - 数据本身的时间和进入flink的当前时间的差值. - -* 各个输入源的脏数据:flink_taskmanager_job_task_operator_dtDirtyData - 从kafka获取的数据解析失败的视为脏数据 - -* 各Source的数据输入TPS: flink_taskmanager_job_task_operator_dtNumRecordsInRate - kafka接受的记录数(未解析前)/s - -* 各Source的数据输入RPS: flink_taskmanager_job_task_operator_dtNumRecordsInResolveRate - kafka接受的记录数(解析后)/s - -* 各Source的数据输入BPS: flink_taskmanager_job_task_operator_dtNumBytesInRate - kafka接受的字节数/s - -* Kafka作为输入源的各个分区的延迟数: flink_taskmanager_job_task_operator_topic_partition_dtTopicPartitionLag - 当前kafka10,kafka11有采集该指标 - -* 各个输出源RPS: flink_taskmanager_job_task_operator_dtNumRecordsOutRate - 写入的外部记录数/s - - -## 4 样例 - -``` - -CREATE (scala|table|aggregate) FUNCTION CHARACTER_LENGTH WITH com.dtstack.Kun; - - -CREATE TABLE MyTable( - name varchar, - channel varchar, - pv int, - xctime bigint, - CHARACTER_LENGTH(channel) AS timeLeng //自定义的函数 - )WITH( - type ='kafka09', - bootstrapServers ='172.16.8.198:9092', - zookeeperQuorum ='172.16.8.198:2181/kafka', - offsetReset ='latest', - topic ='nbTest1', - parallelism ='1' - ); - -CREATE TABLE MyResult( - channel varchar, - pv varchar - )WITH( - type ='mysql', - url ='jdbc:mysql://172.16.8.104:3306/test?charset=utf8', - userName ='dtstack', - password ='abc123', - tableName ='pv2', - parallelism ='1' - ); - -CREATE TABLE workerinfo( - cast(logtime as TIMESTAMP) AS rtime, - cast(logtime) AS rtime - )WITH( - type ='hbase', - zookeeperQuorum ='rdos1:2181', - tableName ='workerinfo', - rowKey ='ce,de', - parallelism ='1', - zookeeperParent ='/hbase' - ); - -CREATE TABLE sideTable( - cf:name varchar as name, - cf:info varchar as info, - PRIMARY KEY(name), - PERIOD FOR SYSTEM_TIME //维表标识 - )WITH( - type ='hbase', - zookeeperQuorum ='rdos1:2181', - zookeeperParent ='/hbase', - tableName ='workerinfo', - cache ='LRU', - cacheSize ='10000', - cacheTTLMs ='60000', - parallelism ='1' - ); - -insert -into - MyResult - select - d.channel, - d.info - from - ( select - a.*,b.info - from - MyTable a - join - sideTable b - on a.channel=b.name - where - a.channel = 'xc2' - and a.pv=10 ) as d -``` - -# 招聘 -1.大数据平台开发工程师,想了解岗位详细信息可以添加本人微信号ysqwhiletrue,注明招聘,如有意者发送简历至sishu@dtstack.com。 - diff --git a/aws/aws-sink/src/main/java/com/dtstack/flink/sql/sink/aws/AwsConstantKey.java b/aws/aws-sink/src/main/java/com/dtstack/flink/sql/sink/aws/AwsConstantKey.java deleted file mode 100644 index 182214169..000000000 --- a/aws/aws-sink/src/main/java/com/dtstack/flink/sql/sink/aws/AwsConstantKey.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.aws; - -/** - * @author tiezhu - * date 2020/12/1 - * company dtstack - */ -public class AwsConstantKey { - - public static final String PARALLELISM_KEY = "parallelism"; - - public static final String ACCESS_KEY = "accessKey"; - public static final String SECRET_KEY = "secretKey"; - public static final String BUCKET_KEY = "bucket"; - public static final String HOST_NAME = "hostname"; - public static final String STORAGE_TYPE = "storageType"; - public static final String BUCKET_ACL = "bucketAcl"; - public static final String OBJECT_NAME = "objectName"; - - public static final String PUBLIC_READ_WRITE = "public-read-write"; - public static final String PRIVATE = "private"; - public static final String PUBLIC_READ = "public-read"; - public static final String AUTHENTICATED_READ = "authenticated-read"; - public static final String LOG_DELIVERY_READ = "log-delivery-write"; - public static final String BUCKET_OWNER_READER = "bucket-owner-read"; - public static final String BUCKET_OWNER_FULL_CONTROL = "bucket-owner-full-control"; - - public static final String STANDARD = "standard"; - public static final String STANDARD_IA = "standard_ia"; - public static final String REDUCED_REDUNDANCY = "reduced_redundancy"; - public static final String GLACIER = "glacier"; - -} diff --git a/aws/aws-sink/src/main/java/com/dtstack/flink/sql/sink/aws/AwsOutputFormat.java b/aws/aws-sink/src/main/java/com/dtstack/flink/sql/sink/aws/AwsOutputFormat.java deleted file mode 100644 index ef52a4cff..000000000 --- a/aws/aws-sink/src/main/java/com/dtstack/flink/sql/sink/aws/AwsOutputFormat.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.aws; - -import com.amazonaws.services.s3.AmazonS3Client; -import com.amazonaws.services.s3.model.AppendObjectRequest; -import com.amazonaws.services.s3.model.ObjectMetadata; -import com.dtstack.flink.sql.outputformat.AbstractDtRichOutputFormat; -import com.dtstack.flink.sql.sink.aws.util.AwsManager; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.configuration.Configuration; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.Objects; - -/** - * @author tiezhu - * date 2020/12/1 - * company dtstack - */ -public class AwsOutputFormat extends AbstractDtRichOutputFormat { - - private static final Logger LOG = LoggerFactory.getLogger(AwsOutputFormat.class); - - private static final String LINE_BREAK = "\n"; - - private transient AmazonS3Client client; - - private String accessKey; - private String secretKey; - private String bucket; - private String bucketAcl; - private String objectName; - private String hostname; - private InputStream inputStream; - private Long position = 0L; - - private AwsOutputFormat() { - } - - @Override - public void configure(Configuration parameters) { - LOG.warn("--- configure client ---"); - client = AwsManager.initClient(accessKey, secretKey, hostname); - } - - @Override - public void open(int taskNumber, int numTasks) throws IOException { - LOG.warn("--- open ---"); - initMetric(); - position = AwsManager.getObjectPosition(bucket, objectName, client); - } - - @Override - public void writeRecord(Tuple2 record) throws IOException { - String recordStr = record.f1.toString() + LINE_BREAK; - int length = recordStr.getBytes().length; - inputStream = new ByteArrayInputStream(recordStr.getBytes()); - ObjectMetadata metadata = new ObjectMetadata(); - metadata.setContentLength(length); - // 追加流式写入,但是这种情况下,可能会出现oom【因为数据都是缓存在内存中】 - AppendObjectRequest appendObjectRequest = new AppendObjectRequest( - bucket, objectName, inputStream, metadata) - .withPosition(position); - - client.appendObject(appendObjectRequest); - position += length; - outRecords.inc(); - } - - @Override - public void close() throws IOException { - if (Objects.nonNull(inputStream)) { - inputStream.close(); - } - - if (Objects.nonNull(client)) { - client.shutdown(); - } - } - - public static AwsOutputFormatBuilder buildS3OutputFormat() { - return new AwsOutputFormatBuilder(); - } - - public static class AwsOutputFormatBuilder { - private final AwsOutputFormat awsOutputFormat; - - private AwsOutputFormatBuilder() { - awsOutputFormat = new AwsOutputFormat(); - } - - public AwsOutputFormatBuilder setAccessKey(String accessKey) { - awsOutputFormat.accessKey = accessKey; - return this; - } - - public AwsOutputFormatBuilder setSecretKey(String secretKey) { - awsOutputFormat.secretKey = secretKey; - return this; - } - - public AwsOutputFormatBuilder setBucket(String bucket) { - awsOutputFormat.bucket = bucket; - return this; - } - - public AwsOutputFormatBuilder setBucketAcl(String bucketAcl) { - awsOutputFormat.bucketAcl = bucketAcl; - return this; - } - - public AwsOutputFormatBuilder setHostname(String hostname) { - awsOutputFormat.hostname = hostname; - return this; - } - - public AwsOutputFormatBuilder setObjectName(String objectName) { - awsOutputFormat.objectName = objectName; - return this; - } - - public AwsOutputFormat finish() { - return awsOutputFormat; - } - } -} diff --git a/aws/aws-sink/src/main/java/com/dtstack/flink/sql/sink/aws/AwsSink.java b/aws/aws-sink/src/main/java/com/dtstack/flink/sql/sink/aws/AwsSink.java deleted file mode 100644 index 118ad74e0..000000000 --- a/aws/aws-sink/src/main/java/com/dtstack/flink/sql/sink/aws/AwsSink.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.aws; - -import com.dtstack.flink.sql.sink.IStreamSinkGener; -import com.dtstack.flink.sql.sink.aws.table.AwsTableInfo; -import com.dtstack.flink.sql.table.AbstractTargetTableInfo; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.api.java.typeutils.TupleTypeInfo; -import org.apache.flink.streaming.api.datastream.DataStream; -import org.apache.flink.streaming.api.datastream.DataStreamSink; -import org.apache.flink.streaming.api.functions.sink.OutputFormatSinkFunction; -import org.apache.flink.streaming.api.functions.sink.RichSinkFunction; -import org.apache.flink.table.sinks.RetractStreamTableSink; -import org.apache.flink.table.sinks.TableSink; -import org.apache.flink.types.Row; - -import java.util.Objects; - -/** - * @author tiezhu - * date 2020/12/1 - * company dtstack - */ -public class AwsSink implements RetractStreamTableSink, IStreamSinkGener { - - protected String[] fieldNames; - TypeInformation[] fieldTypes; - protected String accessKey; - protected String secretKey; - protected String bucket; - protected String bucketAcl; - protected String storageType; - protected String hostname; - protected String objectName; - protected String registerName; - - protected int parallelism = 1; - - public AwsSink() { - } - - @Override - public AwsSink genStreamSink(AbstractTargetTableInfo targetTableInfo) { - AwsTableInfo tableInfo = (AwsTableInfo) targetTableInfo; - this.accessKey = tableInfo.getAccessKey(); - this.secretKey = tableInfo.getSecretKey(); - this.bucket = tableInfo.getBucketName(); - this.bucketAcl = tableInfo.getBucketAcl(); - this.hostname = tableInfo.getHostname(); - this.storageType = tableInfo.getStorageType(); - this.objectName = tableInfo.getObjectName(); - - this.fieldNames = tableInfo.getFields(); - Integer s3TableInfoParallelism = tableInfo.getParallelism(); - if (Objects.nonNull(s3TableInfoParallelism)) { - this.parallelism = s3TableInfoParallelism; - } - this.registerName = tableInfo.getName(); - - return this; - } - - @Override - public void emitDataStream(DataStream> dataStream) { - - } - - @Override - public DataStreamSink consumeDataStream(DataStream> dataStream) { - AwsOutputFormat.AwsOutputFormatBuilder builder = AwsOutputFormat.buildS3OutputFormat(); - AwsOutputFormat awsOutputFormat = builder.setAccessKey(accessKey) - .setBucket(bucket) - .setBucketAcl(bucketAcl) - .setHostname(hostname) - .setObjectName(objectName) - .setSecretKey(secretKey) - .finish(); - RichSinkFunction outputFormatSinkFunction = new OutputFormatSinkFunction(awsOutputFormat); - DataStreamSink dataStreamSink = dataStream.addSink(outputFormatSinkFunction).name(registerName); - if (parallelism > 0) { - dataStreamSink.setParallelism(parallelism); - } - return dataStreamSink; - } - - @Override - public TableSink> configure(String[] fieldNames, TypeInformation[] fieldTypes) { - this.fieldNames = fieldNames; - this.fieldTypes = fieldTypes; - return this; - } - - @Override - public TupleTypeInfo> getOutputType() { - return new TupleTypeInfo<>(org.apache.flink.table.api.Types.BOOLEAN(), getRecordType()); - } - - @Override - public String[] getFieldNames() { - return fieldNames; - } - - @Override - public TypeInformation[] getFieldTypes() { - return fieldTypes; - } - - @Override - public TypeInformation getRecordType() { - return new RowTypeInfo(fieldTypes, fieldNames); - } -} diff --git a/aws/aws-sink/src/main/java/com/dtstack/flink/sql/sink/aws/table/AwsSinkParser.java b/aws/aws-sink/src/main/java/com/dtstack/flink/sql/sink/aws/table/AwsSinkParser.java deleted file mode 100644 index 297bd801e..000000000 --- a/aws/aws-sink/src/main/java/com/dtstack/flink/sql/sink/aws/table/AwsSinkParser.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.aws.table; - -import com.dtstack.flink.sql.sink.aws.AwsConstantKey; -import com.dtstack.flink.sql.table.AbstractTableInfo; -import com.dtstack.flink.sql.table.AbstractTableParser; -import com.dtstack.flink.sql.util.MathUtil; - -import java.util.Map; - -/** - * @author tiezhu - * date 2020/12/1 - * company dtstack - */ -public class AwsSinkParser extends AbstractTableParser { - @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) throws Exception { - AwsTableInfo tableInfo = new AwsTableInfo(); - tableInfo.setName(tableName); - parseFieldsInfo(fieldsInfo, tableInfo); - - tableInfo.setParallelism(MathUtil.getIntegerVal(props.get(AwsConstantKey.PARALLELISM_KEY.toLowerCase()))); - tableInfo.setAccessKey(MathUtil.getString(props.get(AwsConstantKey.ACCESS_KEY.toLowerCase()))); - tableInfo.setSecretKey(MathUtil.getString(props.get(AwsConstantKey.SECRET_KEY.toLowerCase()))); - tableInfo.setStorageType(MathUtil.getString(props.get(AwsConstantKey.STORAGE_TYPE.toLowerCase()))); - tableInfo.setHostname(MathUtil.getString(props.get(AwsConstantKey.HOST_NAME.toLowerCase()))); - tableInfo.setBucketAcl(MathUtil.getString(props.get(AwsConstantKey.BUCKET_ACL.toLowerCase()))); - tableInfo.setBucketName(MathUtil.getString(props.get(AwsConstantKey.BUCKET_KEY.toLowerCase()))); - tableInfo.setObjectName(MathUtil.getString(props.get(AwsConstantKey.OBJECT_NAME.toLowerCase()))); - - tableInfo.check(); - - return tableInfo; - } -} diff --git a/aws/aws-sink/src/main/java/com/dtstack/flink/sql/sink/aws/table/AwsTableInfo.java b/aws/aws-sink/src/main/java/com/dtstack/flink/sql/sink/aws/table/AwsTableInfo.java deleted file mode 100644 index f02826679..000000000 --- a/aws/aws-sink/src/main/java/com/dtstack/flink/sql/sink/aws/table/AwsTableInfo.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.aws.table; - -import com.dtstack.flink.sql.table.AbstractTargetTableInfo; -import com.google.common.base.Preconditions; - -/** - * @author tiezhu - * date 2020/12/1 - * company dtstack - */ -public class AwsTableInfo extends AbstractTargetTableInfo { - - private static final String CURRENT_TYPE = "aws"; - - private String accessKey; - - private String secretKey; - - private String hostname; - - private String bucketName; - - /** - * 写入s3的objectName - */ - private String objectName; - - /** - * 文件存储的类型,分为Standard【标准存储】和 Standard-ia【低频存储】 - */ - private String storageType; - - /** - * 设置bucket的访问权限,有基本的两种,CannedAccessControlList和AccessControlList - */ - private String bucketAcl; - - private String userId; - - private String userDisplayName; - - private String ownerId; - - private String ownerDisplayName; - - public String getAccessKey() { - return accessKey; - } - - public void setAccessKey(String accessKey) { - this.accessKey = accessKey; - } - - public String getSecretKey() { - return secretKey; - } - - public void setSecretKey(String secretKey) { - this.secretKey = secretKey; - } - - public String getHostname() { - return hostname; - } - - public void setHostname(String hostname) { - this.hostname = hostname; - } - - public String getBucketName() { - return bucketName; - } - - public void setBucketName(String bucketName) { - this.bucketName = bucketName; - } - - public String getStorageType() { - return storageType; - } - - public void setStorageType(String storageType) { - this.storageType = storageType; - } - - public String getBucketAcl() { - return bucketAcl; - } - - public void setBucketAcl(String bucketAcl) { - this.bucketAcl = bucketAcl; - } - - public String getUserId() { - return userId; - } - - public void setUserId(String userId) { - this.userId = userId; - } - - public String getUserDisplayName() { - return userDisplayName; - } - - public void setUserDisplayName(String userDisplayName) { - this.userDisplayName = userDisplayName; - } - - public String getOwnerId() { - return ownerId; - } - - public void setOwnerId(String ownerId) { - this.ownerId = ownerId; - } - - public String getOwnerDisplayName() { - return ownerDisplayName; - } - - public void setOwnerDisplayName(String ownerDisplayName) { - this.ownerDisplayName = ownerDisplayName; - } - - public String getObjectName() { - return objectName; - } - - public void setObjectName(String objectName) { - this.objectName = objectName; - } - - @Override - public boolean check() { - Preconditions.checkNotNull(accessKey, "S3 field of AccessKey is required!"); - Preconditions.checkNotNull(secretKey, "S3 field of SecretKey is required!"); - Preconditions.checkNotNull(bucketName, "S3 field of BucketName is required!"); - Preconditions.checkNotNull(objectName, "S3 field of ObjectName is required!"); - - return true; - } - - @Override - public String getType() { - return CURRENT_TYPE; - } -} diff --git a/aws/aws-sink/src/main/java/com/dtstack/flink/sql/sink/aws/util/AwsManager.java b/aws/aws-sink/src/main/java/com/dtstack/flink/sql/sink/aws/util/AwsManager.java deleted file mode 100644 index 9cf1b3ccd..000000000 --- a/aws/aws-sink/src/main/java/com/dtstack/flink/sql/sink/aws/util/AwsManager.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.aws.util; - -import com.amazonaws.ClientConfiguration; -import com.amazonaws.auth.AWSCredentials; -import com.amazonaws.auth.BasicAWSCredentials; -import com.amazonaws.services.s3.AmazonS3Client; -import com.amazonaws.services.s3.model.AccessControlList; -import com.amazonaws.services.s3.model.CannedAccessControlList; -import com.amazonaws.services.s3.model.CanonicalGrantee; -import com.amazonaws.services.s3.model.CreateBucketRequest; -import com.amazonaws.services.s3.model.ObjectMetadata; -import com.amazonaws.services.s3.model.Owner; -import com.amazonaws.services.s3.model.Permission; -import com.amazonaws.services.s3.model.S3Object; -import com.amazonaws.services.s3.model.SetBucketAclRequest; -import com.amazonaws.services.s3.model.StorageClass; -import com.dtstack.flink.sql.sink.aws.AwsConstantKey; -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Objects; - -/** - * @author tiezhu - * date 2020/12/1 - * company dtstack - *

- * 一些针对s3的操作api - */ -public class AwsManager { - private static final Logger LOG = LoggerFactory.getLogger(AwsManager.class); - - /** - * 创建s3 client - * - * @param accessKey accessKey - * @param secretKey secretKey - * @param hostname hostname - * @return 客户端 - */ - public static AmazonS3Client initClient(String accessKey, - String secretKey, - String hostname) { - ClientConfiguration configuration = new ClientConfiguration(); - // TODO 这个参数要对外开发出去 - configuration.setSignerOverride("S3SignerType"); - AWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey); - AmazonS3Client client = new AmazonS3Client(credentials, configuration); - client.setEndpoint(hostname); - return client; - } - - /** - * 创建bucket - * - * @param bucketName bucketName,不能为空 - * @param client 客户端,必须可用 - * @param readWrite 读写权限,默认私有 - * @param storageClass 存储类型,有STANDARD 【标准存储】 和 STANDARD_IA 【低频存储】 默认标准存储 - */ - public static void createBucket(String bucketName, - AmazonS3Client client, - String readWrite, - String storageClass) { - if (StringUtils.isBlank(readWrite)) { - client.createBucket(bucketName); - return; - } - - CreateBucketRequest request = new CreateBucketRequest(bucketName); - - // TODO 完善多个类型 - if (readWrite.equalsIgnoreCase(AwsConstantKey.PUBLIC_READ_WRITE)) { - request.setCannedAcl(CannedAccessControlList.PublicReadWrite); - } - - // TODO 完善多个存储类型 - if (storageClass.equalsIgnoreCase(AwsConstantKey.STANDARD)) { - request.setStorageClass(StorageClass.Standard); - } - } - - /** - * 给bucket设置访问权限CannedAccess - * - * @param client 客户端 - * @param bucketName bucketName - * @param aclName 权限名,权限名分为CannedAccessControlList 与AccessControlList 两种格式。 - */ - public static void setBucketCannedAccessControl(AmazonS3Client client, - String bucketName, - String aclName) { - client.setBucketAcl(bucketName, CannedAccessControlList.valueOf(aclName)); - } - - /** - * 给bucket 设置访问权限AccessControl - * - * @param client 客户端 - * @param bucketName bucketName - * @param aclName 权限名 - */ - public static void setBucketAccessControl(AmazonS3Client client, - String bucketName, - String aclName) { - AccessControlList list = new AccessControlList(); - // set owner - Owner owner = new Owner("owner-id", "owner-displayName"); - list.setOwner(owner); - - // set owner id - CanonicalGrantee grantee = new CanonicalGrantee("owner-id"); - - // set owner display name - grantee.setDisplayName("user-displayName"); - // set access of acl - //TODO 完善Permission选择 - list.grantPermission(grantee, Permission.parsePermission(aclName)); - SetBucketAclRequest request = new SetBucketAclRequest(bucketName, list); - client.setBucketAcl(request); - } - - /** - * 获取当前 Object 字节位数,如果 Object 不存在,那么返回 0 - * - * @param bucket bucket - * @param objectName object name - * @param client client - * @return object bytes 位数 - */ - public static long getObjectPosition(String bucket, String objectName, AmazonS3Client client) { - if (!client.doesObjectExist(bucket, objectName)) { - return 0; - } - - S3Object object = client.getObject(bucket, objectName); - ObjectMetadata objectMetadata = object.getObjectMetadata(); - return objectMetadata.getContentLength(); - } -} diff --git a/aws/pom.xml b/aws/pom.xml deleted file mode 100644 index 7525d712c..000000000 --- a/aws/pom.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - flink.sql - com.dtstack.flink - 1.0-SNAPSHOT - ../pom.xml - - 4.0.0 - - sql.aws - pom - - aws-sink - - - - 1.0-SNAPSHOT - - - - - com.dtstack.flink - sql.core - ${sql.core.version} - provided - - - - \ No newline at end of file diff --git a/cassandra/cassandra-side/cassandra-all-side/pom.xml b/cassandra/cassandra-side/cassandra-all-side/pom.xml index 5715ab605..461e70beb 100644 --- a/cassandra/cassandra-side/cassandra-all-side/pom.xml +++ b/cassandra/cassandra-side/cassandra-all-side/pom.xml @@ -36,10 +36,9 @@ shade - false - org.slf4j + @@ -70,14 +69,14 @@ - + - + diff --git a/cassandra/cassandra-side/cassandra-all-side/src/main/java/com/dtstack/flink/sql/side/cassandra/CassandraAllReqRow.java b/cassandra/cassandra-side/cassandra-all-side/src/main/java/com/dtstack/flink/sql/side/cassandra/CassandraAllReqRow.java index 28830135a..eecb1350e 100644 --- a/cassandra/cassandra-side/cassandra-all-side/src/main/java/com/dtstack/flink/sql/side/cassandra/CassandraAllReqRow.java +++ b/cassandra/cassandra-side/cassandra-all-side/src/main/java/com/dtstack/flink/sql/side/cassandra/CassandraAllReqRow.java @@ -28,26 +28,25 @@ import com.datastax.driver.core.SocketOptions; import com.datastax.driver.core.policies.DowngradingConsistencyRetryPolicy; import com.datastax.driver.core.policies.RetryPolicy; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.BaseAllReqRow; +import com.dtstack.flink.sql.side.AllReqRow; import com.dtstack.flink.sql.side.FieldInfo; import com.dtstack.flink.sql.side.JoinInfo; +import com.dtstack.flink.sql.side.SideTableInfo; import com.dtstack.flink.sql.side.cassandra.table.CassandraSideTableInfo; -import com.dtstack.flink.sql.util.RowDataComplete; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; import org.apache.calcite.sql.JoinType; import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.lang3.StringUtils; import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.table.dataformat.BaseRow; -import org.apache.flink.table.dataformat.GenericRow; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import org.apache.flink.table.typeutils.TimeIndicatorTypeInfo; +import org.apache.flink.types.Row; import org.apache.flink.util.Collector; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.net.InetAddress; import java.sql.SQLException; +import java.sql.Timestamp; import java.util.ArrayList; import java.util.Calendar; import java.util.List; @@ -60,12 +59,14 @@ * * @author xuqianjin */ -public class CassandraAllReqRow extends BaseAllReqRow { +public class CassandraAllReqRow extends AllReqRow { private static final long serialVersionUID = 54015343561288219L; private static final Logger LOG = LoggerFactory.getLogger(CassandraAllReqRow.class); + private static final String cassandra_DRIVER = "com.cassandra.jdbc.Driver"; + private static final int CONN_RETRY_NUM = 3; private static final int FETCH_SIZE = 1000; @@ -75,10 +76,36 @@ public class CassandraAllReqRow extends BaseAllReqRow { private AtomicReference>>> cacheRef = new AtomicReference<>(); - public CassandraAllReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { + public CassandraAllReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, SideTableInfo sideTableInfo) { super(new com.dtstack.flink.sql.side.cassandra.CassandraAllSideInfo(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo)); } + @Override + public Row fillData(Row input, Object sideInput) { + Map cacheInfo = (Map) sideInput; + Row row = new Row(sideInfo.getOutFieldInfoList().size()); + for (Map.Entry entry : sideInfo.getInFieldIndex().entrySet()) { + Object obj = input.getField(entry.getValue()); + boolean isTimeIndicatorTypeInfo = TimeIndicatorTypeInfo.class.isAssignableFrom(sideInfo.getRowTypeInfo().getTypeAt(entry.getValue()).getClass()); + + //Type information for indicating event or processing time. However, it behaves like a regular SQL timestamp but is serialized as Long. + if (obj instanceof Timestamp && isTimeIndicatorTypeInfo) { + obj = ((Timestamp) obj).getTime(); + } + row.setField(entry.getKey(), obj); + } + + for (Map.Entry entry : sideInfo.getSideFieldNameIndex().entrySet()) { + if (cacheInfo == null) { + row.setField(entry.getKey(), null); + } else { + row.setField(entry.getKey(), cacheInfo.get(entry.getValue())); + } + } + + return row; + } + @Override protected void initCache() throws SQLException { Map>> newCache = Maps.newConcurrentMap(); @@ -102,17 +129,12 @@ protected void reloadCache() { @Override - public void flatMap(BaseRow input, Collector out) throws Exception { - GenericRow genericRow = (GenericRow) input; + public void flatMap(Row value, Collector out) throws Exception { List inputParams = Lists.newArrayList(); for (Integer conValIndex : sideInfo.getEqualValIndex()) { - Object equalObj = genericRow.getField(conValIndex); + Object equalObj = value.getField(conValIndex); if (equalObj == null) { - if (sideInfo.getJoinType() == JoinType.LEFT) { - BaseRow row = fillData(input, null); - RowDataComplete.collectBaseRow(out, row); - } - return; + out.collect(null); } inputParams.add(equalObj); @@ -122,8 +144,8 @@ public void flatMap(BaseRow input, Collector out) throws Exception { List> cacheList = cacheRef.get().get(key); if (CollectionUtils.isEmpty(cacheList)) { if (sideInfo.getJoinType() == JoinType.LEFT) { - BaseRow row = fillData(input, null); - RowDataComplete.collectBaseRow(out, row); + Row row = fillData(value, null); + out.collect(row); } else { return; } @@ -132,8 +154,7 @@ public void flatMap(BaseRow input, Collector out) throws Exception { } for (Map one : cacheList) { - BaseRow row = fillData(input, one); - RowDataComplete.collectBaseRow(out, row); + out.collect(fillData(value, one)); } } @@ -196,9 +217,9 @@ private Session getConn(CassandraSideTableInfo tableInfo) { //重试策略 RetryPolicy retryPolicy = DowngradingConsistencyRetryPolicy.INSTANCE; - for (String server : StringUtils.split(address, ",")) { - cassandraPort = Integer.parseInt(StringUtils.split(server, ":")[1]); - serversList.add(InetAddress.getByName(StringUtils.split(server, ":")[0])); + for (String server : address.split(",")) { + cassandraPort = Integer.parseInt(server.split(":")[1]); + serversList.add(InetAddress.getByName(server.split(":")[0])); } if (userName == null || userName.isEmpty() || password == null || password.isEmpty()) { @@ -241,9 +262,9 @@ private void loadData(Map>> tmpCache) throws SQ String connInfo = "address:" + tableInfo.getAddress() + ";userName:" + tableInfo.getUserName() + ",pwd:" + tableInfo.getPassword(); LOG.warn("get conn fail, wait for 5 sec and try again, connInfo:" + connInfo); - Thread.sleep(LOAD_DATA_ERROR_SLEEP_TIME); + Thread.sleep(5 * 1000); } catch (InterruptedException e1) { - LOG.error("", e1); + e1.printStackTrace(); } } @@ -252,7 +273,7 @@ private void loadData(Map>> tmpCache) throws SQ //load data from table String sql = sideInfo.getSqlCondition() + " limit " + FETCH_SIZE; ResultSet resultSet = session.execute(sql); - String[] sideFieldNames = StringUtils.split(sideInfo.getSideSelectFields(), ","); + String[] sideFieldNames = sideInfo.getSideSelectFields().split(","); for (com.datastax.driver.core.Row row : resultSet) { Map oneRow = Maps.newHashMap(); for (String fieldName : sideFieldNames) { diff --git a/cassandra/cassandra-side/cassandra-all-side/src/main/java/com/dtstack/flink/sql/side/cassandra/CassandraAllSideInfo.java b/cassandra/cassandra-side/cassandra-all-side/src/main/java/com/dtstack/flink/sql/side/cassandra/CassandraAllSideInfo.java index 5d95dc9bf..fa665f9a0 100644 --- a/cassandra/cassandra-side/cassandra-all-side/src/main/java/com/dtstack/flink/sql/side/cassandra/CassandraAllSideInfo.java +++ b/cassandra/cassandra-side/cassandra-all-side/src/main/java/com/dtstack/flink/sql/side/cassandra/CassandraAllSideInfo.java @@ -20,8 +20,8 @@ import com.dtstack.flink.sql.side.FieldInfo; import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.BaseSideInfo; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; +import com.dtstack.flink.sql.side.SideInfo; +import com.dtstack.flink.sql.side.SideTableInfo; import com.dtstack.flink.sql.side.cassandra.table.CassandraSideTableInfo; import com.dtstack.flink.sql.util.ParseUtils; import org.apache.calcite.sql.SqlNode; @@ -37,16 +37,16 @@ * * @author xuqianjin */ -public class CassandraAllSideInfo extends BaseSideInfo { +public class CassandraAllSideInfo extends SideInfo { private static final long serialVersionUID = -8690814317653033557L; - public CassandraAllSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { + public CassandraAllSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, SideTableInfo sideTableInfo) { super(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); } @Override - public void buildEqualInfo(JoinInfo joinInfo, AbstractSideTableInfo sideTableInfo) { + public void buildEqualInfo(JoinInfo joinInfo, SideTableInfo sideTableInfo) { CassandraSideTableInfo cassandraSideTableInfo = (CassandraSideTableInfo) sideTableInfo; sqlCondition = "select ${selectField} from ${tableName} "; diff --git a/cassandra/cassandra-side/cassandra-all-side/src/test/java/com/dtstack/flink/sql/side/cassandra/CassandraAllReqRowTest.java b/cassandra/cassandra-side/cassandra-all-side/src/test/java/com/dtstack/flink/sql/side/cassandra/CassandraAllReqRowTest.java deleted file mode 100644 index 352946767..000000000 --- a/cassandra/cassandra-side/cassandra-all-side/src/test/java/com/dtstack/flink/sql/side/cassandra/CassandraAllReqRowTest.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.cassandra; - -import com.dtstack.flink.sql.side.BaseAllReqRow; -import com.dtstack.flink.sql.side.BaseSideInfo; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.cassandra.table.CassandraSideTableInfo; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import org.apache.calcite.sql.JoinType; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.table.dataformat.BaseRow; -import org.apache.flink.table.dataformat.GenericRow; -import org.apache.flink.types.Row; -import org.apache.flink.util.Collector; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PowerMockIgnore; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import org.powermock.reflect.Whitebox; - -import java.sql.SQLException; -import java.sql.Timestamp; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicReference; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.powermock.api.support.membermodification.MemberMatcher.constructor; -import static org.powermock.api.support.membermodification.MemberModifier.suppress; - -/** - * @author: chuixue - * @create: 2020-07-28 10:58 - * @description: - **/ -@RunWith(PowerMockRunner.class) -@PrepareForTest({CassandraAllReqRow.class, - BaseAllReqRow.class, - CassandraAllSideInfo.class})//要跳过的写在后面 -@PowerMockIgnore({"javax.*"}) -public class CassandraAllReqRowTest { - - private CassandraAllReqRow cassandraAllReqRow; - private RowTypeInfo rowTypeInfo = new RowTypeInfo(new TypeInformation[]{TypeInformation.of(Integer.class), TypeInformation.of(String.class), TypeInformation.of(Integer.class)}, new String[]{"id", "bb", "PROCTIME"}); - private JoinInfo joinInfo; - private List outFieldInfoList = new ArrayList<>(); - private CassandraSideTableInfo sideTableInfo; - private BaseSideInfo sideInfo; - private AtomicReference>>> cacheRef = new AtomicReference<>(); - - @Before - public void setUp() { - joinInfo = mock(JoinInfo.class); - sideTableInfo = mock(CassandraSideTableInfo.class); - sideInfo = PowerMockito.mock(CassandraAllSideInfo.class); - - Map>> map = Maps.newHashMap(); - cacheRef.set(map); - - suppress(constructor(CassandraAllSideInfo.class)); - suppress(constructor(BaseAllReqRow.class)); - cassandraAllReqRow = new CassandraAllReqRow(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); - Whitebox.setInternalState(cassandraAllReqRow, "sideInfo", sideInfo); - Whitebox.setInternalState(cassandraAllReqRow, "cacheRef", cacheRef); - } - - @Test - public void testReloadCache() throws SQLException { - when(sideInfo.getSideTableInfo()).thenReturn(sideTableInfo); - when(sideTableInfo.getMaxRequestsPerConnection()).thenReturn(1); - when(sideTableInfo.getCoreConnectionsPerHost()).thenReturn(1); - when(sideTableInfo.getMaxConnectionsPerHost()).thenReturn(1); - when(sideTableInfo.getMaxQueueSize()).thenReturn(1); - when(sideTableInfo.getReadTimeoutMillis()).thenReturn(1); - when(sideTableInfo.getConnectTimeoutMillis()).thenReturn(1); - when(sideTableInfo.getPoolTimeoutMillis()).thenReturn(1); - when(sideTableInfo.getAddress()).thenReturn("12.12.12.12:9042,10.10.10.10:9042"); - when(sideTableInfo.getUserName()).thenReturn("userName"); - when(sideTableInfo.getPassword()).thenReturn("password"); - when(sideTableInfo.getDatabase()).thenReturn("getDatabase"); - - cassandraAllReqRow.initCache(); - cassandraAllReqRow.reloadCache(); - } - - @Test - public void testFlatmap() throws Exception { - GenericRow row = new GenericRow(3); - row.setField(0, 1); - row.setField(1, "bbbbbb"); - row.setField(2, "2020-07-14 01:27:43.969"); - Collector out = mock(Collector.class); - - List equalFieldList = Lists.newArrayList(); - equalFieldList.add("rowkey"); - List equalValIndex = Lists.newArrayList(); - equalValIndex.add(0); - - List outFieldInfoList = Lists.newArrayList(); - FieldInfo fieldInfo = new FieldInfo(); - fieldInfo.setTable("m"); - fieldInfo.setFieldName("id"); - fieldInfo.setTypeInformation(TypeInformation.of(Integer.class)); - outFieldInfoList.add(fieldInfo); - outFieldInfoList.add(fieldInfo); - outFieldInfoList.add(fieldInfo); - outFieldInfoList.add(fieldInfo); - - Map inFieldIndex = Maps.newHashMap(); - inFieldIndex.put(0, 0); - inFieldIndex.put(1, 1); - - - Map sideFieldIndex = Maps.newHashMap(); - sideFieldIndex.put(2, 0); - sideFieldIndex.put(3, 1); - - Map sideFieldNameIndex = Maps.newHashMap(); - sideFieldNameIndex.put(2, "rowkey"); - sideFieldNameIndex.put(3, "channel"); - - RowTypeInfo rowTypeInfo = new RowTypeInfo(new TypeInformation[]{TypeInformation.of(Integer.class), TypeInformation.of(String.class), TypeInformation.of(Timestamp.class)}, new String[]{"id", "bb", "PROCTIME"}); - - when(sideInfo.getEqualValIndex()).thenReturn(equalValIndex); - when(sideInfo.getJoinType()).thenReturn(JoinType.LEFT); - when(sideInfo.getOutFieldInfoList()).thenReturn(outFieldInfoList); - when(sideInfo.getInFieldIndex()).thenReturn(inFieldIndex); - when(sideInfo.getRowTypeInfo()).thenReturn(rowTypeInfo); - when(sideInfo.getSideFieldNameIndex()).thenReturn(sideFieldNameIndex); - - cassandraAllReqRow.flatMap(row, out); - } - -} diff --git a/cassandra/cassandra-side/cassandra-all-side/src/test/java/com/dtstack/flink/sql/side/cassandra/CassandraAllSideInfoTest.java b/cassandra/cassandra-side/cassandra-all-side/src/test/java/com/dtstack/flink/sql/side/cassandra/CassandraAllSideInfoTest.java deleted file mode 100644 index 21d08da59..000000000 --- a/cassandra/cassandra-side/cassandra-all-side/src/test/java/com/dtstack/flink/sql/side/cassandra/CassandraAllSideInfoTest.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.cassandra; - -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.BaseSideInfo; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.cassandra.table.CassandraSideTableInfo; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import org.apache.calcite.sql.SqlBasicCall; -import org.apache.calcite.sql.SqlNode; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import org.powermock.reflect.Whitebox; - -import java.util.List; -import java.util.Map; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.powermock.api.support.membermodification.MemberMatcher.constructor; -import static org.powermock.api.support.membermodification.MemberModifier.suppress; - -/** - * @author: chuixue - * @create: 2020-07-28 11:00 - * @description: - **/ -@RunWith(PowerMockRunner.class) -@PrepareForTest({CassandraAllSideInfo.class, - BaseSideInfo.class})//要跳过的写在后面 -public class CassandraAllSideInfoTest { - private CassandraAllSideInfo cassandraAllSideInfo; - private JoinInfo joinInfo; - private AbstractSideTableInfo sideTableInfo; - - @Before - public void setUp() { - joinInfo = mock(JoinInfo.class); - sideTableInfo = mock(AbstractSideTableInfo.class); - - List outFieldInfoList = Lists.newArrayList(); - FieldInfo fieldInfo = new FieldInfo(); - fieldInfo.setTable("m"); - fieldInfo.setFieldName("_id"); - fieldInfo.setTypeInformation(TypeInformation.of(String.class)); - outFieldInfoList.add(fieldInfo); - - FieldInfo fieldInfo2 = new FieldInfo(); - fieldInfo2.setTable("s"); - fieldInfo2.setFieldName("name"); - fieldInfo2.setTypeInformation(TypeInformation.of(String.class)); - outFieldInfoList.add(fieldInfo2); - - Map sideFieldIndex = Maps.newHashMap(); - Map sideFieldNameIndex = Maps.newHashMap(); - RowTypeInfo rowTypeInfo = new RowTypeInfo(new TypeInformation[]{TypeInformation.of(Integer.class), TypeInformation.of(String.class), TypeInformation.of(Integer.class)}, new String[]{"id", "bb", "PROCTIME"}); - Map inFieldIndex = Maps.newHashMap(); - List equalFieldList = Lists.newArrayList(); - equalFieldList.add("_id"); - - suppress(constructor(BaseSideInfo.class)); - cassandraAllSideInfo = new CassandraAllSideInfo(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); - Whitebox.setInternalState(cassandraAllSideInfo, "outFieldInfoList", outFieldInfoList); - Whitebox.setInternalState(cassandraAllSideInfo, "sideFieldIndex", sideFieldIndex); - Whitebox.setInternalState(cassandraAllSideInfo, "sideFieldNameIndex", sideFieldNameIndex); - Whitebox.setInternalState(cassandraAllSideInfo, "rowTypeInfo", rowTypeInfo); - Whitebox.setInternalState(cassandraAllSideInfo, "inFieldIndex", inFieldIndex); - Whitebox.setInternalState(cassandraAllSideInfo, "equalFieldList", equalFieldList); - } - - @Test - public void testBuildEqualInfo() { - CassandraSideTableInfo sideTableInfo = mock(CassandraSideTableInfo.class); - when(sideTableInfo.getDatabase()).thenReturn("dd"); - when(sideTableInfo.getTableName()).thenReturn("d"); - Whitebox.setInternalState(cassandraAllSideInfo, "sideSelectFields", "cassandraAllSideInfo"); - cassandraAllSideInfo.buildEqualInfo(joinInfo, sideTableInfo); - } - - @Test - public void testParseSelectFields() throws NoSuchMethodException { - SqlBasicCall conditionNode = mock(SqlBasicCall.class); - when(joinInfo.getSideTableName()).thenReturn("s"); - when(joinInfo.getNonSideTable()).thenReturn("m"); - when(joinInfo.getCondition()).thenReturn(conditionNode); - suppress(BaseSideInfo.class.getMethod("dealOneEqualCon", SqlNode.class, String.class)); - - cassandraAllSideInfo.parseSelectFields(joinInfo); - } -} diff --git a/cassandra/cassandra-side/cassandra-async-side/pom.xml b/cassandra/cassandra-side/cassandra-async-side/pom.xml index df8204cb1..ee24ae31a 100644 --- a/cassandra/cassandra-side/cassandra-async-side/pom.xml +++ b/cassandra/cassandra-side/cassandra-async-side/pom.xml @@ -52,10 +52,9 @@ shade - false - org.slf4j + @@ -86,14 +85,14 @@ - + - + diff --git a/cassandra/cassandra-side/cassandra-async-side/src/main/java/com/dtstack/flink/sql/side/cassandra/CassandraAsyncReqRow.java b/cassandra/cassandra-side/cassandra-async-side/src/main/java/com/dtstack/flink/sql/side/cassandra/CassandraAsyncReqRow.java index 22e961a2f..c2528d67b 100644 --- a/cassandra/cassandra-side/cassandra-async-side/src/main/java/com/dtstack/flink/sql/side/cassandra/CassandraAsyncReqRow.java +++ b/cassandra/cassandra-side/cassandra-async-side/src/main/java/com/dtstack/flink/sql/side/cassandra/CassandraAsyncReqRow.java @@ -30,30 +30,30 @@ import com.datastax.driver.core.policies.DowngradingConsistencyRetryPolicy; import com.datastax.driver.core.policies.RetryPolicy; import com.dtstack.flink.sql.enums.ECacheContentType; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.BaseAsyncReqRow; +import com.dtstack.flink.sql.side.AsyncReqRow; import com.dtstack.flink.sql.side.CacheMissVal; import com.dtstack.flink.sql.side.FieldInfo; import com.dtstack.flink.sql.side.JoinInfo; +import com.dtstack.flink.sql.side.SideTableInfo; import com.dtstack.flink.sql.side.cache.CacheObj; import com.dtstack.flink.sql.side.cassandra.table.CassandraSideTableInfo; -import com.dtstack.flink.sql.util.RowDataComplete; import com.google.common.base.Function; -import com.google.common.collect.Lists; import com.google.common.util.concurrent.AsyncFunction; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; -import org.apache.commons.lang3.StringUtils; +import io.vertx.core.json.JsonArray; import org.apache.flink.api.java.typeutils.RowTypeInfo; import org.apache.flink.configuration.Configuration; +import com.google.common.collect.Lists; import org.apache.flink.streaming.api.functions.async.ResultFuture; -import org.apache.flink.table.dataformat.BaseRow; -import org.apache.flink.table.dataformat.GenericRow; +import org.apache.flink.table.typeutils.TimeIndicatorTypeInfo; +import org.apache.flink.types.Row; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.net.InetAddress; +import java.sql.Timestamp; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -65,7 +65,7 @@ * * @author xuqianjin */ -public class CassandraAsyncReqRow extends BaseAsyncReqRow { +public class CassandraAsyncReqRow extends AsyncReqRow { private static final long serialVersionUID = 6631584128079864735L; @@ -81,7 +81,7 @@ public class CassandraAsyncReqRow extends BaseAsyncReqRow { private transient ListenableFuture session; private transient CassandraSideTableInfo cassandraSideTableInfo; - public CassandraAsyncReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { + public CassandraAsyncReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, SideTableInfo sideTableInfo) { super(new com.dtstack.flink.sql.side.cassandra.CassandraAsyncSideInfo(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo)); } @@ -133,9 +133,9 @@ private void connCassandraDB(CassandraSideTableInfo tableInfo) { //重试策略 RetryPolicy retryPolicy = DowngradingConsistencyRetryPolicy.INSTANCE; - for (String server : StringUtils.split(address, ",")) { - cassandraPort = Integer.parseInt(StringUtils.split(server, ":")[1]); - serversList.add(InetAddress.getByName(StringUtils.split(server, ":")[0])); + for (String server : address.split(",")) { + cassandraPort = Integer.parseInt(server.split(":")[1]); + serversList.add(InetAddress.getByName(server.split(":")[0])); } if (userName == null || userName.isEmpty() || password == null || password.isEmpty()) { @@ -160,14 +160,53 @@ private void connCassandraDB(CassandraSideTableInfo tableInfo) { } @Override - public void handleAsyncInvoke(Map inputParams, BaseRow input, ResultFuture resultFuture) throws Exception { + public void asyncInvoke(Row input, ResultFuture resultFuture) throws Exception { + + JsonArray inputParams = new JsonArray(); + StringBuffer stringBuffer = new StringBuffer(); + String sqlWhere = " where "; + + for (int i = 0; i < sideInfo.getEqualFieldList().size(); i++) { + Integer conValIndex = sideInfo.getEqualValIndex().get(i); + Object equalObj = input.getField(conValIndex); + if (equalObj == null) { + resultFuture.complete(null); + } + inputParams.add(equalObj); + stringBuffer.append(sideInfo.getEqualFieldList().get(i)) + .append(" = ").append("'" + equalObj + "'") + .append(" and "); + } String key = buildCacheKey(inputParams); + sqlWhere = sqlWhere + stringBuffer.toString().substring(0, stringBuffer.lastIndexOf(" and ")); + + if (openCache()) { + CacheObj val = getFromCache(key); + if (val != null) { + + if (ECacheContentType.MissVal == val.getType()) { + dealMissKey(input, resultFuture); + return; + } else if (ECacheContentType.MultiLine == val.getType()) { + + for (Object rowArray : (List) val.getContent()) { + Row row = fillData(input, rowArray); + resultFuture.complete(Collections.singleton(row)); + } + + } else { + throw new RuntimeException("not support cache obj type " + val.getType()); + } + return; + } + } + //connect Cassandra connCassandraDB(cassandraSideTableInfo); - String sqlCondition = sideInfo.getSqlCondition() + " " + buildWhereCondition(inputParams) + " ALLOW FILTERING "; - LOG.info("sqlCondition:{}" + sqlCondition); + String sqlCondition = sideInfo.getSqlCondition() + " " + sqlWhere; + System.out.println("sqlCondition:" + sqlCondition); ListenableFuture resultSet = Futures.transformAsync(session, new AsyncFunction() { @@ -191,15 +230,14 @@ public void onSuccess(List rows) { cluster.closeAsync(); if (rows.size() > 0) { List cacheContent = Lists.newArrayList(); - List rowList = Lists.newArrayList(); for (com.datastax.driver.core.Row line : rows) { - BaseRow row = fillData(input, line); + Row row = fillData(input, line); if (openCache()) { cacheContent.add(line); } - rowList.add(row); + resultFuture.complete(Collections.singleton(row)); } - RowDataComplete.completeBaseRow(resultFuture, rowList); + if (openCache()) { putCache(key, CacheObj.buildCacheObj(ECacheContentType.MultiLine, cacheContent)); } @@ -208,7 +246,7 @@ public void onSuccess(List rows) { if (openCache()) { putCache(key, CacheMissVal.getMissKeyObj()); } - resultFuture.complete(Collections.EMPTY_LIST); + resultFuture.complete(null); } } @@ -216,6 +254,7 @@ public void onSuccess(List rows) { public void onFailure(Throwable t) { LOG.error("Failed to retrieve the data: %s%n", t.getMessage()); + System.out.println("Failed to retrieve the data: " + t.getMessage()); cluster.closeAsync(); resultFuture.completeExceptionally(t); } @@ -223,32 +262,17 @@ public void onFailure(Throwable t) { } @Override - public String buildCacheKey(Map inputParams) { - StringBuilder sb = new StringBuilder(); - for (Object ele : inputParams.values()) { - sb.append(ele.toString()).append("_"); - } - return sb.toString(); - } - - private String buildWhereCondition(Map inputParams){ - StringBuilder sb = new StringBuilder(" where "); - for(Map.Entry entry : inputParams.entrySet()){ - Object value = entry.getValue() instanceof String ? "'" + entry.getValue() + "'" : entry.getValue(); - sb.append(String.format("%s = %s", entry.getKey(), value)); - } - return sb.toString(); - } - - @Override - public BaseRow fillData(BaseRow input, Object line) { - GenericRow genericRow = (GenericRow) input; + public Row fillData(Row input, Object line) { com.datastax.driver.core.Row rowArray = (com.datastax.driver.core.Row) line; - GenericRow row = new GenericRow(sideInfo.getOutFieldInfoList().size()); - row.setHeader(genericRow.getHeader()); + Row row = new Row(sideInfo.getOutFieldInfoList().size()); for (Map.Entry entry : sideInfo.getInFieldIndex().entrySet()) { - Object obj = genericRow.getField(entry.getValue()); - obj = convertTimeIndictorTypeInfo(entry.getValue(), obj); + Object obj = input.getField(entry.getValue()); + boolean isTimeIndicatorTypeInfo = TimeIndicatorTypeInfo.class.isAssignableFrom(sideInfo.getRowTypeInfo().getTypeAt(entry.getValue()).getClass()); + + if (obj instanceof Timestamp && isTimeIndicatorTypeInfo) { + obj = ((Timestamp) obj).getTime(); + } + row.setField(entry.getKey(), obj); } @@ -260,6 +284,7 @@ public BaseRow fillData(BaseRow input, Object line) { } } + System.out.println("row:" + row.toString()); return row; } @@ -271,4 +296,14 @@ public void close() throws Exception { cluster = null; } } + + public String buildCacheKey(JsonArray jsonArray) { + StringBuilder sb = new StringBuilder(); + for (Object ele : jsonArray.getList()) { + sb.append(ele.toString()) + .append("_"); + } + + return sb.toString(); + } } diff --git a/cassandra/cassandra-side/cassandra-async-side/src/main/java/com/dtstack/flink/sql/side/cassandra/CassandraAsyncSideInfo.java b/cassandra/cassandra-side/cassandra-async-side/src/main/java/com/dtstack/flink/sql/side/cassandra/CassandraAsyncSideInfo.java index 4c341d131..3557f0f73 100644 --- a/cassandra/cassandra-side/cassandra-async-side/src/main/java/com/dtstack/flink/sql/side/cassandra/CassandraAsyncSideInfo.java +++ b/cassandra/cassandra-side/cassandra-async-side/src/main/java/com/dtstack/flink/sql/side/cassandra/CassandraAsyncSideInfo.java @@ -20,8 +20,8 @@ import com.dtstack.flink.sql.side.FieldInfo; import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.BaseSideInfo; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; +import com.dtstack.flink.sql.side.SideInfo; +import com.dtstack.flink.sql.side.SideTableInfo; import com.dtstack.flink.sql.side.cassandra.table.CassandraSideTableInfo; import com.dtstack.flink.sql.util.ParseUtils; import org.apache.calcite.sql.SqlBasicCall; @@ -30,8 +30,6 @@ import org.apache.calcite.sql.SqlNode; import org.apache.flink.api.java.typeutils.RowTypeInfo; import com.google.common.collect.Lists; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.util.List; @@ -41,18 +39,16 @@ * * @author xuqianjin */ -public class CassandraAsyncSideInfo extends BaseSideInfo { +public class CassandraAsyncSideInfo extends SideInfo { private static final long serialVersionUID = -4403313049809013362L; - private static final Logger LOG = LoggerFactory.getLogger(CassandraAsyncSideInfo.class.getSimpleName()); - - public CassandraAsyncSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { + public CassandraAsyncSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, SideTableInfo sideTableInfo) { super(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); } @Override - public void buildEqualInfo(JoinInfo joinInfo, AbstractSideTableInfo sideTableInfo) { + public void buildEqualInfo(JoinInfo joinInfo, SideTableInfo sideTableInfo) { CassandraSideTableInfo cassandraSideTableInfo = (CassandraSideTableInfo) sideTableInfo; String sideTableName = joinInfo.getSideTableName(); @@ -67,9 +63,62 @@ public void buildEqualInfo(JoinInfo joinInfo, AbstractSideTableInfo sideTableInf } sqlCondition = "select ${selectField} from ${tableName}"; + sqlCondition = sqlCondition.replace("${tableName}", cassandraSideTableInfo.getDatabase()+"."+cassandraSideTableInfo.getTableName()).replace("${selectField}", sideSelectFields); + System.out.println("---------side_exe_sql-----\n" + sqlCondition); + } + + + @Override + public void dealOneEqualCon(SqlNode sqlNode, String sideTableName) { + if (sqlNode.getKind() != SqlKind.EQUALS) { + throw new RuntimeException("not equal operator."); + } + + SqlIdentifier left = (SqlIdentifier) ((SqlBasicCall) sqlNode).getOperands()[0]; + SqlIdentifier right = (SqlIdentifier) ((SqlBasicCall) sqlNode).getOperands()[1]; + + String leftTableName = left.getComponent(0).getSimple(); + String leftField = left.getComponent(1).getSimple(); + + String rightTableName = right.getComponent(0).getSimple(); + String rightField = right.getComponent(1).getSimple(); + + if (leftTableName.equalsIgnoreCase(sideTableName)) { + equalFieldList.add(leftField); + int equalFieldIndex = -1; + for (int i = 0; i < rowTypeInfo.getFieldNames().length; i++) { + String fieldName = rowTypeInfo.getFieldNames()[i]; + if (fieldName.equalsIgnoreCase(rightField)) { + equalFieldIndex = i; + } + } + if (equalFieldIndex == -1) { + throw new RuntimeException("can't deal equal field: " + sqlNode); + } + + equalValIndex.add(equalFieldIndex); + + } else if (rightTableName.equalsIgnoreCase(sideTableName)) { + + equalFieldList.add(rightField); + int equalFieldIndex = -1; + for (int i = 0; i < rowTypeInfo.getFieldNames().length; i++) { + String fieldName = rowTypeInfo.getFieldNames()[i]; + if (fieldName.equalsIgnoreCase(leftField)) { + equalFieldIndex = i; + } + } + if (equalFieldIndex == -1) { + throw new RuntimeException("can't deal equal field: " + sqlNode.toString()); + } + + equalValIndex.add(equalFieldIndex); + + } else { + throw new RuntimeException("resolve equalFieldList error:" + sqlNode.toString()); + } - LOG.info("---------side_exe_sql-----\n{}" + sqlCondition); } } diff --git a/cassandra/cassandra-side/cassandra-async-side/src/test/java/com/dtstack/flink/sql/side/cassandra/CassandraAsyncReqRowTest.java b/cassandra/cassandra-side/cassandra-async-side/src/test/java/com/dtstack/flink/sql/side/cassandra/CassandraAsyncReqRowTest.java deleted file mode 100644 index cca339388..000000000 --- a/cassandra/cassandra-side/cassandra-async-side/src/test/java/com/dtstack/flink/sql/side/cassandra/CassandraAsyncReqRowTest.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.cassandra; - -import com.google.common.util.concurrent.ListenableFuture; -import com.datastax.driver.core.Cluster; -import com.dtstack.flink.sql.side.*; -import com.dtstack.flink.sql.side.cassandra.table.CassandraSideTableInfo; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.configuration.Configuration; -import org.apache.flink.streaming.api.functions.async.ResultFuture; -import org.apache.flink.table.dataformat.GenericRow; -import org.apache.flink.types.Row; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.core.classloader.annotations.PowerMockIgnore; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import org.powermock.reflect.Whitebox; - -import java.util.List; -import java.util.Map; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.powermock.api.support.membermodification.MemberMatcher.constructor; -import static org.powermock.api.support.membermodification.MemberModifier.suppress; - -/** - * @author: chuixue - * @create: 2020-07-28 12:39 - * @description: - **/ -@RunWith(PowerMockRunner.class) -@PrepareForTest({CassandraAsyncReqRow.class, - BaseSideInfo.class, - CassandraAsyncSideInfo.class, - BaseAsyncReqRow.class}) -@PowerMockIgnore({"javax.*"}) -public class CassandraAsyncReqRowTest { - - private CassandraAsyncReqRow cassandraAsyncReqRow; - private JoinInfo joinInfo; - private AbstractSideTableInfo sideTableInfo; - private RowTypeInfo rowTypeInfo = new RowTypeInfo(new TypeInformation[]{TypeInformation.of(Integer.class), TypeInformation.of(String.class), TypeInformation.of(Integer.class)}, new String[]{"id", "bb", "PROCTIME"}); - private BaseSideInfo sideInfo; - private Map inputParams = Maps.newHashMap(); - private GenericRow row = new GenericRow(4); - - @Before - public void setUp() { - joinInfo = mock(JoinInfo.class); - sideTableInfo = mock(AbstractSideTableInfo.class); - sideInfo = mock(BaseSideInfo.class); - inputParams.put("a", "1"); - - row.setField(0, "5f1d7fe5a38c8f074f2ba1e8"); - row.setField(1, "bbbbbbbb"); - row.setField(2, "ccxx"); - row.setField(3, "lisi"); - - List outFieldInfoList = Lists.newArrayList(); - FieldInfo fieldInfo = new FieldInfo(); - fieldInfo.setTable("m"); - fieldInfo.setFieldName("id"); - fieldInfo.setTypeInformation(TypeInformation.of(Integer.class)); - outFieldInfoList.add(fieldInfo); - outFieldInfoList.add(fieldInfo); - outFieldInfoList.add(fieldInfo); - outFieldInfoList.add(fieldInfo); - - Map inFieldIndex = Maps.newHashMap(); - inFieldIndex.put(0, 0); - inFieldIndex.put(1, 1); - - Map sideFieldIndex = Maps.newHashMap(); - sideFieldIndex.put(2, 0); - sideFieldIndex.put(3, 1); - - suppress(constructor(CassandraAsyncSideInfo.class)); - suppress(constructor(BaseSideInfo.class)); - cassandraAsyncReqRow = new CassandraAsyncReqRow(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); - Whitebox.setInternalState(cassandraAsyncReqRow, "sideInfo", sideInfo); - when(sideInfo.getOutFieldInfoList()).thenReturn(outFieldInfoList); - when(sideInfo.getInFieldIndex()).thenReturn(inFieldIndex); - when(sideInfo.getRowTypeInfo()).thenReturn(rowTypeInfo); - when(sideInfo.getSideFieldIndex()).thenReturn(sideFieldIndex); - } - - @Test - public void testOpen() throws Exception { - suppress(BaseAsyncReqRow.class.getMethod("open", Configuration.class)); - CassandraSideTableInfo sideTableInfo = mock(CassandraSideTableInfo.class); - - when(sideInfo.getSideTableInfo()).thenReturn(sideTableInfo); - when(sideTableInfo.getMaxRequestsPerConnection()).thenReturn(1); - when(sideTableInfo.getCoreConnectionsPerHost()).thenReturn(1); - when(sideTableInfo.getMaxConnectionsPerHost()).thenReturn(1); - when(sideTableInfo.getMaxQueueSize()).thenReturn(1); - when(sideTableInfo.getReadTimeoutMillis()).thenReturn(1); - when(sideTableInfo.getConnectTimeoutMillis()).thenReturn(1); - when(sideTableInfo.getPoolTimeoutMillis()).thenReturn(1); - when(sideTableInfo.getAddress()).thenReturn("12.12.12.12:9042,10.10.10.10:9042"); - when(sideTableInfo.getUserName()).thenReturn("userName"); - when(sideTableInfo.getPassword()).thenReturn("password"); - when(sideTableInfo.getDatabase()).thenReturn("getDatabase"); - cassandraAsyncReqRow.open(new Configuration()); - } - - @Test - public void testClose() throws Exception { - Cluster cluster = mock(Cluster.class); - Whitebox.setInternalState(cassandraAsyncReqRow, "cluster", cluster); - cassandraAsyncReqRow.close(); - } - - @Test - public void testHandleAsyncInvoke() throws Exception { - ListenableFuture session = mock(ListenableFuture.class); - Whitebox.setInternalState(cassandraAsyncReqRow, "session", session); - ResultFuture resultFuture = mock(ResultFuture.class); - - cassandraAsyncReqRow.handleAsyncInvoke(inputParams, row, resultFuture); - } - - @Test - public void testFillData() { - cassandraAsyncReqRow.fillData(row, null); - } -} diff --git a/cassandra/cassandra-side/cassandra-async-side/src/test/java/com/dtstack/flink/sql/side/cassandra/CassandraAsyncSideInfoTest.java b/cassandra/cassandra-side/cassandra-async-side/src/test/java/com/dtstack/flink/sql/side/cassandra/CassandraAsyncSideInfoTest.java deleted file mode 100644 index 783613b9e..000000000 --- a/cassandra/cassandra-side/cassandra-async-side/src/test/java/com/dtstack/flink/sql/side/cassandra/CassandraAsyncSideInfoTest.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.cassandra; - -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.BaseSideInfo; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.cassandra.table.CassandraSideTableInfo; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import org.apache.calcite.sql.SqlBasicCall; -import org.apache.calcite.sql.SqlBinaryOperator; -import org.apache.calcite.sql.SqlIdentifier; -import org.apache.calcite.sql.SqlNode; -import org.apache.calcite.sql.fun.SqlStdOperatorTable; -import org.apache.calcite.sql.parser.SqlParserPos; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import org.powermock.reflect.Whitebox; - -import java.util.List; -import java.util.Map; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.powermock.api.support.membermodification.MemberMatcher.constructor; -import static org.powermock.api.support.membermodification.MemberModifier.suppress; - -/** - * @author: chuixue - * @create: 2020-07-28 12:39 - * @description: - **/ -@RunWith(PowerMockRunner.class) -@PrepareForTest({CassandraAsyncSideInfo.class - , BaseSideInfo.class}) -public class CassandraAsyncSideInfoTest { - - private CassandraAsyncSideInfo cassandraAsyncSideInfo; - private JoinInfo joinInfo; - private AbstractSideTableInfo sideTableInfo; - private List equalValIndex = Lists.newArrayList(); - - @Before - public void setUp() { - joinInfo = mock(JoinInfo.class); - sideTableInfo = mock(AbstractSideTableInfo.class); - - List outFieldInfoList = Lists.newArrayList(); - FieldInfo fieldInfo = new FieldInfo(); - fieldInfo.setTable("m"); - fieldInfo.setFieldName("rowkey"); - fieldInfo.setTypeInformation(TypeInformation.of(String.class)); - outFieldInfoList.add(fieldInfo); - - FieldInfo fieldInfo2 = new FieldInfo(); - fieldInfo2.setTable("s"); - fieldInfo2.setFieldName("name"); - fieldInfo2.setTypeInformation(TypeInformation.of(String.class)); - outFieldInfoList.add(fieldInfo2); - - RowTypeInfo rowTypeInfo = new RowTypeInfo(new TypeInformation[]{TypeInformation.of(Integer.class), TypeInformation.of(String.class), TypeInformation.of(Integer.class)}, new String[]{"id", "bb", "PROCTIME"}); - List equalFieldList = Lists.newArrayList(); - equalFieldList.add("rowkey"); - - suppress(constructor(BaseSideInfo.class)); - cassandraAsyncSideInfo = new CassandraAsyncSideInfo(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); - - Whitebox.setInternalState(cassandraAsyncSideInfo, "equalValIndex", equalValIndex); - Whitebox.setInternalState(cassandraAsyncSideInfo, "rowTypeInfo", rowTypeInfo); - Whitebox.setInternalState(cassandraAsyncSideInfo, "equalFieldList", equalFieldList); - Whitebox.setInternalState(cassandraAsyncSideInfo, "sideSelectFields", "equalFieldList"); - } - - @Test - public void testBuildEqualInfo() { - CassandraSideTableInfo sideTableInfo = mock(CassandraSideTableInfo.class); - SqlBinaryOperator equalsOperators = SqlStdOperatorTable.EQUALS; - SqlNode[] operands = new SqlNode[2]; - List one = Lists.newArrayList(); - one.add("m"); - one.add("id"); - List two = Lists.newArrayList(); - two.add("s"); - two.add("rowkey"); - operands[0] = new SqlIdentifier(one, new SqlParserPos(0, 0)); - operands[1] = new SqlIdentifier(two, new SqlParserPos(0, 0)); - SqlBasicCall sqlBasicCall = new SqlBasicCall(equalsOperators, operands, SqlParserPos.ZERO); - - when(joinInfo.getSideTableName()).thenReturn("s"); - when(joinInfo.getCondition()).thenReturn(sqlBasicCall); - when(sideTableInfo.getDatabase()).thenReturn("da"); - when(sideTableInfo.getTableName()).thenReturn("da"); - - - cassandraAsyncSideInfo.buildEqualInfo(joinInfo, sideTableInfo); - } -} diff --git a/cassandra/cassandra-side/cassandra-side-core/src/main/java/com/dtstack/flink/sql/side/cassandra/table/CassandraSideParser.java b/cassandra/cassandra-side/cassandra-side-core/src/main/java/com/dtstack/flink/sql/side/cassandra/table/CassandraSideParser.java index f7f226548..6403a225b 100644 --- a/cassandra/cassandra-side/cassandra-side-core/src/main/java/com/dtstack/flink/sql/side/cassandra/table/CassandraSideParser.java +++ b/cassandra/cassandra-side/cassandra-side-core/src/main/java/com/dtstack/flink/sql/side/cassandra/table/CassandraSideParser.java @@ -19,16 +19,15 @@ package com.dtstack.flink.sql.side.cassandra.table; -import com.dtstack.flink.sql.table.AbstractSideTableParser; -import com.dtstack.flink.sql.table.AbstractTableInfo; +import com.dtstack.flink.sql.table.AbsSideTableParser; +import com.dtstack.flink.sql.table.TableInfo; import com.dtstack.flink.sql.util.MathUtil; -import java.sql.Timestamp; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; -import static com.dtstack.flink.sql.table.AbstractTableInfo.PARALLELISM_KEY; +import static com.dtstack.flink.sql.table.TableInfo.PARALLELISM_KEY; /** * Reason: @@ -36,7 +35,7 @@ * * @author xuqianjin */ -public class CassandraSideParser extends AbstractSideTableParser { +public class CassandraSideParser extends AbsSideTableParser { private final static String SIDE_SIGN_KEY = "sideSignKey"; @@ -66,12 +65,13 @@ public class CassandraSideParser extends AbstractSideTableParser { public static final String POOL_TIMEOUT_MILLIS_KEY = "poolTimeoutMillis"; - public CassandraSideParser() { - addParserHandler(SIDE_SIGN_KEY, SIDE_TABLE_SIGN, this::dealSideSign); + static { + keyPatternMap.put(SIDE_SIGN_KEY, SIDE_TABLE_SIGN); + keyHandlerMap.put(SIDE_SIGN_KEY, CassandraSideParser::dealSideSign); } @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { + public TableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { com.dtstack.flink.sql.side.cassandra.table.CassandraSideTableInfo cassandraSideTableInfo = new com.dtstack.flink.sql.side.cassandra.table.CassandraSideTableInfo(); cassandraSideTableInfo.setName(tableName); parseFieldsInfo(fieldsInfo, cassandraSideTableInfo); @@ -91,44 +91,9 @@ public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props = Maps.newHashMap(); - props.put("database", "cx"); - props.put("primarykeys", "mid"); - props.put("address", "localhost:9042"); - props.put("type", "cassandra"); - props.put("tablename", "sinkTable"); - - CassandraSideParser cassandraSideParser = new CassandraSideParser(); - cassandraSideParser.getTableInfo("Mykafka", " rowkey int,\n" + - " channel varchar ,\n" + - " name varchar ,\n" + - " PRIMARY KEY (rowkey),\n" + - " PERIOD FOR SYSTEM_TIME ", props); - } -} diff --git a/cassandra/cassandra-sink/pom.xml b/cassandra/cassandra-sink/pom.xml index 3c7a6a1e6..0d9b10361 100644 --- a/cassandra/cassandra-sink/pom.xml +++ b/cassandra/cassandra-sink/pom.xml @@ -33,7 +33,7 @@ - org.slf4j + @@ -64,14 +64,14 @@ - + - + diff --git a/cassandra/cassandra-sink/src/main/java/com/dtstack/flink/sql/sink/cassandra/CassandraOutputFormat.java b/cassandra/cassandra-sink/src/main/java/com/dtstack/flink/sql/sink/cassandra/CassandraOutputFormat.java index 4428fbc76..11fe24b81 100644 --- a/cassandra/cassandra-sink/src/main/java/com/dtstack/flink/sql/sink/cassandra/CassandraOutputFormat.java +++ b/cassandra/cassandra-sink/src/main/java/com/dtstack/flink/sql/sink/cassandra/CassandraOutputFormat.java @@ -38,12 +38,6 @@ package com.dtstack.flink.sql.sink.cassandra; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.tuple.Tuple; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.configuration.Configuration; -import org.apache.flink.types.Row; - import com.datastax.driver.core.Cluster; import com.datastax.driver.core.ConsistencyLevel; import com.datastax.driver.core.HostDistance; @@ -54,16 +48,20 @@ import com.datastax.driver.core.SocketOptions; import com.datastax.driver.core.policies.DowngradingConsistencyRetryPolicy; import com.datastax.driver.core.policies.RetryPolicy; -import com.dtstack.flink.sql.outputformat.AbstractDtRichOutputFormat; -import org.apache.commons.lang3.StringUtils; +import com.dtstack.flink.sql.metric.MetricConstant; +import org.apache.flink.api.common.io.RichOutputFormat; +import org.apache.flink.api.common.typeinfo.TypeInformation; +import org.apache.flink.api.java.tuple.Tuple; +import org.apache.flink.api.java.tuple.Tuple2; +import org.apache.flink.configuration.Configuration; +import org.apache.flink.metrics.Counter; +import org.apache.flink.metrics.Meter; +import org.apache.flink.metrics.MeterView; +import org.apache.flink.types.Row; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.io.IOException; import java.net.InetAddress; -import java.sql.Time; -import java.sql.Date; -import java.sql.Timestamp; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.util.ArrayList; @@ -75,7 +73,7 @@ * @see Tuple * @see DriverManager */ -public class CassandraOutputFormat extends AbstractDtRichOutputFormat { +public class CassandraOutputFormat extends RichOutputFormat { private static final long serialVersionUID = -7994311331389155692L; private static final Logger LOG = LoggerFactory.getLogger(CassandraOutputFormat.class); @@ -96,9 +94,17 @@ public class CassandraOutputFormat extends AbstractDtRichOutputFormat { protected String[] fieldNames; TypeInformation[] fieldTypes; + private int batchInterval = 5000; + private Cluster cluster; private Session session = null; + private int batchCount = 0; + + private transient Counter outRecords; + + private transient Meter outRecordsRate; + public CassandraOutputFormat() { } @@ -114,8 +120,7 @@ public void configure(Configuration parameters) { * I/O problem. */ @Override - public void open(int taskNumber, int numTasks) { - initMetric(); + public void open(int taskNumber, int numTasks) throws IOException { try { if (session == null) { QueryOptions queryOptions = new QueryOptions(); @@ -151,9 +156,9 @@ public void open(int taskNumber, int numTasks) { //重试策略 RetryPolicy retryPolicy = DowngradingConsistencyRetryPolicy.INSTANCE; - for (String server : StringUtils.split(address, ",")) { - cassandraPort = Integer.parseInt(StringUtils.split(server, ":")[1]); - serversList.add(InetAddress.getByName(StringUtils.split(server, ":")[0])); + for (String server : address.split(",")) { + cassandraPort = Integer.parseInt(server.split(":")[1]); + serversList.add(InetAddress.getByName(server.split(":")[0])); } if (userName == null || userName.isEmpty() || password == null || password.isEmpty()) { @@ -171,12 +176,17 @@ public void open(int taskNumber, int numTasks) { // 建立连接 连接已存在的键空间 session = cluster.connect(database); LOG.info("connect cassandra is successed!"); + initMetric(); } } catch (Exception e) { LOG.error("connect cassandra is error:" + e.getMessage()); } } + private void initMetric() { + outRecords = getRuntimeContext().getMetricGroup().counter(MetricConstant.DT_NUM_RECORDS_OUT); + outRecordsRate = getRuntimeContext().getMetricGroup().meter(MetricConstant.DT_NUM_RECORDS_OUT_RATE, new MeterView(outRecords, 20)); + } /** * Adds a record to the prepared statement. @@ -199,6 +209,7 @@ public void writeRecord(Tuple2 tuple2) throws IOException { try { if (retract) { insertWrite(row); + outRecords.inc(); } else { //do nothing } @@ -209,24 +220,13 @@ public void writeRecord(Tuple2 tuple2) throws IOException { private void insertWrite(Row row) { try { - - if(outRecords.getCount() % ROW_PRINT_FREQUENCY == 0){ - LOG.info("Receive data : {}", row); - } - String cql = buildSql(row); if (cql != null) { ResultSet resultSet = session.execute(cql); resultSet.wasApplied(); - outRecords.inc(); } } catch (Exception e) { - if(outDirtyRecords.getCount() % DIRTY_PRINT_FREQUENCY == 0){ - LOG.error("record insert failed, total dirty num:{}, current record:{}", outDirtyRecords.getCount(), row.toString()); - LOG.error("", e); - } - - outDirtyRecords.inc(); + LOG.error("[upsert] is error:" + e.getMessage()); } } @@ -237,14 +237,7 @@ private String buildSql(Row row) { if (row.getField(index) == null) { } else { fields.append(fieldNames[index] + ","); - if (row.getField(index) instanceof String - || row.getField(index) instanceof Time - || row.getField(index) instanceof Date - || row.getField(index) instanceof Timestamp) { - values.append("'" + row.getField(index) + "'" + ","); - } else { - values.append(row.getField(index) + ","); - } + values.append("'" + row.getField(index) + "'" + ","); } } fields.deleteCharAt(fields.length() - 1); diff --git a/cassandra/cassandra-sink/src/main/java/com/dtstack/flink/sql/sink/cassandra/CassandraSink.java b/cassandra/cassandra-sink/src/main/java/com/dtstack/flink/sql/sink/cassandra/CassandraSink.java index b8af15bf7..eb7b23b53 100644 --- a/cassandra/cassandra-sink/src/main/java/com/dtstack/flink/sql/sink/cassandra/CassandraSink.java +++ b/cassandra/cassandra-sink/src/main/java/com/dtstack/flink/sql/sink/cassandra/CassandraSink.java @@ -22,13 +22,12 @@ import com.dtstack.flink.sql.sink.IStreamSinkGener; import com.dtstack.flink.sql.sink.cassandra.table.CassandraTableInfo; -import com.dtstack.flink.sql.table.AbstractTargetTableInfo; +import com.dtstack.flink.sql.table.TargetTableInfo; import org.apache.flink.api.common.typeinfo.TypeInformation; import org.apache.flink.api.java.tuple.Tuple2; import org.apache.flink.api.java.typeutils.RowTypeInfo; import org.apache.flink.api.java.typeutils.TupleTypeInfo; import org.apache.flink.streaming.api.datastream.DataStream; -import org.apache.flink.streaming.api.datastream.DataStreamSink; import org.apache.flink.streaming.api.functions.sink.OutputFormatSinkFunction; import org.apache.flink.streaming.api.functions.sink.RichSinkFunction; import org.apache.flink.table.sinks.RetractStreamTableSink; @@ -58,15 +57,13 @@ public class CassandraSink implements RetractStreamTableSink, IStreamSinkGe protected Integer readTimeoutMillis; protected Integer connectTimeoutMillis; protected Integer poolTimeoutMillis; - protected Integer parallelism = 1; - protected String registerTableName; public CassandraSink() { // TO DO NOTHING } @Override - public CassandraSink genStreamSink(AbstractTargetTableInfo targetTableInfo) { + public CassandraSink genStreamSink(TargetTableInfo targetTableInfo) { CassandraTableInfo cassandraTableInfo = (CassandraTableInfo) targetTableInfo; this.address = cassandraTableInfo.getAddress(); this.tableName = cassandraTableInfo.getTableName(); @@ -80,18 +77,11 @@ public CassandraSink genStreamSink(AbstractTargetTableInfo targetTableInfo) { this.readTimeoutMillis = cassandraTableInfo.getReadTimeoutMillis(); this.connectTimeoutMillis = cassandraTableInfo.getConnectTimeoutMillis(); this.poolTimeoutMillis = cassandraTableInfo.getPoolTimeoutMillis(); - this.parallelism = cassandraTableInfo.getParallelism(); - this.registerTableName = cassandraTableInfo.getTableName(); return this; } @Override public void emitDataStream(DataStream> dataStream) { - consumeDataStream(dataStream); - } - - @Override - public DataStreamSink> consumeDataStream(DataStream> dataStream) { CassandraOutputFormat.CassandraFormatBuilder builder = CassandraOutputFormat.buildOutputFormat(); builder.setAddress(this.address) .setDatabase(this.database) @@ -110,10 +100,7 @@ public DataStreamSink> consumeDataStream(DataStream props) { + public TableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { CassandraTableInfo cassandraTableInfo = new CassandraTableInfo(); cassandraTableInfo.setName(tableName); parseFieldsInfo(fieldsInfo, cassandraTableInfo); diff --git a/cassandra/cassandra-sink/src/main/java/com/dtstack/flink/sql/sink/cassandra/table/CassandraTableInfo.java b/cassandra/cassandra-sink/src/main/java/com/dtstack/flink/sql/sink/cassandra/table/CassandraTableInfo.java index ffb5fa876..c6626c42a 100644 --- a/cassandra/cassandra-sink/src/main/java/com/dtstack/flink/sql/sink/cassandra/table/CassandraTableInfo.java +++ b/cassandra/cassandra-sink/src/main/java/com/dtstack/flink/sql/sink/cassandra/table/CassandraTableInfo.java @@ -19,7 +19,7 @@ package com.dtstack.flink.sql.sink.cassandra.table; -import com.dtstack.flink.sql.table.AbstractTargetTableInfo; +import com.dtstack.flink.sql.table.TargetTableInfo; import com.google.common.base.Preconditions; /** @@ -28,7 +28,7 @@ * * @author xuqianjin */ -public class CassandraTableInfo extends AbstractTargetTableInfo { +public class CassandraTableInfo extends TargetTableInfo { private static final String CURR_TYPE = "cassandra"; diff --git a/cassandra/cassandra-sink/src/test/java/com/dtstack/flink/sql/sink/cassandra/CassandraOutputFormatTest.java b/cassandra/cassandra-sink/src/test/java/com/dtstack/flink/sql/sink/cassandra/CassandraOutputFormatTest.java deleted file mode 100644 index 6857b097b..000000000 --- a/cassandra/cassandra-sink/src/test/java/com/dtstack/flink/sql/sink/cassandra/CassandraOutputFormatTest.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.cassandra; - -import com.datastax.driver.core.Cluster; -import com.datastax.driver.core.ResultSet; -import com.datastax.driver.core.Session; -import com.dtstack.flink.sql.outputformat.AbstractDtRichOutputFormat; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.metrics.Counter; -import org.apache.flink.types.Row; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.core.classloader.annotations.PowerMockIgnore; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import org.powermock.reflect.Whitebox; - -import java.io.IOException; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.powermock.api.support.membermodification.MemberModifier.suppress; - -/** - * @author: chuixue - * @create: 2020-07-28 10:07 - * @description: - **/ -@RunWith(PowerMockRunner.class) -@PrepareForTest({AbstractDtRichOutputFormat.class - , Cluster.class}) -@PowerMockIgnore({"javax.*"}) -public class CassandraOutputFormatTest { - - private CassandraOutputFormat cassandraOutputFormat = new CassandraOutputFormat(); - private Session session; - - @Before - public void setUp() { - session = mock(Session.class); - String[] fieldNames = new String[]{"mid", "mbb", "sid", "sbb"}; - Whitebox.setInternalState(cassandraOutputFormat, "session", session); - Whitebox.setInternalState(cassandraOutputFormat, "database", "cx"); - Whitebox.setInternalState(cassandraOutputFormat, "tableName", "tableName"); - Whitebox.setInternalState(cassandraOutputFormat, "fieldNames", fieldNames); - } - - @Test - public void testOpen() throws NoSuchMethodException { - suppress(AbstractDtRichOutputFormat.class.getMethod("initMetric")); - Whitebox.setInternalState(cassandraOutputFormat, "address", "12.12.12.12:9042,10.10.10.10:9042"); - Whitebox.setInternalState(cassandraOutputFormat, "userName", "userName"); - Whitebox.setInternalState(cassandraOutputFormat, "password", "password"); - Whitebox.setInternalState(cassandraOutputFormat, "coreConnectionsPerHost", 1); - Whitebox.setInternalState(cassandraOutputFormat, "maxConnectionsPerHost", 1); - Whitebox.setInternalState(cassandraOutputFormat, "maxQueueSize", 1); - Whitebox.setInternalState(cassandraOutputFormat, "readTimeoutMillis", 1); - Whitebox.setInternalState(cassandraOutputFormat, "connectTimeoutMillis", 1); - Whitebox.setInternalState(cassandraOutputFormat, "poolTimeoutMillis", 1); - - cassandraOutputFormat.open(1, 1); - } - - @Test - public void testClose() throws IOException { - Cluster cluster = mock(Cluster.class); - Whitebox.setInternalState(cassandraOutputFormat, "cluster", cluster); - - cassandraOutputFormat.close(); - } - - @Test - public void testInsertWrite() throws IOException { - Counter outRecords = mock(Counter.class); - Counter outDirtyRecords = mock(Counter.class); - Whitebox.setInternalState(cassandraOutputFormat, "outRecords", outRecords); - Whitebox.setInternalState(cassandraOutputFormat, "outDirtyRecords", outDirtyRecords); - - Row row = new Row(4); - row.setField(0, 1); - row.setField(1, "ddd"); - row.setField(2, "ad"); - row.setField(3, "qwe"); - - Tuple2 tuple2 = new Tuple2(); - tuple2.f0 = true; - tuple2.f1 = row; - - ResultSet resultSet = mock(ResultSet.class); - when(session.execute("")).thenReturn(resultSet); - - cassandraOutputFormat.writeRecord(tuple2); - } -} diff --git a/cassandra/cassandra-sink/src/test/java/com/dtstack/flink/sql/sink/cassandra/CassandraSinkTest.java b/cassandra/cassandra-sink/src/test/java/com/dtstack/flink/sql/sink/cassandra/CassandraSinkTest.java deleted file mode 100644 index e66c54e12..000000000 --- a/cassandra/cassandra-sink/src/test/java/com/dtstack/flink/sql/sink/cassandra/CassandraSinkTest.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.cassandra; - -import com.dtstack.flink.sql.sink.cassandra.table.CassandraTableInfo; -import com.dtstack.flink.sql.table.AbstractTargetTableInfo; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.streaming.api.datastream.DataStream; -import org.apache.flink.streaming.api.datastream.DataStreamSink; -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import org.powermock.reflect.Whitebox; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -/** - * @author: chuixue - * @create: 2020-07-28 09:46 - * @description: - **/ -@RunWith(PowerMockRunner.class) -@PrepareForTest({CassandraSink.class}) -public class CassandraSinkTest { - - private CassandraSink cassandraSink = new CassandraSink(); - -// @Test - public void testGenStreamSink() { - CassandraTableInfo cassandraTableInfo = new CassandraTableInfo(); - Assert.assertEquals(cassandraSink, cassandraSink.genStreamSink(cassandraTableInfo)); - } - -// @Test - public void testEmitDataStream() { - DataStream dataStream = mock(DataStream.class); - String[] fieldNames = new String[]{}; - TypeInformation[] fieldTypes = new TypeInformation[]{TypeInformation.of(Integer.class), TypeInformation.of(String.class), TypeInformation.of(Integer.class)}; - Whitebox.setInternalState(cassandraSink, "address", "address"); - Whitebox.setInternalState(cassandraSink, "database", "database"); - Whitebox.setInternalState(cassandraSink, "tableName", "tableName"); - Whitebox.setInternalState(cassandraSink, "password", "password"); - Whitebox.setInternalState(cassandraSink, "userName", "userName"); - Whitebox.setInternalState(cassandraSink, "maxRequestsPerConnection", 1); - Whitebox.setInternalState(cassandraSink, "coreConnectionsPerHost", 1); - Whitebox.setInternalState(cassandraSink, "maxConnectionsPerHost", 1); - Whitebox.setInternalState(cassandraSink, "maxQueueSize", 1); - Whitebox.setInternalState(cassandraSink, "readTimeoutMillis", 1); - Whitebox.setInternalState(cassandraSink, "connectTimeoutMillis", 1); - Whitebox.setInternalState(cassandraSink, "poolTimeoutMillis", 1); - Whitebox.setInternalState(cassandraSink, "fieldNames", fieldNames); - Whitebox.setInternalState(cassandraSink, "fieldTypes", fieldTypes); - - DataStreamSink dataStreamSink = PowerMockito.mock(DataStreamSink.class); - when(dataStream.addSink(any())).thenReturn(dataStreamSink); - when(dataStreamSink.setParallelism(anyInt())).thenReturn(dataStreamSink); - - cassandraSink.emitDataStream(dataStream); - } -} diff --git a/cassandra/cassandra-sink/src/test/java/com/dtstack/flink/sql/sink/cassandra/table/CassandraSinkParserTest.java b/cassandra/cassandra-sink/src/test/java/com/dtstack/flink/sql/sink/cassandra/table/CassandraSinkParserTest.java deleted file mode 100644 index 1c0504c6a..000000000 --- a/cassandra/cassandra-sink/src/test/java/com/dtstack/flink/sql/sink/cassandra/table/CassandraSinkParserTest.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.cassandra.table; - -import com.google.common.collect.Maps; -import org.junit.Test; - -import java.util.Map; - -/** - * @author: chuixue - * @create: 2020-07-28 09:48 - * @description: - **/ -public class CassandraSinkParserTest { - -// @Test - public void testGetTableInfo() { - - - CassandraSinkParser cassandraSinkParser = new CassandraSinkParser(); - Map props = Maps.newHashMap(); - props.put("database", "cx"); - props.put("primarykeys", "mid"); - props.put("address", "localhost:9042"); - props.put("type", "cassandra"); - props.put("tablename", "sinkTable"); - - cassandraSinkParser.getTableInfo("Mykafka", " mid int , mbb varchar, sid varchar, sbb varchar ", props); - } -} diff --git a/hbase/hbase-sink/src/main/java/com/dtstack/flink/sql/sink/hbase/enums/EReplaceType.java b/cassandra/cassandra-sink/src/test/java/com/dtstack/flinkx/AppTest.java similarity index 59% rename from hbase/hbase-sink/src/main/java/com/dtstack/flink/sql/sink/hbase/enums/EReplaceType.java rename to cassandra/cassandra-sink/src/test/java/com/dtstack/flinkx/AppTest.java index ad6bbcc4e..33a0233ac 100644 --- a/hbase/hbase-sink/src/main/java/com/dtstack/flink/sql/sink/hbase/enums/EReplaceType.java +++ b/cassandra/cassandra-sink/src/test/java/com/dtstack/flinkx/AppTest.java @@ -18,26 +18,41 @@ -package com.dtstack.flink.sql.sink.hbase.enums; +package com.dtstack.flinkx; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; /** - * Reason: - * Date: 2018/8/23 - * Company: www.dtstack.com - * - * @author xuchao + * Unit test for simple App. */ -public enum EReplaceType { +public class AppTest + extends TestCase +{ /** - * 参数 + * Create the test case + * + * @param testName name of the test case */ - PARAM, + public AppTest( String testName ) + { + super( testName ); + } + /** - * 函数 + * @return the suite of tests being tested */ - FUNC, + public static Test suite() + { + return new TestSuite( AppTest.class ); + } + /** - * 常量 + * Rigourous Test :-) */ - CONSTANT; + public void testApp() + { + assertTrue( true ); + } } diff --git a/cassandra/pom.xml b/cassandra/pom.xml index f41028708..f49de388b 100644 --- a/cassandra/pom.xml +++ b/cassandra/pom.xml @@ -17,6 +17,12 @@ + + junit + junit + 3.8.1 + test + com.dtstack.flink sql.core diff --git a/ci/sonar_analyze.sh b/ci/sonar_analyze.sh deleted file mode 100755 index a0d9a18e3..000000000 --- a/ci/sonar_analyze.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash - -mvn clean test -Dmaven.test.failure.ignore=true -q - -mvn sonar:sonar \ - -Dsonar.projectKey="dt-insight-engine/flinkStreamSQL" \ - -Dsonar.login=11974c5e9a29625efa09fdc3c3fdc031efb1aab1 \ - -Dsonar.host.url=http://172.16.100.198:9000 \ - -Dsonar.jdbc.url=jdbc:postgresql://172.16.100.198:5432/sonar \ - -Dsonar.java.binaries=target/classes \ - -Dsonar.inclusions="src/main/java/com/dtstack/flink/**/*" \ - -Dsonar.exclusions="src/main/java/org/**/*" diff --git a/ci/sonar_notify.sh b/ci/sonar_notify.sh deleted file mode 100644 index da36b8c5e..000000000 --- a/ci/sonar_notify.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash -#参考钉钉文档 https://open-doc.dingtalk.com/microapp/serverapi2/qf2nxq - sonarreport=$(curl -s http://172.16.100.198:8082/?projectname=dt-insight-engine/flinkStreamSQL) - curl -s "https://oapi.dingtalk.com/robot/send?access_token=58fd731d8bed3b17708d3aa27e49a7e2c41c7e6545f6c4be3170963a7bba7e2a" \ - -H "Content-Type: application/json" \ - -d "{ - \"msgtype\": \"markdown\", - \"markdown\": { - \"title\":\"sonar代码质量\", - \"text\": \"## sonar代码质量报告: \n -> [sonar地址](http://172.16.100.198:9000/dashboard?id=dt-insight-engine/flinkStreamSQL) \n -> ${sonarreport} \n\" - } - }" \ No newline at end of file diff --git a/clickhouse/clickhouse-side/clickhouse-all-side/pom.xml b/clickhouse/clickhouse-side/clickhouse-all-side/pom.xml index b8fc40f74..8e6c6f51a 100644 --- a/clickhouse/clickhouse-side/clickhouse-all-side/pom.xml +++ b/clickhouse/clickhouse-side/clickhouse-all-side/pom.xml @@ -41,7 +41,7 @@ - org.slf4j + @@ -72,14 +72,14 @@ - + - + diff --git a/clickhouse/clickhouse-side/clickhouse-all-side/src/main/java/com/dtstack/flink/sql/side/clickhouse/ClickhouseAllReqRow.java b/clickhouse/clickhouse-side/clickhouse-all-side/src/main/java/com/dtstack/flink/sql/side/clickhouse/ClickhouseAllReqRow.java index d770356a8..68c0c7984 100644 --- a/clickhouse/clickhouse-side/clickhouse-all-side/src/main/java/com/dtstack/flink/sql/side/clickhouse/ClickhouseAllReqRow.java +++ b/clickhouse/clickhouse-side/clickhouse-all-side/src/main/java/com/dtstack/flink/sql/side/clickhouse/ClickhouseAllReqRow.java @@ -18,39 +18,42 @@ package com.dtstack.flink.sql.side.clickhouse; -import com.dtstack.flink.sql.classloader.ClassLoaderManager; import com.dtstack.flink.sql.side.FieldInfo; import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.rdb.all.AbstractRdbAllReqRow; +import com.dtstack.flink.sql.side.SideTableInfo; +import com.dtstack.flink.sql.side.rdb.all.RdbAllReqRow; +import com.dtstack.flink.sql.util.DtStringUtil; +import com.dtstack.flink.sql.util.JDBCUtils; import org.apache.flink.api.java.typeutils.RowTypeInfo; +import org.apache.flink.shaded.guava18.com.google.common.collect.Maps; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.sql.Connection; import java.sql.DriverManager; import java.util.List; +import java.util.Map; -public class ClickhouseAllReqRow extends AbstractRdbAllReqRow { +public class ClickhouseAllReqRow extends RdbAllReqRow { private static final Logger LOG = LoggerFactory.getLogger(ClickhouseAllReqRow.class); private static final String CLICKHOUSE_DRIVER = "ru.yandex.clickhouse.ClickHouseDriver"; - public ClickhouseAllReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { + public ClickhouseAllReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, SideTableInfo sideTableInfo) { super(new ClickhouseAllSideInfo(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo)); } @Override - public Connection getConn(String dbUrl, String userName, String passWord) { + public Connection getConn(String dbURL, String userName, String passWord) { try { Connection connection ; - ClassLoaderManager.forName(CLICKHOUSE_DRIVER, getClass().getClassLoader()); + JDBCUtils.forName(CLICKHOUSE_DRIVER, getClass().getClassLoader()); // ClickHouseProperties contains all properties if (userName == null) { - connection = DriverManager.getConnection(dbUrl); + connection = DriverManager.getConnection(dbURL); } else { - connection = DriverManager.getConnection(dbUrl, userName, passWord); + connection = DriverManager.getConnection(dbURL, userName, passWord); } return connection; } catch (Exception e) { diff --git a/clickhouse/clickhouse-side/clickhouse-all-side/src/main/java/com/dtstack/flink/sql/side/clickhouse/ClickhouseAllSideInfo.java b/clickhouse/clickhouse-side/clickhouse-all-side/src/main/java/com/dtstack/flink/sql/side/clickhouse/ClickhouseAllSideInfo.java index 43fbeaa56..973c069b9 100644 --- a/clickhouse/clickhouse-side/clickhouse-all-side/src/main/java/com/dtstack/flink/sql/side/clickhouse/ClickhouseAllSideInfo.java +++ b/clickhouse/clickhouse-side/clickhouse-all-side/src/main/java/com/dtstack/flink/sql/side/clickhouse/ClickhouseAllSideInfo.java @@ -20,7 +20,7 @@ import com.dtstack.flink.sql.side.FieldInfo; import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; +import com.dtstack.flink.sql.side.SideTableInfo; import com.dtstack.flink.sql.side.rdb.all.RdbAllSideInfo; import org.apache.flink.api.java.typeutils.RowTypeInfo; @@ -28,7 +28,7 @@ public class ClickhouseAllSideInfo extends RdbAllSideInfo { - public ClickhouseAllSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { + public ClickhouseAllSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, SideTableInfo sideTableInfo) { super(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); } } diff --git a/clickhouse/clickhouse-side/clickhouse-all-side/src/test/java/com/dtstack/flink/sql/side/clickhouse/ClickhouseAllReqRowTest.java b/clickhouse/clickhouse-side/clickhouse-all-side/src/test/java/com/dtstack/flink/sql/side/clickhouse/ClickhouseAllReqRowTest.java deleted file mode 100644 index 874470800..000000000 --- a/clickhouse/clickhouse-side/clickhouse-all-side/src/test/java/com/dtstack/flink/sql/side/clickhouse/ClickhouseAllReqRowTest.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.dtstack.flink.sql.side.clickhouse; - -import com.dtstack.flink.sql.side.rdb.all.RdbAllReqRowTestBase; - -public class ClickhouseAllReqRowTest extends RdbAllReqRowTestBase { - - @Override - protected void init() { - clazz = ClickhouseAllReqRow.class; - } - -} \ No newline at end of file diff --git a/clickhouse/clickhouse-side/clickhouse-async-side/pom.xml b/clickhouse/clickhouse-side/clickhouse-async-side/pom.xml index 7f99ac840..ab889c5a8 100644 --- a/clickhouse/clickhouse-side/clickhouse-async-side/pom.xml +++ b/clickhouse/clickhouse-side/clickhouse-async-side/pom.xml @@ -41,7 +41,7 @@ - org.slf4j + @@ -72,14 +72,14 @@ - + - + diff --git a/clickhouse/clickhouse-side/clickhouse-async-side/src/main/java/com/dtstack/flink/sql/side/clickhouse/ClickhouseAsyncReqRow.java b/clickhouse/clickhouse-side/clickhouse-async-side/src/main/java/com/dtstack/flink/sql/side/clickhouse/ClickhouseAsyncReqRow.java index 8f577d1e8..305d65118 100644 --- a/clickhouse/clickhouse-side/clickhouse-async-side/src/main/java/com/dtstack/flink/sql/side/clickhouse/ClickhouseAsyncReqRow.java +++ b/clickhouse/clickhouse-side/clickhouse-async-side/src/main/java/com/dtstack/flink/sql/side/clickhouse/ClickhouseAsyncReqRow.java @@ -19,12 +19,15 @@ package com.dtstack.flink.sql.side.clickhouse; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; import com.dtstack.flink.sql.side.FieldInfo; import com.dtstack.flink.sql.side.JoinInfo; +import com.dtstack.flink.sql.side.SideTableInfo; import com.dtstack.flink.sql.side.rdb.async.RdbAsyncReqRow; import com.dtstack.flink.sql.side.rdb.table.RdbSideTableInfo; +import io.vertx.core.Vertx; +import io.vertx.core.VertxOptions; import io.vertx.core.json.JsonObject; +import io.vertx.ext.jdbc.JDBCClient; import org.apache.flink.api.java.typeutils.RowTypeInfo; import org.apache.flink.configuration.Configuration; @@ -34,29 +37,28 @@ public class ClickhouseAsyncReqRow extends RdbAsyncReqRow { private static final String CLICKHOUSE_DRIVER = "ru.yandex.clickhouse.ClickHouseDriver"; - public ClickhouseAsyncReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { + public ClickhouseAsyncReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, SideTableInfo sideTableInfo) { super(new ClickhouseAsyncSideInfo(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo)); } @Override public void open(Configuration parameters) throws Exception { super.open(parameters); - } - - @Override - public JsonObject buildJdbcConfig() { JsonObject clickhouseClientConfig = new JsonObject(); RdbSideTableInfo rdbSideTableInfo = (RdbSideTableInfo) sideInfo.getSideTableInfo(); clickhouseClientConfig.put("url", rdbSideTableInfo.getUrl()) .put("driver_class", CLICKHOUSE_DRIVER) - .put("max_pool_size", rdbSideTableInfo.getAsyncPoolSize()) + .put("max_pool_size", DEFAULT_MAX_DB_CONN_POOL_SIZE) .put("user", rdbSideTableInfo.getUserName()) .put("password", rdbSideTableInfo.getPassword()) - .put("provider_class", DT_PROVIDER_CLASS) - .put("preferred_test_query", PREFERRED_TEST_QUERY_SQL) - .put("idle_connection_test_period", DEFAULT_IDLE_CONNECTION_TEST_PEROID) - .put("test_connection_on_checkin", DEFAULT_TEST_CONNECTION_ON_CHECKIN); - - return clickhouseClientConfig; + .put("provider_class", DT_PROVIDER_CLASS); + System.setProperty("vertx.disableFileCPResolving", "true"); + VertxOptions vo = new VertxOptions(); + vo.setEventLoopPoolSize(DEFAULT_VERTX_EVENT_LOOP_POOL_SIZE); + vo.setWorkerPoolSize(DEFAULT_VERTX_WORKER_POOL_SIZE); + vo.setFileResolverCachingEnabled(false); + Vertx vertx = Vertx.vertx(vo); + setRdbSQLClient(JDBCClient.createNonShared(vertx, clickhouseClientConfig)); } + } diff --git a/clickhouse/clickhouse-side/clickhouse-async-side/src/main/java/com/dtstack/flink/sql/side/clickhouse/ClickhouseAsyncSideInfo.java b/clickhouse/clickhouse-side/clickhouse-async-side/src/main/java/com/dtstack/flink/sql/side/clickhouse/ClickhouseAsyncSideInfo.java index eec5fbe74..254561de0 100644 --- a/clickhouse/clickhouse-side/clickhouse-async-side/src/main/java/com/dtstack/flink/sql/side/clickhouse/ClickhouseAsyncSideInfo.java +++ b/clickhouse/clickhouse-side/clickhouse-async-side/src/main/java/com/dtstack/flink/sql/side/clickhouse/ClickhouseAsyncSideInfo.java @@ -20,7 +20,7 @@ import com.dtstack.flink.sql.side.FieldInfo; import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; +import com.dtstack.flink.sql.side.SideTableInfo; import com.dtstack.flink.sql.side.rdb.async.RdbAsyncSideInfo; import org.apache.flink.api.java.typeutils.RowTypeInfo; @@ -29,7 +29,7 @@ public class ClickhouseAsyncSideInfo extends RdbAsyncSideInfo { - public ClickhouseAsyncSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { + public ClickhouseAsyncSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, SideTableInfo sideTableInfo) { super(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); } } diff --git a/clickhouse/clickhouse-side/clickhouse-async-side/src/test/java/com/dtstack/flink/sql/side/clickhouse/ClickhouseAsyncReqRowTest.java b/clickhouse/clickhouse-side/clickhouse-async-side/src/test/java/com/dtstack/flink/sql/side/clickhouse/ClickhouseAsyncReqRowTest.java deleted file mode 100644 index eeb4f205c..000000000 --- a/clickhouse/clickhouse-side/clickhouse-async-side/src/test/java/com/dtstack/flink/sql/side/clickhouse/ClickhouseAsyncReqRowTest.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.dtstack.flink.sql.side.clickhouse; - -import com.dtstack.flink.sql.side.rdb.async.RdbAsyncReqRowTestBase; - -public class ClickhouseAsyncReqRowTest extends RdbAsyncReqRowTestBase { - - @Override - protected void init() { - clazz = ClickhouseAsyncReqRow.class; - } - -} \ No newline at end of file diff --git a/clickhouse/clickhouse-side/clickhouse-side-core/src/main/java/com/dtstack/flink/sql/side/clickhouse/table/ClickhouseSideParser.java b/clickhouse/clickhouse-side/clickhouse-side-core/src/main/java/com/dtstack/flink/sql/side/clickhouse/table/ClickhouseSideParser.java index 0e85a0ccc..7be387fd8 100644 --- a/clickhouse/clickhouse-side/clickhouse-side-core/src/main/java/com/dtstack/flink/sql/side/clickhouse/table/ClickhouseSideParser.java +++ b/clickhouse/clickhouse-side/clickhouse-side-core/src/main/java/com/dtstack/flink/sql/side/clickhouse/table/ClickhouseSideParser.java @@ -19,9 +19,8 @@ package com.dtstack.flink.sql.side.clickhouse.table; -import com.dtstack.flink.sql.core.rdb.JdbcCheckKeys; import com.dtstack.flink.sql.side.rdb.table.RdbSideParser; -import com.dtstack.flink.sql.table.AbstractTableInfo; +import com.dtstack.flink.sql.table.TableInfo; import ru.yandex.clickhouse.domain.ClickHouseDataType; import java.util.Map; @@ -39,9 +38,8 @@ public class ClickhouseSideParser extends RdbSideParser { private static final String CURR_TYPE = "clickhouse"; @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { - props.put(JdbcCheckKeys.DRIVER_NAME, "ru.yandex.clickhouse.ClickHouseDriver"); - AbstractTableInfo clickhouseTableInfo = super.getTableInfo(tableName, fieldsInfo, props); + public TableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { + TableInfo clickhouseTableInfo = super.getTableInfo(tableName, fieldsInfo, props); clickhouseTableInfo.setType(CURR_TYPE); return clickhouseTableInfo; } diff --git a/clickhouse/clickhouse-side/clickhouse-side-core/src/test/java/com/dtstack/flink/sql/side/clickhouse/table/ClickhouseSideParserTest.java b/clickhouse/clickhouse-side/clickhouse-side-core/src/test/java/com/dtstack/flink/sql/side/clickhouse/table/ClickhouseSideParserTest.java deleted file mode 100644 index adfb2639d..000000000 --- a/clickhouse/clickhouse-side/clickhouse-side-core/src/test/java/com/dtstack/flink/sql/side/clickhouse/table/ClickhouseSideParserTest.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.dtstack.flink.sql.side.clickhouse.table; - -import com.dtstack.flink.sql.table.AbstractTableInfo; -import org.junit.Assert; -import org.junit.Test; -import java.util.HashMap; -import java.util.Map; - -public class ClickhouseSideParserTest { - -// @Test - public void getTableInfo() { - ClickhouseSideParser sideParser = new ClickhouseSideParser(); - - final String tableName = "table_foo"; - final String fieldsInfo = "id INT, name VARCHAR , PRIMARY KEY (id) , PERIOD FOR SYSTEM_TIME"; - - Map props = new HashMap(); - props.put("url", "jdbc:mysql://foo:3306/db_foo"); - props.put("tablename", "table_foo"); - props.put("username", "foo"); - props.put("password", "foo"); - - AbstractTableInfo tableInfo= sideParser.getTableInfo(tableName, fieldsInfo, props); - - final String NORMAL_TYPE = "clickhouse"; - final String table_type = tableInfo.getType(); - Assert.assertTrue(NORMAL_TYPE.equals(table_type)); - } - -} \ No newline at end of file diff --git a/clickhouse/clickhouse-side/pom.xml b/clickhouse/clickhouse-side/pom.xml index 558eb0bf3..2ba6a14dc 100644 --- a/clickhouse/clickhouse-side/pom.xml +++ b/clickhouse/clickhouse-side/pom.xml @@ -31,16 +31,6 @@ sql.side.rdb ${rdb.side.version} - - - - - com.dtstack.flink - sql.side.rdb - ${rdb.side.version} - test-jar - test - \ No newline at end of file diff --git a/clickhouse/clickhouse-sink/pom.xml b/clickhouse/clickhouse-sink/pom.xml index 2022ac6fd..75aac514a 100644 --- a/clickhouse/clickhouse-sink/pom.xml +++ b/clickhouse/clickhouse-sink/pom.xml @@ -40,7 +40,7 @@ - org.slf4j + @@ -71,14 +71,14 @@ - + - + diff --git a/clickhouse/clickhouse-sink/src/main/java/com/dtstack/flink/sql/sink/clickhouse/ClickhouseDialect.java b/clickhouse/clickhouse-sink/src/main/java/com/dtstack/flink/sql/sink/clickhouse/ClickhouseDialect.java deleted file mode 100644 index 29bf54798..000000000 --- a/clickhouse/clickhouse-sink/src/main/java/com/dtstack/flink/sql/sink/clickhouse/ClickhouseDialect.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.clickhouse; - -import com.dtstack.flink.sql.sink.rdb.dialect.JDBCDialect; - -import java.util.Optional; - -/** - * Date: 2020/1/15 - * Company: www.dtstack.com - * @author maqi - */ -public class ClickhouseDialect implements JDBCDialect { - - @Override - public boolean canHandle(String url) { - return url.startsWith("jdbc:clickhouse:"); - } - - @Override - public Optional defaultDriverName() { - return Optional.of("ru.yandex.clickhouse.ClickHouseDriver"); - } - - @Override - public String getUpdateStatement(String tableName, String[] fieldNames, String[] conditionFields) { - throw new RuntimeException("Clickhouse does not support update sql, please remove primary key or use append mode"); - } -} diff --git a/clickhouse/clickhouse-sink/src/main/java/com/dtstack/flink/sql/sink/clickhouse/ClickhouseSink.java b/clickhouse/clickhouse-sink/src/main/java/com/dtstack/flink/sql/sink/clickhouse/ClickhouseSink.java index e28dfc2b0..66c1f26d5 100644 --- a/clickhouse/clickhouse-sink/src/main/java/com/dtstack/flink/sql/sink/clickhouse/ClickhouseSink.java +++ b/clickhouse/clickhouse-sink/src/main/java/com/dtstack/flink/sql/sink/clickhouse/ClickhouseSink.java @@ -21,37 +21,58 @@ import com.dtstack.flink.sql.sink.IStreamSinkGener; -import com.dtstack.flink.sql.sink.rdb.JDBCOptions; -import com.dtstack.flink.sql.sink.rdb.AbstractRdbSink; -import com.dtstack.flink.sql.sink.rdb.format.JDBCUpsertOutputFormat; +import com.dtstack.flink.sql.sink.rdb.RdbSink; +import com.dtstack.flink.sql.sink.rdb.format.RetractJDBCOutputFormat; +import java.util.List; +import java.util.Map; + + +public class ClickhouseSink extends RdbSink implements IStreamSinkGener { + + private static final String CLICKHOUSE_DRIVER = "ru.yandex.clickhouse.ClickHouseDriver"; -public class ClickhouseSink extends AbstractRdbSink implements IStreamSinkGener { public ClickhouseSink() { - super(new ClickhouseDialect()); } @Override - public JDBCUpsertOutputFormat getOutputFormat() { - JDBCOptions jdbcOptions = JDBCOptions.builder() - .setDbUrl(dbUrl) - .setDialect(jdbcDialect) - .setUsername(userName) - .setPassword(password) - .setTableName(tableName) - .build(); - - return JDBCUpsertOutputFormat.builder() - .setOptions(jdbcOptions) - .setFieldNames(fieldNames) - .setFlushMaxSize(batchNum) - .setFlushIntervalMills(batchWaitInterval) - .setFieldTypes(sqlTypes) - .setKeyFields(primaryKeys) - .setAllReplace(allReplace) - .setUpdateMode(updateMode) - .setErrorLimit(errorLimit) - .build(); + public RetractJDBCOutputFormat getOutputFormat() { + return new RetractJDBCOutputFormat(); + } + + @Override + public void buildSql(String scheam, String tableName, List fields) { + buildInsertSql(tableName, fields); + } + + @Override + public String buildUpdateSql(String schema, String tableName, List fieldNames, Map> realIndexes, List fullField) { + return null; + } + + private void buildInsertSql(String tableName, List fields) { + String sqlTmp = "insert into " + tableName + " (${fields}) values (${placeholder})"; + String fieldsStr = ""; + String placeholder = ""; + + for (String fieldName : fields) { + fieldsStr += ",`" + fieldName + "`"; + placeholder += ",?"; + } + + fieldsStr = fieldsStr.replaceFirst(",", ""); + placeholder = placeholder.replaceFirst(",", ""); + + sqlTmp = sqlTmp.replace("${fields}", fieldsStr).replace("${placeholder}", placeholder); + this.sql = sqlTmp; + System.out.println("---insert sql----"); + System.out.println(sql); + } + + + @Override + public String getDriverName() { + return CLICKHOUSE_DRIVER; } diff --git a/clickhouse/clickhouse-sink/src/main/java/com/dtstack/flink/sql/sink/clickhouse/table/ClickhouseSinkParser.java b/clickhouse/clickhouse-sink/src/main/java/com/dtstack/flink/sql/sink/clickhouse/table/ClickhouseSinkParser.java index 75478061e..8c3df93d7 100644 --- a/clickhouse/clickhouse-sink/src/main/java/com/dtstack/flink/sql/sink/clickhouse/table/ClickhouseSinkParser.java +++ b/clickhouse/clickhouse-sink/src/main/java/com/dtstack/flink/sql/sink/clickhouse/table/ClickhouseSinkParser.java @@ -19,9 +19,8 @@ package com.dtstack.flink.sql.sink.clickhouse.table; -import com.dtstack.flink.sql.core.rdb.JdbcCheckKeys; import com.dtstack.flink.sql.sink.rdb.table.RdbSinkParser; -import com.dtstack.flink.sql.table.AbstractTableInfo; +import com.dtstack.flink.sql.table.TableInfo; import ru.yandex.clickhouse.domain.ClickHouseDataType; import java.util.Map; @@ -31,9 +30,8 @@ public class ClickhouseSinkParser extends RdbSinkParser { private static final String CURR_TYPE = "clickhouse"; @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { - props.put(JdbcCheckKeys.DRIVER_NAME, "ru.yandex.clickhouse.ClickHouseDriver"); - AbstractTableInfo clickhouseTableInfo = super.getTableInfo(tableName, fieldsInfo, props); + public TableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { + TableInfo clickhouseTableInfo = super.getTableInfo(tableName, fieldsInfo, props); clickhouseTableInfo.setType(CURR_TYPE); return clickhouseTableInfo; } diff --git a/clickhouse/clickhouse-sink/src/test/java/com/dtstack/flink/sql/sink/clickhouse/ClickhouseDialectTest.java b/clickhouse/clickhouse-sink/src/test/java/com/dtstack/flink/sql/sink/clickhouse/ClickhouseDialectTest.java deleted file mode 100644 index 62aec0dcf..000000000 --- a/clickhouse/clickhouse-sink/src/test/java/com/dtstack/flink/sql/sink/clickhouse/ClickhouseDialectTest.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.dtstack.flink.sql.sink.clickhouse; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -public class ClickhouseDialectTest { - - ClickhouseDialect dialect; - - @Before - public void setUp() throws Exception { - dialect = new ClickhouseDialect(); - } - - @Test - public void testEasyUtils() { - final String s = "jdbc:clickhouse://localhost:3306/foo_db"; - boolean r = dialect.canHandle(s); - Assert.assertTrue(r); - - String driver = dialect.defaultDriverName().get(); - Assert.assertTrue(driver.equals("ru.yandex.clickhouse.ClickHouseDriver")); - } - -} \ No newline at end of file diff --git a/clickhouse/clickhouse-sink/src/test/java/com/dtstack/flink/sql/sink/clickhouse/ClickhouseSinkTest.java b/clickhouse/clickhouse-sink/src/test/java/com/dtstack/flink/sql/sink/clickhouse/ClickhouseSinkTest.java deleted file mode 100644 index 091361f96..000000000 --- a/clickhouse/clickhouse-sink/src/test/java/com/dtstack/flink/sql/sink/clickhouse/ClickhouseSinkTest.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.dtstack.flink.sql.sink.clickhouse; - -import com.dtstack.flink.sql.sink.rdb.dialect.JDBCDialect; -import com.dtstack.flink.sql.sink.rdb.format.JDBCUpsertOutputFormat; -import org.junit.Before; -import org.junit.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.powermock.api.support.membermodification.MemberModifier; -import java.util.Optional; -import static org.mockito.Mockito.when; - -public class ClickhouseSinkTest { - - @Mock - JDBCDialect jdbcDialect; - - @InjectMocks - ClickhouseSink sink = new ClickhouseSink();; - @Before - public void setUp () { - MockitoAnnotations.initMocks(this); - } - - @Test - public void testGetOutputFormat() throws IllegalAccessException { - when(jdbcDialect.defaultDriverName()).thenReturn(Optional.of("dd")); - - MemberModifier.field(ClickhouseSink.class, "dbUrl").set(sink, "foo"); - MemberModifier.field(ClickhouseSink.class, "jdbcDialect").set(sink, jdbcDialect); - MemberModifier.field(ClickhouseSink.class, "userName").set(sink, "foo"); - MemberModifier.field(ClickhouseSink.class, "password").set(sink, "foo"); - MemberModifier.field(ClickhouseSink.class, "tableName").set(sink, "foo"); - MemberModifier.field(ClickhouseSink.class, "fieldNames").set(sink, new String[]{"foo", "bar"}); - - JDBCUpsertOutputFormat format = sink.getOutputFormat(); - } - -} \ No newline at end of file diff --git a/clickhouse/clickhouse-sink/src/test/java/com/dtstack/flink/sql/sink/clickhouse/table/ClickhouseSinkParserTest.java b/clickhouse/clickhouse-sink/src/test/java/com/dtstack/flink/sql/sink/clickhouse/table/ClickhouseSinkParserTest.java deleted file mode 100644 index 8b3ab8fe5..000000000 --- a/clickhouse/clickhouse-sink/src/test/java/com/dtstack/flink/sql/sink/clickhouse/table/ClickhouseSinkParserTest.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.dtstack.flink.sql.sink.clickhouse.table; - -import com.dtstack.flink.sql.table.AbstractTableInfo; -import org.junit.Assert; -import org.junit.Test; -import java.util.HashMap; -import java.util.Map; - -public class ClickhouseSinkParserTest { - -// @Test - public void getTableInfo() { - ClickhouseSinkParser mysqlSinkParser = new ClickhouseSinkParser(); - - final String tableName = "table_foo"; - final String fieldsInfo = "id INT, name VARCHAR"; - - Map props = new HashMap(); - props.put("url", "jdbc:mysql://foo:3306/db_foo"); - props.put("tablename", "table_foo"); - props.put("username", "foo"); - props.put("password", "foo"); - - AbstractTableInfo tableInfo= mysqlSinkParser.getTableInfo(tableName, fieldsInfo, props); - - final String NORMAL_TYPE = "clickhouse"; - final String table_type = tableInfo.getType(); - Assert.assertTrue(NORMAL_TYPE.equals(table_type)); - } - -} \ No newline at end of file diff --git a/console/console-sink/pom.xml b/console/console-sink/pom.xml index 86f3e73eb..2f8ad9ef9 100644 --- a/console/console-sink/pom.xml +++ b/console/console-sink/pom.xml @@ -60,14 +60,14 @@ - + - + diff --git a/console/console-sink/src/main/java/com/dtstack/flink/sql/sink/console/ConsoleOutputFormat.java b/console/console-sink/src/main/java/com/dtstack/flink/sql/sink/console/ConsoleOutputFormat.java index fc5a768c4..7658e9979 100644 --- a/console/console-sink/src/main/java/com/dtstack/flink/sql/sink/console/ConsoleOutputFormat.java +++ b/console/console-sink/src/main/java/com/dtstack/flink/sql/sink/console/ConsoleOutputFormat.java @@ -18,7 +18,7 @@ package com.dtstack.flink.sql.sink.console; -import com.dtstack.flink.sql.outputformat.AbstractDtRichOutputFormat; +import com.dtstack.flink.sql.sink.MetricOutputFormat; import com.dtstack.flink.sql.sink.console.table.TablePrintUtil; import org.apache.flink.api.common.typeinfo.TypeInformation; import org.apache.flink.api.java.tuple.Tuple2; @@ -37,7 +37,7 @@ * * @author xuqianjin */ -public class ConsoleOutputFormat extends AbstractDtRichOutputFormat { +public class ConsoleOutputFormat extends MetricOutputFormat { private static final Logger LOG = LoggerFactory.getLogger(ConsoleOutputFormat.class); @@ -56,7 +56,6 @@ public void open(int taskNumber, int numTasks) throws IOException { @Override public void writeRecord(Tuple2 tuple2) throws IOException { - LOG.info("received oriainal data:{}" + tuple2); Tuple2 tupleTrans = tuple2; Boolean retract = tupleTrans.getField(0); if (!retract) { @@ -70,11 +69,7 @@ public void writeRecord(Tuple2 tuple2) throws IOException { List data = new ArrayList<>(); data.add(fieldNames); - String[] recordStr = new String[record.getArity()]; - for (int i=0; i < record.getArity(); i++) { - recordStr[i] = (String.valueOf(record.getField(i))); - } - data.add(recordStr); + data.add(record.toString().split(",")); TablePrintUtil.build(data).print(); outRecords.inc(); diff --git a/console/console-sink/src/main/java/com/dtstack/flink/sql/sink/console/ConsoleSink.java b/console/console-sink/src/main/java/com/dtstack/flink/sql/sink/console/ConsoleSink.java index afd4e48a7..77a3efea2 100644 --- a/console/console-sink/src/main/java/com/dtstack/flink/sql/sink/console/ConsoleSink.java +++ b/console/console-sink/src/main/java/com/dtstack/flink/sql/sink/console/ConsoleSink.java @@ -19,13 +19,12 @@ package com.dtstack.flink.sql.sink.console; import com.dtstack.flink.sql.sink.IStreamSinkGener; -import com.dtstack.flink.sql.table.AbstractTargetTableInfo; +import com.dtstack.flink.sql.table.TargetTableInfo; import org.apache.flink.api.common.typeinfo.TypeInformation; import org.apache.flink.api.java.tuple.Tuple2; import org.apache.flink.api.java.typeutils.RowTypeInfo; import org.apache.flink.api.java.typeutils.TupleTypeInfo; import org.apache.flink.streaming.api.datastream.DataStream; -import org.apache.flink.streaming.api.datastream.DataStreamSink; import org.apache.flink.streaming.api.functions.sink.OutputFormatSinkFunction; import org.apache.flink.streaming.api.functions.sink.RichSinkFunction; import org.apache.flink.table.sinks.RetractStreamTableSink; @@ -72,23 +71,16 @@ public TypeInformation[] getFieldTypes() { @Override public void emitDataStream(DataStream> dataStream) { - // flink 1.9 use consumeDataStream - consumeDataStream(dataStream); - } - - @Override - public ConsoleSink genStreamSink(AbstractTargetTableInfo targetTableInfo) { - return this; - } - - @Override - public DataStreamSink> consumeDataStream(DataStream> dataStream) { ConsoleOutputFormat.ConsoleOutputFormatBuilder builder = ConsoleOutputFormat.buildOutputFormat(); builder.setFieldNames(this.fieldNames) .setFieldTypes(this.fieldTypes); ConsoleOutputFormat outputFormat = builder.finish(); RichSinkFunction richSinkFunction = new OutputFormatSinkFunction(outputFormat); - DataStreamSink dataStreamSink = dataStream.addSink(richSinkFunction); - return dataStreamSink; + dataStream.addSink(richSinkFunction); + } + + @Override + public ConsoleSink genStreamSink(TargetTableInfo targetTableInfo) { + return this; } } diff --git a/console/console-sink/src/main/java/com/dtstack/flink/sql/sink/console/table/ConsoleSinkParser.java b/console/console-sink/src/main/java/com/dtstack/flink/sql/sink/console/table/ConsoleSinkParser.java index 93ed02420..e77444bfd 100644 --- a/console/console-sink/src/main/java/com/dtstack/flink/sql/sink/console/table/ConsoleSinkParser.java +++ b/console/console-sink/src/main/java/com/dtstack/flink/sql/sink/console/table/ConsoleSinkParser.java @@ -18,13 +18,13 @@ package com.dtstack.flink.sql.sink.console.table; -import com.dtstack.flink.sql.table.AbstractTableParser; -import com.dtstack.flink.sql.table.AbstractTableInfo; +import com.dtstack.flink.sql.table.AbsTableParser; +import com.dtstack.flink.sql.table.TableInfo; import com.dtstack.flink.sql.util.MathUtil; import java.util.Map; -import static com.dtstack.flink.sql.table.AbstractTableInfo.PARALLELISM_KEY; +import static com.dtstack.flink.sql.table.TableInfo.PARALLELISM_KEY; /** * Reason: @@ -32,9 +32,9 @@ * * @author xuqianjin */ -public class ConsoleSinkParser extends AbstractTableParser { +public class ConsoleSinkParser extends AbsTableParser { @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { + public TableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { ConsoleTableInfo consoleTableInfo = new ConsoleTableInfo(); consoleTableInfo.setName(tableName); parseFieldsInfo(fieldsInfo, consoleTableInfo); diff --git a/console/console-sink/src/main/java/com/dtstack/flink/sql/sink/console/table/ConsoleTableInfo.java b/console/console-sink/src/main/java/com/dtstack/flink/sql/sink/console/table/ConsoleTableInfo.java index 6fd7063c6..4b286c667 100644 --- a/console/console-sink/src/main/java/com/dtstack/flink/sql/sink/console/table/ConsoleTableInfo.java +++ b/console/console-sink/src/main/java/com/dtstack/flink/sql/sink/console/table/ConsoleTableInfo.java @@ -18,7 +18,7 @@ package com.dtstack.flink.sql.sink.console.table; -import com.dtstack.flink.sql.table.AbstractTargetTableInfo; +import com.dtstack.flink.sql.table.TargetTableInfo; /** * Reason: @@ -26,7 +26,7 @@ * * @author xuqianjin */ -public class ConsoleTableInfo extends AbstractTargetTableInfo { +public class ConsoleTableInfo extends TargetTableInfo { private static final String CURR_TYPE = "console"; diff --git a/console/console-sink/src/main/java/com/dtstack/flink/sql/sink/console/table/TablePrintUtil.java b/console/console-sink/src/main/java/com/dtstack/flink/sql/sink/console/table/TablePrintUtil.java index 12bb2a5d4..8813da619 100644 --- a/console/console-sink/src/main/java/com/dtstack/flink/sql/sink/console/table/TablePrintUtil.java +++ b/console/console-sink/src/main/java/com/dtstack/flink/sql/sink/console/table/TablePrintUtil.java @@ -22,7 +22,6 @@ public class TablePrintUtil { public static final int ALIGN_LEFT = 1;//左对齐 public static final int ALIGN_RIGHT = 2;//右对齐 public static final int ALIGN_CENTER = 3;//居中对齐 - private static final Pattern PATTERN = Pattern.compile("[\u4e00-\u9fa5]"); private int align = ALIGN_CENTER;//默认居中对齐 private boolean equilong = false;//默认不等宽 @@ -59,9 +58,7 @@ public static TablePrintUtil build(String[][] data) { public static TablePrintUtil build(List data) { TablePrintUtil self = new TablePrintUtil(); self.data = new ArrayList<>(); - if (data.size() <= 0) { - throw new RuntimeException("数据源至少得有一行吧"); - } + if (data.size() <= 0) throw new RuntimeException("数据源至少得有一行吧"); Object obj = data.get(0); @@ -73,9 +70,7 @@ public static TablePrintUtil build(List data) { int length = ((List) obj).size(); for (Object item : data) { List col = (List) item; - if (col.size() != length) { - throw new RuntimeException("数据源每列长度必须一致"); - } + if (col.size() != length) throw new RuntimeException("数据源每列长度必须一致"); self.data.add(col.toArray(new String[length])); } } else { @@ -95,7 +90,7 @@ public static TablePrintUtil build(List data) { try { value = obj.getClass().getMethod(colList.get(j).getMethodName).invoke(data.get(i)).toString(); } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { - LOG.error("", e); + e.printStackTrace(); } item[j] = value == null ? "null" : value; } @@ -120,7 +115,7 @@ private static List getColList(Object obj) { Method[] methods = obj.getClass().getMethods(); for (Method m : methods) { StringBuilder getMethodName = new StringBuilder(m.getName()); - if ("get".equals(getMethodName.substring(0, 3)) && !"getClass".equals(m.getName())) { + if (getMethodName.substring(0, 3).equals("get") && !m.getName().equals("getClass")) { Col col = new Col(); col.getMethodName = getMethodName.toString(); char first = Character.toLowerCase(getMethodName.delete(0, 3).charAt(0)); @@ -139,8 +134,8 @@ private static List getColList(Object obj) { * @return */ private int getStringCharLength(String str) { - //利用正则找到中文 - Matcher m = PATTERN.matcher(str); + Pattern p = Pattern.compile("[\u4e00-\u9fa5]");//利用正则找到中文 + Matcher m = p.matcher(str); int count = 0; while (m.find()) { count++; @@ -168,9 +163,7 @@ private int[] getColLengths() { if (equilong) {//如果等宽表格 int max = 0; for (int len : result) { - if (len > max) { - max = len; - } + if (len > max) max = len; } for (int i = 0; i < result.length; i++) { result[i] = max; @@ -220,8 +213,6 @@ public String getTableString() { sb.append(cell); for (int i = 0; i < right + padding; i++) {sb.append(s);} break; - default: - break; } sb.append(v); } diff --git a/console/console-sink/src/test/java/com/dtstack/flink/sql/sink/console/ConsoleOutputFormatTest.java b/console/console-sink/src/test/java/com/dtstack/flink/sql/sink/console/ConsoleOutputFormatTest.java deleted file mode 100644 index bec295cab..000000000 --- a/console/console-sink/src/test/java/com/dtstack/flink/sql/sink/console/ConsoleOutputFormatTest.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.dtstack.flink.sql.sink.console; - -import com.dtstack.flink.sql.sink.console.table.TablePrintUtil; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.metrics.Counter; -import org.apache.flink.types.Row; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import org.powermock.reflect.Whitebox; - -import java.io.IOException; - -import static org.mockito.ArgumentMatchers.*; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.when; - -/** - * @program: flink.sql - * @description: - * @author: wuren - * @create: 2020-06-16 20:43 - **/ -@RunWith(PowerMockRunner. class) -@PrepareForTest({TablePrintUtil.class }) -public class ConsoleOutputFormatTest { - - @Mock - Counter counter; - - ConsoleOutputFormat.ConsoleOutputFormatBuilder builder; - - ConsoleOutputFormat consoleOutputFormat; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - builder = ConsoleOutputFormat.buildOutputFormat(); - String[] fieldNames = new String[]{"id", "name"}; - TypeInformation[] fieldTypes = new TypeInformation[]{ - TypeInformation.of(Integer.class), - TypeInformation.of(String.class) - }; - builder - .setFieldNames(fieldNames) - .setFieldTypes(fieldTypes); - consoleOutputFormat = builder.finish(); - } - - @Test - public void testWriteRecord() throws IOException { - Row row = Row.of(1, "foo_name"); - Tuple2 tuple = Tuple2.of(true, row); - doNothing().when(counter).inc(); -// PowerMockito.mockStatic(TablePrintUtil.class); -// TablePrintUtil printUtilMock = Whitebox.newInstance(TablePrintUtil.class); -// Whitebox.newInstance(printUtilMock, "print") -// TablePrintUtil printUtilMock = PowerMockito.mock(TablePrintUtil.class); -// PowerMockito.doNothing().when(printUtilMock).print(); -// PowerMockito.when(TablePrintUtil.build((String[][]) any())).thenReturn(printUtilMock); -// TablePrintUtil.build((String[][]) null); - consoleOutputFormat.outRecords = counter; - consoleOutputFormat.writeRecord(tuple); - } - -} diff --git a/console/console-sink/src/test/java/com/dtstack/flink/sql/sink/console/ConsoleSinkTest.java b/console/console-sink/src/test/java/com/dtstack/flink/sql/sink/console/ConsoleSinkTest.java deleted file mode 100644 index 711cc426a..000000000 --- a/console/console-sink/src/test/java/com/dtstack/flink/sql/sink/console/ConsoleSinkTest.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.dtstack.flink.sql.sink.console; - -/** - * @program: flink.sql - * @description: - * @author: wuren - * @create: 2020-06-16 20:18 - **/ -public class ConsoleSinkTest { -} diff --git a/console/console-sink/src/test/java/com/dtstack/flink/sql/sink/console/table/ConsoleSinkParserTest.java b/console/console-sink/src/test/java/com/dtstack/flink/sql/sink/console/table/ConsoleSinkParserTest.java deleted file mode 100644 index 756db6a6c..000000000 --- a/console/console-sink/src/test/java/com/dtstack/flink/sql/sink/console/table/ConsoleSinkParserTest.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.dtstack.flink.sql.sink.console.table; - -import com.dtstack.flink.sql.table.AbstractTableInfo; -import org.junit.Assert; -import org.junit.Test; - -import java.util.HashMap; -import java.util.Map; - -public class ConsoleSinkParserTest { - - @Test - public void getTableInfo() { - ConsoleSinkParser sinkParser = new ConsoleSinkParser(); - - final String tableName = "table_foo"; - final String fieldsInfo = "id INT, name VARCHAR"; - - Map props = new HashMap(); - props.put("url", "jdbc:mysql://foo:3306/db_foo"); - props.put("tablename", "table_foo"); - props.put("username", "foo"); - props.put("password", "foo"); - - AbstractTableInfo tableInfo= sinkParser.getTableInfo(tableName, fieldsInfo, props); - - final String table_type = tableInfo.getName(); - Assert.assertTrue(tableName.equals(table_type)); - } - -} \ No newline at end of file diff --git a/console/console-sink/src/test/java/com/dtstack/flink/sql/sink/console/table/ConsoleTableInfoTest.java b/console/console-sink/src/test/java/com/dtstack/flink/sql/sink/console/table/ConsoleTableInfoTest.java deleted file mode 100644 index 8cb1a5792..000000000 --- a/console/console-sink/src/test/java/com/dtstack/flink/sql/sink/console/table/ConsoleTableInfoTest.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.dtstack.flink.sql.sink.console.table; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -/** - * @program: flink.sql - * @description: - * @author: wuren - * @create: 2020-06-16 20:18 - **/ -public class ConsoleTableInfoTest { - private ConsoleTableInfo consoleTableInfo; - @Before - public void setUp() { - consoleTableInfo = new ConsoleTableInfo(); - } - - @Test - public void testCheck() { - Boolean b = consoleTableInfo.check(); - Assert.assertTrue(b == true); - } - - @Test - public void testGetType() { - String r = consoleTableInfo.getType(); - Assert.assertTrue("console".equals(r)); - } -} diff --git a/console/console-sink/src/test/java/com/dtstack/flink/sql/sink/console/table/TablePrintUtilTest.java b/console/console-sink/src/test/java/com/dtstack/flink/sql/sink/console/table/TablePrintUtilTest.java deleted file mode 100644 index af5582d29..000000000 --- a/console/console-sink/src/test/java/com/dtstack/flink/sql/sink/console/table/TablePrintUtilTest.java +++ /dev/null @@ -1,124 +0,0 @@ -package com.dtstack.flink.sql.sink.console.table; - -import com.google.common.collect.Lists; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.powermock.reflect.Whitebox; - -import java.util.ArrayList; -import java.util.List; - -public class TablePrintUtilTest { - - TablePrintUtil tablePrintUtil; - - @Before - public void setUp() { - List data = new ArrayList<>(); - String[] fieldNames = new String[] {"id", "name"}; - data.add(fieldNames); - String[] recordStr = new String[] {"1", "foo_name"}; - data.add(recordStr); - tablePrintUtil = TablePrintUtil.build(data); - } - - @Test - public void testBuild() { - List data = Whitebox.getInternalState(tablePrintUtil, "data"); - String[] tableHead = data.get(0); - String[] tableBody = data.get(1); - Assert.assertTrue("id".equals(tableHead[0])); - Assert.assertTrue("name".equals(tableHead[1])); - Assert.assertTrue("1".equals(tableBody[0])); - Assert.assertTrue("foo_name".equals(tableBody[1])); - } - - @Test - public void testGetTableString() { - String s = tablePrintUtil.getTableString(); - final String normal = - "+----+----------+\r\n" + - "| id | name |\r\n" + - "+----+----------+\r\n" + - "| 1 | foo_name |\r\n" + - "+----+----------+\r\n"; - Assert.assertTrue(normal.equals(s)); - } - - @Test - public void testGetTableString2() { -// List data1 = new ArrayList<>(); -// data1.add(new String[]{"用户名", "密码", "姓名"}); -// data1.add(new String[]{"xiaoming", "xm123", "小明"}); -// data1.add(new String[]{"xiaohong", "xh123", "小红"}); -// TablePrintUtil.build(data1).print(); - - List> data2 = new ArrayList<>(); - - data2.add( - Lists.newArrayList("用户名", "密码", "姓名") - ); - data2.add( - Lists.newArrayList("xiaoming", "xm123", "小明") - ); - data2.add( - Lists.newArrayList("xiaohong", "xh123", "小红") - ); - - TablePrintUtil printUtil = TablePrintUtil.build(data2) - .setAlign(TablePrintUtil.ALIGN_LEFT) - .setPadding(5) - .setEquilong(true); - final String normal = - "+------------------+------------------+------------------+\r\n" + - "| 用户名 | 密码 | 姓名 |\r\n" + - "+------------------+------------------+------------------+\r\n" + - "| xiaoming | xm123 | 小明 |\r\n" + - "+------------------+------------------+------------------+\r\n" + - "| xiaohong | xh123 | 小红 |\r\n" + - "+------------------+------------------+------------------+\r\n" - ; - String s = printUtil.getTableString(); - Assert.assertTrue(normal.equals(s)); - - } - - @Test - public void testGetTableString3() { - - class User { - String name; - - User(String name) { - this.name = name; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - } - List data3 = new ArrayList<>(); - data3.add(new User("xiaoming")); - data3.add(new User("xiaohong")); - TablePrintUtil printUtil = TablePrintUtil.build(data3) - .setAlign(TablePrintUtil.ALIGN_RIGHT) - .setH('=') - .setV('!'); - - final String normal = - "+==========+\r\n" + - "! name !\r\n" + - "+==========+\r\n" + - "! xiaoming !\r\n" + - "+==========+\r\n" + - "! xiaohong !\r\n" + - "+==========+\r\n"; - String s = printUtil.getTableString(); - Assert.assertTrue(normal.equals(s)); - } -} \ No newline at end of file diff --git a/core/src/main/java/com/dtstack/flink/sql/enums/EStateBackend.java b/console/console-sink/src/test/java/com/dtstack/flinkx/AppTest.java similarity index 60% rename from core/src/main/java/com/dtstack/flink/sql/enums/EStateBackend.java rename to console/console-sink/src/test/java/com/dtstack/flinkx/AppTest.java index 098cb57fe..e03e5451f 100644 --- a/core/src/main/java/com/dtstack/flink/sql/enums/EStateBackend.java +++ b/console/console-sink/src/test/java/com/dtstack/flinkx/AppTest.java @@ -16,34 +16,43 @@ * limitations under the License. */ -package com.dtstack.flink.sql.enums; + + +package com.dtstack.flinkx; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; /** - * Flink状态后端类型 - * Date: 2019/11/15 - * Company: www.dtstack.com - * @author maqi + * Unit test for simple App. */ -public enum EStateBackend { +public class AppTest + extends TestCase +{ /** - * memory + * Create the test case + * + * @param testName name of the test case */ - MEMORY, + public AppTest(String testName ) + { + super( testName ); + } + /** - * rockdb + * @return the suite of tests being tested */ - ROCKSDB, + public static Test suite() + { + return new TestSuite( AppTest.class ); + } + /** - * filesystem + * Rigourous Test :-) */ - FILESYSTEM; - - public static EStateBackend convertFromString(String type) { - if(type == null) { - throw new RuntimeException("null StateBackend!"); - } - return valueOf(type.toUpperCase()); + public void testApp() + { + assertTrue( true ); } } - - diff --git a/console/pom.xml b/console/pom.xml index 5b2b162e9..983e1c185 100644 --- a/console/pom.xml +++ b/console/pom.xml @@ -16,6 +16,12 @@ + + junit + junit + 3.8.1 + test + com.dtstack.flink sql.core diff --git a/core/pom.xml b/core/pom.xml index c11662f0a..c357b4c99 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -17,34 +17,26 @@ UTF-8 core - 2.11.3 - 19.0 - 1.0.0-SNAPSHOT + 1.16.0 - - org.apache.flink - flink-table-common - ${flink.version} - - - - org.apache.flink - flink-table-api-java-bridge_2.11 - ${flink.version} + junit + junit + 4.12 + test - org.apache.flink - flink-table-planner-blink_2.11 - ${flink.version} + joda-time + joda-time + 2.5 org.apache.flink - flink-table-runtime-blink_2.11 + flink-core ${flink.version} @@ -60,53 +52,47 @@ ${flink.version} - + org.apache.flink - flink-statebackend-rocksdb_2.11 + flink-table-planner_2.11 ${flink.version} - com.fasterxml.jackson.core - jackson-databind - ${jackson.version} + org.apache.flink + flink-table-common + ${flink.version} - com.google.guava - guava - ${guava.version} + org.apache.calcite + calcite-server + + ${calcite.server.version} org.apache.flink - flink-shaded-hadoop2 - 2.7.5-1.8.1 + flink-cep-scala_2.11 + ${flink.version} - junit - junit - 4.12 - test + org.apache.flink + flink-scala_2.11 + ${flink.version} - joda-time - joda-time - 2.5 + org.apache.flink + flink-yarn_2.11 + ${flink.version} @@ -122,40 +108,21 @@ org.apache.maven.plugins - maven-shade-plugin - 3.1.0 - - - package - - shade - - - false - - - com.dtstack.flink.sql.Main - - - - - com.fasterxml.jackson.* - com.google.guava - - - - - *:* - - META-INF/*.SF - META-INF/*.DSA - META-INF/*.RSA - - - - - - + maven-jar-plugin + + target/classes/ + + + + com.dtstack.flink.sql.Main + + false + + + . + + + @@ -171,31 +138,20 @@ - + - - + - - org.apache.maven.plugins - maven-jar-plugin - - - - test-jar - - - - + diff --git a/core/src/main/java/com/dtstack/flink/sql/GetPlan.java b/core/src/main/java/com/dtstack/flink/sql/GetPlan.java deleted file mode 100644 index 91f486a21..000000000 --- a/core/src/main/java/com/dtstack/flink/sql/GetPlan.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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 com.dtstack.flink.sql; - -import com.dtstack.flink.sql.exec.ApiResult; -import com.dtstack.flink.sql.exec.ExecuteProcessHelper; -import com.dtstack.flink.sql.exec.ParamsInfo; -import org.apache.commons.lang.exception.ExceptionUtils; -import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.net.URL; -import java.net.URLClassLoader; - -/** - * local模式获取sql任务的执行计划 - * Date: 2020/2/17 - * Company: www.dtstack.com - * - * @author maqi - */ -public class GetPlan { - - private static final Logger LOG = LoggerFactory.getLogger(GetPlan.class); - - public static String getExecutionPlan(String[] args) { - ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader(); - try { - long start = System.currentTimeMillis(); - ParamsInfo paramsInfo = ExecuteProcessHelper.parseParams(args); - paramsInfo.setGetPlan(true); - ClassLoader envClassLoader = StreamExecutionEnvironment.class.getClassLoader(); - ClassLoader plannerClassLoader = URLClassLoader.newInstance( - paramsInfo.getJarUrlList().toArray(new URL[0]), - envClassLoader); - Thread.currentThread().setContextClassLoader(plannerClassLoader); - StreamExecutionEnvironment env = ExecuteProcessHelper.getStreamExecution(paramsInfo); - String executionPlan = env.getExecutionPlan(); - long end = System.currentTimeMillis(); - return ApiResult.createSuccessResultJsonStr(executionPlan, end - start); - } catch (Exception e) { - LOG.error("Get plan error", e); - return ApiResult.createErrorResultJsonStr(ExceptionUtils.getFullStackTrace(e)); - } finally { - Thread.currentThread().setContextClassLoader(currentClassLoader); - } - } -} diff --git a/core/src/main/java/com/dtstack/flink/sql/Main.java b/core/src/main/java/com/dtstack/flink/sql/Main.java index 5d7528869..a08df9b05 100644 --- a/core/src/main/java/com/dtstack/flink/sql/Main.java +++ b/core/src/main/java/com/dtstack/flink/sql/Main.java @@ -17,15 +17,74 @@ */ -package com.dtstack.flink.sql; - +package com.dtstack.flink.sql; -import com.dtstack.flink.sql.exec.ExecuteProcessHelper; -import com.dtstack.flink.sql.exec.ParamsInfo; +import com.dtstack.flink.sql.config.CalciteConfig; +import com.dtstack.flink.sql.classloader.ClassLoaderManager; +import com.dtstack.flink.sql.constrant.ConfigConstrant; +import com.dtstack.flink.sql.enums.ClusterMode; +import com.dtstack.flink.sql.enums.ECacheType; +import com.dtstack.flink.sql.enums.EPluginLoadMode; +import com.dtstack.flink.sql.environment.MyLocalStreamEnvironment; +import com.dtstack.flink.sql.exec.FlinkSQLExec; +import com.dtstack.flink.sql.option.OptionParser; +import com.dtstack.flink.sql.parser.CreateFuncParser; +import com.dtstack.flink.sql.parser.CreateTmpTableParser; +import com.dtstack.flink.sql.parser.InsertSqlParser; +import com.dtstack.flink.sql.parser.SqlParser; +import com.dtstack.flink.sql.parser.SqlTree; +import com.dtstack.flink.sql.side.SideSqlExec; +import com.dtstack.flink.sql.side.SideTableInfo; +import com.dtstack.flink.sql.table.SourceTableInfo; +import com.dtstack.flink.sql.table.TableInfo; +import com.dtstack.flink.sql.table.TargetTableInfo; +import com.dtstack.flink.sql.sink.StreamSinkFactory; +import com.dtstack.flink.sql.source.StreamSourceFactory; +import com.dtstack.flink.sql.util.DtStringUtil; +import com.dtstack.flink.sql.util.PropertiesUtils; +import com.dtstack.flink.sql.watermarker.WaterMarkerAssigner; +import com.dtstack.flink.sql.util.FlinkUtil; +import com.dtstack.flink.sql.util.PluginUtil; +import org.apache.calcite.sql.SqlInsert; +import org.apache.calcite.sql.SqlNode; +import org.apache.commons.io.Charsets; +import org.apache.commons.lang3.StringUtils; +import org.apache.flink.api.common.ExecutionConfig; +import org.apache.flink.api.common.restartstrategy.RestartStrategies; +import org.apache.flink.api.common.time.Time; +import org.apache.flink.api.common.typeinfo.TypeInformation; +import org.apache.flink.api.java.tuple.Tuple2; +import org.apache.flink.api.java.typeutils.RowTypeInfo; +import org.apache.flink.client.program.ContextEnvironment; +import org.apache.flink.configuration.Configuration; +import com.google.common.base.Strings; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.flink.streaming.api.datastream.DataStream; +import org.apache.flink.streaming.api.environment.StreamContextEnvironment; import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; +import org.apache.flink.table.api.Table; +import org.apache.flink.table.api.java.StreamTableEnvironment; +import org.apache.flink.table.sinks.TableSink; +import org.apache.flink.types.Row; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.File; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.net.URLDecoder; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import com.dtstack.flink.sql.option.Options; /** * Date: 2018/6/26 @@ -34,12 +93,259 @@ */ public class Main { + + private static final String CLASS_FILE_NAME_FMT = "class_path_%d"; + + private static final ObjectMapper objMapper = new ObjectMapper(); + private static final Logger LOG = LoggerFactory.getLogger(Main.class); + public static void main(String[] args) throws Exception { - ParamsInfo paramsInfo = ExecuteProcessHelper.parseParams(args); - StreamExecutionEnvironment env = ExecuteProcessHelper.getStreamExecution(paramsInfo); - env.execute(paramsInfo.getName()); - LOG.info("program {} execution success", paramsInfo.getName()); + + OptionParser optionParser = new OptionParser(args); + Options options = optionParser.getOptions(); + String sql = options.getSql(); + String name = options.getName(); + String addJarListStr = options.getAddjar(); + String localSqlPluginPath = options.getLocalSqlPluginPath(); + String remoteSqlPluginPath = options.getRemoteSqlPluginPath(); + String pluginLoadMode = options.getPluginLoadMode(); + String deployMode = options.getMode(); + String confProp = options.getConfProp(); + + sql = URLDecoder.decode(sql, Charsets.UTF_8.name()); + SqlParser.setLocalSqlPluginRoot(localSqlPluginPath); + + List addJarFileList = Lists.newArrayList(); + if(!Strings.isNullOrEmpty(addJarListStr)){ + addJarListStr = URLDecoder.decode(addJarListStr, Charsets.UTF_8.name()); + addJarFileList = objMapper.readValue(addJarListStr, List.class); + } + + confProp = URLDecoder.decode(confProp, Charsets.UTF_8.toString()); + Properties confProperties = PluginUtil.jsonStrToObject(confProp, Properties.class); + StreamExecutionEnvironment env = getStreamExeEnv(confProperties, deployMode); + StreamTableEnvironment tableEnv = StreamTableEnvironment.getTableEnvironment(env); + + List jarURList = Lists.newArrayList(); + SqlTree sqlTree = SqlParser.parseSql(sql); + + //Get External jar to load + for(String addJarPath : addJarFileList){ + File tmpFile = new File(addJarPath); + jarURList.add(tmpFile.toURI().toURL()); + } + + Map sideTableMap = Maps.newHashMap(); + Map registerTableCache = Maps.newHashMap(); + + //register udf + registerUDF(sqlTree, jarURList, tableEnv); + //register table schema + registerTable(sqlTree, env, tableEnv, localSqlPluginPath, remoteSqlPluginPath, pluginLoadMode, sideTableMap, registerTableCache); + + sqlTranslation(localSqlPluginPath, tableEnv,sqlTree,sideTableMap,registerTableCache); + + if(env instanceof MyLocalStreamEnvironment) { + ((MyLocalStreamEnvironment) env).setClasspaths(ClassLoaderManager.getClassPath()); + } + + env.execute(name); + } + + private static void sqlTranslation(String localSqlPluginPath, StreamTableEnvironment tableEnv,SqlTree sqlTree,Map sideTableMap,Map registerTableCache) throws Exception { + SideSqlExec sideSqlExec = new SideSqlExec(); + sideSqlExec.setLocalSqlPluginPath(localSqlPluginPath); + for (CreateTmpTableParser.SqlParserResult result : sqlTree.getTmpSqlList()) { + sideSqlExec.registerTmpTable(result, sideTableMap, tableEnv, registerTableCache); + } + + for (InsertSqlParser.SqlParseResult result : sqlTree.getExecSqlList()) { + if(LOG.isInfoEnabled()){ + LOG.info("exe-sql:\n" + result.getExecSql()); + } + boolean isSide = false; + for (String tableName : result.getTargetTableList()) { + if (sqlTree.getTmpTableMap().containsKey(tableName)) { + CreateTmpTableParser.SqlParserResult tmp = sqlTree.getTmpTableMap().get(tableName); + String realSql = DtStringUtil.replaceIgnoreQuota(result.getExecSql(), "`", ""); + + SqlNode sqlNode = org.apache.calcite.sql.parser.SqlParser.create(realSql, CalciteConfig.MYSQL_LEX_CONFIG).parseStmt(); + String tmpSql = ((SqlInsert) sqlNode).getSource().toString(); + tmp.setExecSql(tmpSql); + sideSqlExec.registerTmpTable(tmp, sideTableMap, tableEnv, registerTableCache); + } else { + for(String sourceTable : result.getSourceTableList()){ + if(sideTableMap.containsKey(sourceTable)){ + isSide = true; + break; + } + } + if(isSide){ + //sql-dimensional table contains the dimension table of execution + sideSqlExec.exec(result.getExecSql(), sideTableMap, tableEnv, registerTableCache); + }else{ + FlinkSQLExec.sqlUpdate(tableEnv, result.getExecSql()); + if(LOG.isInfoEnabled()){ + LOG.info("exec sql: " + result.getExecSql()); + } + } + } + } + } + + + } + /** + * This part is just to add classpath for the jar when reading remote execution, and will not submit jar from a local + * @param env + * @param classPathSet + * @throws NoSuchFieldException + * @throws IllegalAccessException + */ + private static void addEnvClassPath(StreamExecutionEnvironment env, Set classPathSet) throws NoSuchFieldException, IllegalAccessException { + if(env instanceof StreamContextEnvironment){ + Field field = env.getClass().getDeclaredField("ctx"); + field.setAccessible(true); + ContextEnvironment contextEnvironment= (ContextEnvironment) field.get(env); + for(URL url : classPathSet){ + contextEnvironment.getClasspaths().add(url); + } + } } + + private static void registerUDF(SqlTree sqlTree, List jarURList, StreamTableEnvironment tableEnv) + throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { + //register urf + // udf和tableEnv须由同一个类加载器加载 + ClassLoader levelClassLoader = tableEnv.getClass().getClassLoader(); + URLClassLoader classLoader = null; + List funcList = sqlTree.getFunctionList(); + for (CreateFuncParser.SqlParserResult funcInfo : funcList) { + //classloader + if (classLoader == null) { + classLoader = FlinkUtil.loadExtraJar(jarURList, (URLClassLoader)levelClassLoader); + } + FlinkUtil.registerUDF(funcInfo.getType(), funcInfo.getClassName(), funcInfo.getName(), tableEnv, classLoader); + } + } + + + private static void registerTable(SqlTree sqlTree, StreamExecutionEnvironment env, StreamTableEnvironment tableEnv, String localSqlPluginPath, + String remoteSqlPluginPath, String pluginLoadMode, Map sideTableMap, Map registerTableCache) throws Exception { + Set classPathSet = Sets.newHashSet(); + WaterMarkerAssigner waterMarkerAssigner = new WaterMarkerAssigner(); + for (TableInfo tableInfo : sqlTree.getTableInfoMap().values()) { + + if (tableInfo instanceof SourceTableInfo) { + + SourceTableInfo sourceTableInfo = (SourceTableInfo) tableInfo; + Table table = StreamSourceFactory.getStreamSource(sourceTableInfo, env, tableEnv, localSqlPluginPath); + tableEnv.registerTable(sourceTableInfo.getAdaptName(), table); + //Note --- parameter conversion function can not be used inside a function of the type of polymerization + //Create table in which the function is arranged only need adaptation sql + String adaptSql = sourceTableInfo.getAdaptSelectSql(); + Table adaptTable = adaptSql == null ? table : tableEnv.sqlQuery(adaptSql); + + RowTypeInfo typeInfo = new RowTypeInfo(adaptTable.getSchema().getTypes(), adaptTable.getSchema().getColumnNames()); + DataStream adaptStream = tableEnv.toRetractStream(adaptTable, typeInfo) + .map((Tuple2 f0) -> { return f0.f1; }) + .returns(typeInfo); + + String fields = String.join(",", typeInfo.getFieldNames()); + + if(waterMarkerAssigner.checkNeedAssignWaterMarker(sourceTableInfo)){ + adaptStream = waterMarkerAssigner.assignWaterMarker(adaptStream, typeInfo, sourceTableInfo); + fields += ",ROWTIME.ROWTIME"; + }else{ + fields += ",PROCTIME.PROCTIME"; + } + + Table regTable = tableEnv.fromDataStream(adaptStream, fields); + tableEnv.registerTable(tableInfo.getName(), regTable); + if(LOG.isInfoEnabled()){ + LOG.info("registe table {} success.", tableInfo.getName()); + } + registerTableCache.put(tableInfo.getName(), regTable); + classPathSet.add(buildSourceAndSinkPathByLoadMode(tableInfo.getType(), SourceTableInfo.SOURCE_SUFFIX, localSqlPluginPath, remoteSqlPluginPath, pluginLoadMode)); + } else if (tableInfo instanceof TargetTableInfo) { + + TableSink tableSink = StreamSinkFactory.getTableSink((TargetTableInfo) tableInfo, localSqlPluginPath); + TypeInformation[] flinkTypes = FlinkUtil.transformTypes(tableInfo.getFieldClasses()); + tableEnv.registerTableSink(tableInfo.getName(), tableInfo.getFields(), flinkTypes, tableSink); + classPathSet.add(buildSourceAndSinkPathByLoadMode(tableInfo.getType(), TargetTableInfo.TARGET_SUFFIX, localSqlPluginPath, remoteSqlPluginPath, pluginLoadMode)); + } else if(tableInfo instanceof SideTableInfo){ + + String sideOperator = ECacheType.ALL.name().equals(((SideTableInfo) tableInfo).getCacheType()) ? "all" : "async"; + sideTableMap.put(tableInfo.getName(), (SideTableInfo) tableInfo); + classPathSet.add(buildSidePathByLoadMode(tableInfo.getType(), sideOperator, SideTableInfo.TARGET_SUFFIX, localSqlPluginPath, remoteSqlPluginPath, pluginLoadMode)); + }else { + throw new RuntimeException("not support table type:" + tableInfo.getType()); + } + } + + //The plug-in information corresponding to the table is loaded into the classPath env + addEnvClassPath(env, classPathSet); + int i = 0; + for(URL url : classPathSet){ + String classFileName = String.format(CLASS_FILE_NAME_FMT, i); + env.registerCachedFile(url.getPath(), classFileName, true); + i++; + } + } + + private static URL buildSourceAndSinkPathByLoadMode(String type, String suffix, String localSqlPluginPath, String remoteSqlPluginPath, String pluginLoadMode) throws Exception { + if (StringUtils.equalsIgnoreCase(pluginLoadMode, EPluginLoadMode.CLASSPATH.name())) { + return PluginUtil.getRemoteJarFilePath(type, suffix, remoteSqlPluginPath, localSqlPluginPath); + } + return PluginUtil.getLocalJarFilePath(type, suffix, localSqlPluginPath); + } + + private static URL buildSidePathByLoadMode(String type, String operator, String suffix, String localSqlPluginPath, String remoteSqlPluginPath, String pluginLoadMode) throws Exception { + if (StringUtils.equalsIgnoreCase(pluginLoadMode, EPluginLoadMode.CLASSPATH.name())) { + return PluginUtil.getRemoteSideJarFilePath(type, operator, suffix, remoteSqlPluginPath, localSqlPluginPath); + } + return PluginUtil.getLocalSideJarFilePath(type, operator, suffix, localSqlPluginPath); + } + + private static StreamExecutionEnvironment getStreamExeEnv(Properties confProperties, String deployMode) throws Exception { + confProperties = PropertiesUtils.propertiesTrim(confProperties); + + StreamExecutionEnvironment env = !ClusterMode.local.name().equals(deployMode) ? + StreamExecutionEnvironment.getExecutionEnvironment() : + new MyLocalStreamEnvironment(); + env.getConfig().disableClosureCleaner(); + env.setParallelism(FlinkUtil.getEnvParallelism(confProperties)); + + Configuration globalJobParameters = new Configuration(); + //Configuration unsupported set properties key-value + Method method = Configuration.class.getDeclaredMethod("setValueInternal", String.class, Object.class); + method.setAccessible(true); + for (Map.Entry prop : confProperties.entrySet()) { + method.invoke(globalJobParameters, prop.getKey(), prop.getValue()); + } + + ExecutionConfig exeConfig = env.getConfig(); + if(exeConfig.getGlobalJobParameters() == null){ + exeConfig.setGlobalJobParameters(globalJobParameters); + }else if(exeConfig.getGlobalJobParameters() instanceof Configuration){ + ((Configuration) exeConfig.getGlobalJobParameters()).addAll(globalJobParameters); + } + if(FlinkUtil.getMaxEnvParallelism(confProperties) > 0){ + env.setMaxParallelism(FlinkUtil.getMaxEnvParallelism(confProperties)); + } + if(FlinkUtil.getBufferTimeoutMillis(confProperties) > 0){ + env.setBufferTimeout(FlinkUtil.getBufferTimeoutMillis(confProperties)); + } + env.setRestartStrategy(RestartStrategies.failureRateRestart( + ConfigConstrant.failureRate, + Time.of(ConfigConstrant.failureInterval, TimeUnit.MINUTES), + Time.of(ConfigConstrant.delayInterval, TimeUnit.SECONDS) + )); + FlinkUtil.setStreamTimeCharacteristic(env, confProperties); + FlinkUtil.openCheckpoint(env, confProperties); + return env; + } + } diff --git a/core/src/main/java/com/dtstack/flink/sql/classloader/ClassLoaderManager.java b/core/src/main/java/com/dtstack/flink/sql/classloader/ClassLoaderManager.java index 3f1165e40..6db1058e5 100644 --- a/core/src/main/java/com/dtstack/flink/sql/classloader/ClassLoaderManager.java +++ b/core/src/main/java/com/dtstack/flink/sql/classloader/ClassLoaderManager.java @@ -19,18 +19,11 @@ package com.dtstack.flink.sql.classloader; import com.dtstack.flink.sql.util.PluginUtil; -import com.dtstack.flink.sql.util.ReflectionUtils; -import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.FileInputStream; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.net.URL; -import java.net.URLClassLoader; -import java.sql.DriverManager; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; @@ -46,28 +39,8 @@ public class ClassLoaderManager { private static final Logger LOG = LoggerFactory.getLogger(ClassLoaderManager.class); - private static final Map pluginClassLoader = new ConcurrentHashMap<>(); - private static final Object LOCK = new Object(); - public static void forName(String clazz, ClassLoader classLoader) { - synchronized (LOCK) { - try { - Class.forName(clazz, true, classLoader); - DriverManager.setLoginTimeout(10); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - } - - public synchronized static void forName(String clazz) { - try { - Class driverClass = Class.forName(clazz); - driverClass.newInstance(); - } catch (Exception e) { - throw new RuntimeException(e); - } - } + private static Map pluginClassLoader = new ConcurrentHashMap<>(); public static R newInstance(String pluginJarPath, ClassLoaderSupplier supplier) throws Exception { ClassLoader classLoader = retrieveClassLoad(pluginJarPath); @@ -88,25 +61,15 @@ private static DtClassLoader retrieveClassLoad(String pluginJarPath) { LOG.info("pluginJarPath:{} create ClassLoad successful...", pluginJarPath); return classLoader; } catch (Throwable e) { - LOG.error("retrieve ClassLoad happens error", e); + LOG.error("retrieve ClassLoad happens error:{}", e); throw new RuntimeException("retrieve ClassLoad happens error"); } }); } - public static DtClassLoader retrieveClassLoad(List jarUrls) { + private static DtClassLoader retrieveClassLoad(List jarUrls) { jarUrls.sort(Comparator.comparing(URL::toString)); - - List jarMd5s = new ArrayList<>(jarUrls.size()); - for (URL jarUrl : jarUrls) { - try (FileInputStream inputStream = new FileInputStream(jarUrl.getPath())){ - String jarMd5 = DigestUtils.md5Hex(inputStream); - jarMd5s.add(jarMd5); - } catch (Exception e) { - throw new RuntimeException("Exceptions appears when read file:" + e); - } - } - String jarUrlkey = StringUtils.join(jarMd5s, "_"); + String jarUrlkey = StringUtils.join(jarUrls, "_"); return pluginClassLoader.computeIfAbsent(jarUrlkey, k -> { try { URL[] urls = jarUrls.toArray(new URL[jarUrls.size()]); @@ -128,25 +91,4 @@ public static List getClassPath() { } return classPaths; } - - - public static URLClassLoader loadExtraJar(List jarUrlList, URLClassLoader classLoader) - throws IllegalAccessException, InvocationTargetException { - for (URL url : jarUrlList) { - if (url.toString().endsWith(".jar")) { - urlClassLoaderAddUrl(classLoader, url); - } - } - return classLoader; - } - - private static void urlClassLoaderAddUrl(URLClassLoader classLoader, URL url) throws InvocationTargetException, IllegalAccessException { - Method method = ReflectionUtils.getDeclaredMethod(classLoader, "addURL", URL.class); - - if (method == null) { - throw new RuntimeException("can't not find declared method addURL, curr classLoader is " + classLoader.getClass()); - } - method.setAccessible(true); - method.invoke(classLoader, url); - } } diff --git a/file/file-source/src/main/java/com/dtstack/flink/sql/source/file/throwable/LengthMismatchException.java b/core/src/main/java/com/dtstack/flink/sql/config/CalciteConfig.java similarity index 70% rename from file/file-source/src/main/java/com/dtstack/flink/sql/source/file/throwable/LengthMismatchException.java rename to core/src/main/java/com/dtstack/flink/sql/config/CalciteConfig.java index ea40350e6..54ae66bbc 100644 --- a/file/file-source/src/main/java/com/dtstack/flink/sql/source/file/throwable/LengthMismatchException.java +++ b/core/src/main/java/com/dtstack/flink/sql/config/CalciteConfig.java @@ -16,17 +16,20 @@ * limitations under the License. */ -package com.dtstack.flink.sql.source.file.throwable; -import org.apache.flink.util.FlinkRuntimeException; +package com.dtstack.flink.sql.config; + +import org.apache.calcite.config.Lex; +import org.apache.calcite.sql.parser.SqlParser; +import org.apache.calcite.sql.parser.SqlParser.Config; + +public class CalciteConfig { + + public static Config MYSQL_LEX_CONFIG = SqlParser + .configBuilder() + .setLex(Lex.MYSQL) + .build(); + -/** - * @author tiezhu - * @since 2021/5/6 3:39 下午 - */ -public class LengthMismatchException extends FlinkRuntimeException { - public LengthMismatchException(String message) { - super(message); - } } diff --git a/core/src/main/java/com/dtstack/flink/sql/constant/PluginParamConsts.java b/core/src/main/java/com/dtstack/flink/sql/constant/PluginParamConsts.java deleted file mode 100644 index 8fc3a472a..000000000 --- a/core/src/main/java/com/dtstack/flink/sql/constant/PluginParamConsts.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.constant; - -/** - * @program: flinkStreamSQL - * @author: wuren - * @create: 2020/09/15 - */ -public class PluginParamConsts { - - public static final String PRINCIPAL = "principal"; - public static final String KEYTAB = "keytab"; - public static final String KRB5_CONF = "krb5conf"; - - public static final String SINK_BUFFER_FLUSH_MAX_ROWS = "sink.buffer-flush.max-rows"; - public static final String SINK_BUFFER_FLUSH_INTERVAL = "sink.buffer-flush.interval"; - public static final String SINK_MAX_RETRIES = "sink.max-retries"; - -} diff --git a/core/src/main/java/com/dtstack/flink/sql/constrant/ConfigConstrant.java b/core/src/main/java/com/dtstack/flink/sql/constrant/ConfigConstrant.java index 31a482da7..76f5996c3 100644 --- a/core/src/main/java/com/dtstack/flink/sql/constrant/ConfigConstrant.java +++ b/core/src/main/java/com/dtstack/flink/sql/constrant/ConfigConstrant.java @@ -43,44 +43,25 @@ public class ConfigConstrant { public static final String FLINK_CHECKPOINT_CLEANUPMODE_KEY = "flink.checkpoint.cleanup.mode"; + + + public static final String FLINK_CHECKPOINT_DATAURI_KEY = "flinkCheckpointDataURI"; + public static final String SQL_ENV_PARALLELISM = "sql.env.parallelism"; public static final String SQL_MAX_ENV_PARALLELISM = "sql.max.env.parallelism"; - public static final String SAVE_POINT_PATH_KEY = "savePointPath"; - public static final String ALLOW_NON_RESTORED_STATE_KEY = "allowNonRestoredState"; - + public static final String MR_JOB_PARALLELISM = "mr.job.parallelism"; + public static final String SQL_BUFFER_TIMEOUT_MILLIS = "sql.buffer.timeout.millis"; public static final String FLINK_TIME_CHARACTERISTIC_KEY = "time.characteristic"; - // default 200ms - public static final String AUTO_WATERMARK_INTERVAL_KEY = "autoWatermarkInterval"; - - // window early trigger - public static final String EARLY_TRIGGER = "early.trigger"; - - public static final String SQL_TTL_MINTIME = "sql.ttl.min"; - public static final String SQL_TTL_MAXTIME = "sql.ttl.max"; - - public static final String STATE_BACKEND_KEY = "state.backend"; - public static final String CHECKPOINTS_DIRECTORY_KEY = "state.checkpoints.dir"; - public static final String STATE_BACKEND_INCREMENTAL_KEY = "state.backend.incremental"; - - public static final String RESTOREENABLE = "restore.enable"; - - public static final String LOG_LEVEL_KEY = "logLevel"; - // restart plocy - public static final int FAILUEE_RATE = 3; - - public static final int FAILUEE_INTERVAL = 6; //min - - public static final int DELAY_INTERVAL = 10; //sec - - public static final String FAILUREINTERVAL = "failure.interval"; //min + public static final int failureRate = 3; - public static final String DELAYINTERVAL= "delay.interval"; //sec + public static final int failureInterval = 6; //min + public static final int delayInterval = 10; //sec } diff --git a/core/src/main/java/com/dtstack/flink/sql/dirtyManager/consumer/AbstractDirtyDataConsumer.java b/core/src/main/java/com/dtstack/flink/sql/dirtyManager/consumer/AbstractDirtyDataConsumer.java deleted file mode 100644 index 9748100fc..000000000 --- a/core/src/main/java/com/dtstack/flink/sql/dirtyManager/consumer/AbstractDirtyDataConsumer.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.dirtyManager.consumer; - -import com.dtstack.flink.sql.dirtyManager.entity.DirtyDataEntity; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.Serializable; -import java.util.Map; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicLong; - -/** - * @author tiezhu - * Company dtstack - * Date 2020/8/27 星期四 - */ -public abstract class AbstractDirtyDataConsumer implements Runnable, Serializable { - protected static final long serialVersionUID = -6058598201315176687L; - - protected static final Logger LOG = LoggerFactory.getLogger(AbstractDirtyDataConsumer.class); - - protected Long errorLimit = 1000L; - protected AtomicLong errorCount = new AtomicLong(0L); - - protected AtomicLong count = new AtomicLong(0L); - - public AtomicBoolean isRunning = new AtomicBoolean(true); - - protected LinkedBlockingQueue queue; - - /** - * 消费队列数据 - * - * @throws Exception throw exception - */ - public abstract void consume() throws Exception; - - /** - * 关闭消费者,需要释放资源 - */ - public abstract void close(); - - /** - * 初始化消费者,初始化定时任务 - * - * @param properties 任务参数 - * @throws Exception throw exception - */ - public abstract void init(Map properties) throws Exception; - - /** - * 检验consumer是否正在执行 - */ - public boolean isRunning() { - return isRunning.get(); - } - - @Override - public void run() { - try { - while (isRunning.get()) { - consume(); - } - } catch (Exception e) { - LOG.error("consume dirtyData error", e); - if (errorCount.getAndIncrement() > errorLimit) { - throw new RuntimeException("The task failed due to the number of dirty data consume failed reached the limit " + errorLimit); - } - } - } - - public AbstractDirtyDataConsumer setQueue(LinkedBlockingQueue queue) { - this.queue = queue; - return this; - } - - public void collectDirtyData(DirtyDataEntity dataEntity, long blockingInterval) throws InterruptedException { - queue.offer(dataEntity, blockingInterval, TimeUnit.MILLISECONDS); - } -} diff --git a/core/src/main/java/com/dtstack/flink/sql/dirtyManager/consumer/DirtyConsumerFactory.java b/core/src/main/java/com/dtstack/flink/sql/dirtyManager/consumer/DirtyConsumerFactory.java deleted file mode 100644 index fdefc0f34..000000000 --- a/core/src/main/java/com/dtstack/flink/sql/dirtyManager/consumer/DirtyConsumerFactory.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.dirtyManager.consumer; - -import com.dtstack.flink.sql.classloader.ClassLoaderManager; -import com.dtstack.flink.sql.util.PluginUtil; - -import java.io.File; -import java.lang.reflect.Constructor; -import java.util.Objects; - -import static com.dtstack.flink.sql.util.PluginUtil.upperCaseFirstChar; - -/** - * @author tiezhu - * Company dtstack - * Date 2020/12/21 星期一 - */ -public class DirtyConsumerFactory { - public static final String DEFAULT_DIRTY_TYPE = "console"; - public static final String DIRTY_CONSUMER_PATH = "dirtyData"; - public static final String CLASS_PRE_STR = "com.dtstack.flink.sql.dirty"; - public static final String CLASS_POST_STR = "DirtyDataConsumer"; - - /** - * 通过动态方式去加载脏数据插件 - * - * @param dirtyType 脏数据插件类型 - * @param pluginPath 脏数据插件直地址 - * @param pluginLoadMode 插件加载方式 - * @return 脏数据消费者 - * @throws Exception exception - */ - public static AbstractDirtyDataConsumer getDirtyConsumer( - String dirtyType - , String pluginPath - , String pluginLoadMode) throws Exception { - if (Objects.isNull(dirtyType)) { - dirtyType = DEFAULT_DIRTY_TYPE; - } - String consumerType = DIRTY_CONSUMER_PATH + File.separator + dirtyType; - String consumerJar = PluginUtil.getJarFileDirPath(consumerType, pluginPath, pluginLoadMode); - String className = CLASS_PRE_STR + "." + dirtyType.toLowerCase() + "." + upperCaseFirstChar(dirtyType + CLASS_POST_STR); - return ClassLoaderManager.newInstance(consumerJar, cl -> { - Class clazz = cl.loadClass(className); - Constructor constructor = clazz.getConstructor(); - return (AbstractDirtyDataConsumer) constructor.newInstance(); - }); - } -} diff --git a/core/src/main/java/com/dtstack/flink/sql/dirtyManager/entity/DirtyDataEntity.java b/core/src/main/java/com/dtstack/flink/sql/dirtyManager/entity/DirtyDataEntity.java deleted file mode 100644 index 42466970d..000000000 --- a/core/src/main/java/com/dtstack/flink/sql/dirtyManager/entity/DirtyDataEntity.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.dirtyManager.entity; - -import java.sql.Date; -import java.text.SimpleDateFormat; - -/** - * @author tiezhu - * Company dtstack - * Date 2020/8/27 星期四 - */ -public class DirtyDataEntity { - private final SimpleDateFormat timeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - /** - * 脏数据信息内容 - */ - private String dirtyData; - - /** - * 脏数据处理时间 - */ - private String processDate; - - /** - * 产生脏数据的原因 - */ - private String cause; - - /** - * 产生异常的字段 - */ - private String field; - - public String getDirtyData() { - return dirtyData; - } - - public void setDirtyData(String dirtyData) { - this.dirtyData = dirtyData; - } - - public String getProcessDate() { - return processDate; - } - - public void setProcessDate(String processDate) { - this.processDate = processDate; - } - - public String getCause() { - return cause; - } - - public void setCause(String cause) { - this.cause = cause; - } - - public String getField() { - return field; - } - - public void setField(String field) { - this.field = field; - } - - public DirtyDataEntity(String dirtyData, Long processDate, String cause, String field) { - this.dirtyData = dirtyData; - this.processDate = timeFormat.format(processDate); - this.cause = cause; - this.field = field; - } - - public DirtyDataEntity(String dirtyData, Long processDate, String cause) { - this.dirtyData = dirtyData; - this.processDate = timeFormat.format(processDate); - this.cause = cause; - } - - @Override - public String toString() { - return "DirtyDataEntity{" + - "dirtyData='" + dirtyData + '\'' + - ", processDate=" + processDate + - ", cause='" + cause + '\'' + - '}'; - } - - /** - * 获取脏数据信息,返回字符数组 - * @return 脏数据信息字符数组 - */ - public String[] get() { - return new String[] {dirtyData, String.valueOf(processDate), cause}; - } -} diff --git a/core/src/main/java/com/dtstack/flink/sql/dirtyManager/manager/DirtyDataManager.java b/core/src/main/java/com/dtstack/flink/sql/dirtyManager/manager/DirtyDataManager.java deleted file mode 100644 index 6a57ba44c..000000000 --- a/core/src/main/java/com/dtstack/flink/sql/dirtyManager/manager/DirtyDataManager.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.dirtyManager.manager; - -import com.alibaba.fastjson.JSONObject; -import com.dtstack.flink.sql.dirtyManager.consumer.AbstractDirtyDataConsumer; -import com.dtstack.flink.sql.dirtyManager.consumer.DirtyConsumerFactory; -import com.dtstack.flink.sql.dirtyManager.entity.DirtyDataEntity; -import com.dtstack.flink.sql.factory.DTThreadFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.Serializable; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; - -import static com.dtstack.flink.sql.dirtyManager.manager.DirtyKeys.DEFAULT_BLOCKING_INTERVAL; -import static com.dtstack.flink.sql.dirtyManager.manager.DirtyKeys.DEFAULT_ERROR_LIMIT_RATE; -import static com.dtstack.flink.sql.dirtyManager.manager.DirtyKeys.DEFAULT_PRINT_LIMIT; -import static com.dtstack.flink.sql.dirtyManager.manager.DirtyKeys.DEFAULT_TYPE; -import static com.dtstack.flink.sql.dirtyManager.manager.DirtyKeys.DIRTY_BLOCK_STR; -import static com.dtstack.flink.sql.dirtyManager.manager.DirtyKeys.DIRTY_LIMIT_RATE_STR; -import static com.dtstack.flink.sql.dirtyManager.manager.DirtyKeys.PLUGIN_LOAD_MODE_STR; -import static com.dtstack.flink.sql.dirtyManager.manager.DirtyKeys.PLUGIN_PATH_STR; -import static com.dtstack.flink.sql.dirtyManager.manager.DirtyKeys.PLUGIN_TYPE_STR; -import static com.dtstack.flink.sql.dirtyManager.manager.DirtyKeys.PRINT_LIMIT_STR; - -/** - * @author tiezhu - * Company dtstack - * Date 2020/8/27 星期四 - */ -public class DirtyDataManager implements Serializable { - private static final long serialVersionUID = 1L; - - public final static int MAX_POOL_SIZE_LIMIT = 5; - private static final Logger LOG = LoggerFactory.getLogger(DirtyDataManager.class); - private final static int MAX_TASK_QUEUE_SIZE = 100; - - private AbstractDirtyDataConsumer consumer; - private transient ThreadPoolExecutor dirtyDataConsumer; - - private static final DirtyDataManager INSTANCE = new DirtyDataManager(); - - /** - * 统计manager收集到的脏数据条数 - */ - private final AtomicLong count = new AtomicLong(0); - /** - * 脏数据写入队列失败条数 - */ - private final AtomicLong errorCount = new AtomicLong(0); - /** - * 写入队列阻塞时间 - */ - private long blockingInterval; - /** - * 任务失败的脏数据比例 - */ - private double errorLimitRate; - - private DirtyDataManager() { - - } - - /** - * 通过参数生成manager实例,并同时将consumer实例化 - */ - public static DirtyDataManager newInstance(Map properties) { - try { - INSTANCE.setBlockingInterval(Long.parseLong( - String.valueOf(properties.getOrDefault(DIRTY_BLOCK_STR, DEFAULT_BLOCKING_INTERVAL)))); - INSTANCE.setErrorLimitRate(Double.parseDouble( - String.valueOf(properties.getOrDefault(DIRTY_LIMIT_RATE_STR, DEFAULT_ERROR_LIMIT_RATE)))); - - INSTANCE.setConsumer(properties); - return INSTANCE; - } catch (Exception e) { - throw new RuntimeException("create dirtyManager error!", e); - } - } - - private void setConsumer(Map properties) throws Exception { - consumer = DirtyConsumerFactory.getDirtyConsumer( - String.valueOf(properties.getOrDefault(PLUGIN_TYPE_STR, DEFAULT_TYPE)), - String.valueOf(properties.get(PLUGIN_PATH_STR)), - String.valueOf(properties.get(PLUGIN_LOAD_MODE_STR)) - ); - consumer.init(properties); - consumer.setQueue(new LinkedBlockingQueue<>()); - } - - public void execute() { - if (Objects.isNull(dirtyDataConsumer)) { - dirtyDataConsumer = new ThreadPoolExecutor( - MAX_POOL_SIZE_LIMIT, - MAX_POOL_SIZE_LIMIT, - 0, - TimeUnit.MILLISECONDS, - new LinkedBlockingQueue<>(MAX_TASK_QUEUE_SIZE), - new DTThreadFactory("dirtyDataConsumer", true), - new ThreadPoolExecutor.CallerRunsPolicy()); - dirtyDataConsumer.execute(consumer); - } - } - - /** - * 设置脏数据插件默认配置 - * - * @return console的默认配置 - */ - public static String buildDefaultDirty() { - JSONObject jsonObject = new JSONObject(); - jsonObject.put(PLUGIN_TYPE_STR, DEFAULT_TYPE); - jsonObject.put(PRINT_LIMIT_STR, DEFAULT_PRINT_LIMIT); - return jsonObject.toJSONString(); - } - - /** - * 脏数据收集任务停止,任务停止之前,需要将队列中所有的数据清空 - */ - public void close() { - if (consumer != null && checkConsumer()) { - LOG.info("dirty consumer is closing ..."); - consumer.close(); - } - - if (dirtyDataConsumer != null) { - dirtyDataConsumer.shutdownNow(); - } - } - - /** - * 收集脏数据放入队列缓存中,记录放入失败的数目和存入队列中的总数目,如果放入失败的数目超过一定比例,那么manager任务失败 - */ - public void collectDirtyData(String dataInfo, String cause) { - DirtyDataEntity dirtyDataEntity = new DirtyDataEntity(dataInfo, System.currentTimeMillis(), cause); - try { - count.incrementAndGet(); - consumer.collectDirtyData(dirtyDataEntity, blockingInterval); - } catch (Exception e) { - LOG.warn("dirty Data insert error ... Failed number: " + errorCount.incrementAndGet()); - LOG.warn("error cause: " + e.getMessage()); - LOG.warn("error dirty data:" + dirtyDataEntity.getDirtyData()); - if (errorCount.get() > Math.ceil(count.longValue() * errorLimitRate)) { - // close consumer and manager - close(); - throw new RuntimeException( - String.format("The number of failed number 【%s】 reaches the limit, manager fails", errorCount.get())); - } - } - } - - /** - * 查看consumer当前状态 - */ - public boolean checkConsumer() { - return consumer.isRunning(); - } - - public AtomicLong getCount() { - return count; - } - - public AtomicLong getErrorCount() { - return errorCount; - } - - public long getBlockingInterval() { - return blockingInterval; - } - - public void setBlockingInterval(long blockingInterval) { - this.blockingInterval = blockingInterval; - } - - public double getErrorLimitRate() { - return errorLimitRate; - } - - public void setErrorLimitRate(double errorLimitRate) { - this.errorLimitRate = errorLimitRate; - } -} diff --git a/core/src/main/java/com/dtstack/flink/sql/dirtyManager/manager/DirtyKeys.java b/core/src/main/java/com/dtstack/flink/sql/dirtyManager/manager/DirtyKeys.java deleted file mode 100644 index d9df6b8d4..000000000 --- a/core/src/main/java/com/dtstack/flink/sql/dirtyManager/manager/DirtyKeys.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.dirtyManager.manager; - -/** - * Date: 2021/1/6 - * - * @author tiezhu - * Company dtstack - */ -public class DirtyKeys { - public final static String DEFAULT_TYPE = "console"; - public final static String DEFAULT_BLOCKING_INTERVAL = "60"; - public final static String DEFAULT_ERROR_LIMIT_RATE = "0.8"; - public final static String DEFAULT_PRINT_LIMIT = "1000"; - - public final static String DIRTY_BLOCK_STR = "blockingInterval"; - public final static String DIRTY_LIMIT_RATE_STR = "errorLimitRate"; - public final static String PLUGIN_TYPE_STR = "type"; - public final static String PLUGIN_PATH_STR = "pluginPath"; - public final static String PLUGIN_LOAD_MODE_STR = "pluginLoadMode"; - - public final static String PRINT_LIMIT_STR = "printLimit"; - - public final static String ENV_CLASSLOADER = "envClassLoader"; - public final static String TABLE_NAME = "tableName"; -} diff --git a/core/src/main/java/com/dtstack/flink/sql/enums/ClusterMode.java b/core/src/main/java/com/dtstack/flink/sql/enums/ClusterMode.java index 4e8a3e210..341258a43 100644 --- a/core/src/main/java/com/dtstack/flink/sql/enums/ClusterMode.java +++ b/core/src/main/java/com/dtstack/flink/sql/enums/ClusterMode.java @@ -24,14 +24,7 @@ */ public enum ClusterMode { - //run in local - local(0), - //submit job to standalone cluster - standalone(1), - //submit job to flink-session which is already run on yarn - yarn(2), - //submit job to yarn cluster as an application - yarnPer(3); + local(0),standalone(1),yarn(2),yarnPer(3); private int type; diff --git a/core/src/main/java/com/dtstack/flink/sql/enums/ColumnType.java b/core/src/main/java/com/dtstack/flink/sql/enums/ColumnType.java index e93c92f51..749bbc907 100644 --- a/core/src/main/java/com/dtstack/flink/sql/enums/ColumnType.java +++ b/core/src/main/java/com/dtstack/flink/sql/enums/ColumnType.java @@ -46,70 +46,11 @@ * @author huyifan.zju@163.com */ public enum ColumnType { - /* - * string - */ - STRING, - /** - * varchar - */ - VARCHAR, - /** - * char - */ - CHAR, - /** - * int - */ - INT, - /** - * mediumint - */ - MEDIUMINT, - /** - * tinyint - */ - TINYINT, - /** - * datetime - */ - DATETIME, - /** - * smallint - */ - SMALLINT, - /** - * bigint - */ - BIGINT, - /** - * double - */ - DOUBLE, - /** - * float - */ - FLOAT, - /** - * boolean - */ + STRING, VARCHAR, CHAR, + INT, MEDIUMINT, TINYINT, DATETIME, SMALLINT, BIGINT, + DOUBLE, FLOAT, BOOLEAN, - /** - * date - */ - DATE, - /** - * timestamp - */ - TIMESTAMP, - /** - * time eg: 23:59:59 - */ - TIME, - /** - * decimal - */ - DECIMAL; + DATE, TIMESTAMP, DECIMAL; public static ColumnType fromString(String type) { if(type == null) { diff --git a/core/src/main/java/com/dtstack/flink/sql/enums/ECacheContentType.java b/core/src/main/java/com/dtstack/flink/sql/enums/ECacheContentType.java index 49e352757..66160d820 100644 --- a/core/src/main/java/com/dtstack/flink/sql/enums/ECacheContentType.java +++ b/core/src/main/java/com/dtstack/flink/sql/enums/ECacheContentType.java @@ -30,17 +30,8 @@ public enum ECacheContentType { - /** - * 无 - */ MissVal(0), - /** - * 1行 - */ SingleLine(1), - /** - * 多行 - */ MultiLine(2); int type; diff --git a/core/src/main/java/com/dtstack/flink/sql/enums/ECacheType.java b/core/src/main/java/com/dtstack/flink/sql/enums/ECacheType.java index 9d5bb5d11..582148c2c 100644 --- a/core/src/main/java/com/dtstack/flink/sql/enums/ECacheType.java +++ b/core/src/main/java/com/dtstack/flink/sql/enums/ECacheType.java @@ -27,18 +27,7 @@ * @author xuchao */ public enum ECacheType { - /** - * none - */ - NONE, - /** - * lru - */ - LRU, - /** - * all - */ - ALL; + NONE, LRU, ALL; public static boolean isValid(String type){ for(ECacheType tmpType : ECacheType.values()){ diff --git a/core/src/main/java/com/dtstack/flink/sql/enums/EConnectionErrorCode.java b/core/src/main/java/com/dtstack/flink/sql/enums/EConnectionErrorCode.java deleted file mode 100644 index a0a281c4a..000000000 --- a/core/src/main/java/com/dtstack/flink/sql/enums/EConnectionErrorCode.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.enums; - -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.exception.ExceptionUtils; - -import java.util.Arrays; - -/** - * Date: 2020/4/2 - * Company: www.dtstack.com - * @author maqi - */ -public enum EConnectionErrorCode { - ERROR_NOT_MATCH(0, "错误信息未匹配", new String[]{}), - CONN_DB_INVALID(1, "数据库连接失效,请重新打开", new String[]{"the last packet successfully received from the server was", "Zookeeper session has been expired"}), - CONN_DB_FAILED(2, "数据库连接失败,请检查用户名或密码是否正确", new String[]{"Access denied for user"}), - DB_TABLE_NOT_EXIST(3, "操作的表名不存在", new String[]{"doesn't exist"}); - - private int code; - private String description; - private String[] baseErrorInfo; - - EConnectionErrorCode(int code, String description, String[] baseErrorInfo) { - this.code = code; - this.description = description; - this.baseErrorInfo = baseErrorInfo; - } - - - public static EConnectionErrorCode resolveErrorCodeFromException(Throwable e) { - final String stackErrorMsg = ExceptionUtils.getFullStackTrace(e); - return Arrays.stream(values()) - .filter(errorCode -> matchKnowError(errorCode, stackErrorMsg)) - .findAny() - .orElse(ERROR_NOT_MATCH); - } - - public static boolean matchKnowError(EConnectionErrorCode errorCode, String errorMsg) { - return Arrays.stream(errorCode.baseErrorInfo) - .filter(baseInfo -> StringUtils.containsIgnoreCase(errorMsg, baseInfo)) - .findAny() - .isPresent(); - } -} diff --git a/core/src/main/java/com/dtstack/flink/sql/enums/EDatabaseType.java b/core/src/main/java/com/dtstack/flink/sql/enums/EDatabaseType.java index 7d2235f2e..9b01bf052 100644 --- a/core/src/main/java/com/dtstack/flink/sql/enums/EDatabaseType.java +++ b/core/src/main/java/com/dtstack/flink/sql/enums/EDatabaseType.java @@ -26,17 +26,8 @@ */ public enum EDatabaseType { - /** - * mysql - */ MYSQL, - /** - * sqlserver - */ SQLSERVER, - /** - * oracle - */ ORACLE, } diff --git a/core/src/main/java/com/dtstack/flink/sql/enums/EPluginLoadMode.java b/core/src/main/java/com/dtstack/flink/sql/enums/EPluginLoadMode.java index 34d58e1c3..6cb027ac3 100644 --- a/core/src/main/java/com/dtstack/flink/sql/enums/EPluginLoadMode.java +++ b/core/src/main/java/com/dtstack/flink/sql/enums/EPluginLoadMode.java @@ -26,19 +26,8 @@ */ public enum EPluginLoadMode { - /** - * 0:classpath - */ CLASSPATH(0), - /** - * 1:shipfile - */ - SHIPFILE(1), - - /** - * 2:localTest - */ - LOCALTEST(3); + SHIPFILE(1); private int type; diff --git a/core/src/main/java/com/dtstack/flink/sql/enums/EUpdateMode.java b/core/src/main/java/com/dtstack/flink/sql/enums/EUpdateMode.java deleted file mode 100644 index eec1a4c4a..000000000 --- a/core/src/main/java/com/dtstack/flink/sql/enums/EUpdateMode.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.enums; - -/** - * restract stream数据处理模式 - * - * Reason: - * Date: 2019/1/2 - * Company: www.dtstack.com - * @author maqi - */ -public enum EUpdateMode { - // 不回撤数据,只下发增量数据 - APPEND(0), - // 先删除回撤数据,然后更新 - UPSERT(1); - - private int type; - - EUpdateMode(int type) { - this.type = type; - } - - public int getType() { - return this.type; - } -} diff --git a/core/src/main/java/com/dtstack/flink/sql/environment/MyLocalStreamEnvironment.java b/core/src/main/java/com/dtstack/flink/sql/environment/MyLocalStreamEnvironment.java index 8196d57d6..8ac1edd41 100644 --- a/core/src/main/java/com/dtstack/flink/sql/environment/MyLocalStreamEnvironment.java +++ b/core/src/main/java/com/dtstack/flink/sql/environment/MyLocalStreamEnvironment.java @@ -22,7 +22,6 @@ import org.apache.flink.api.common.JobExecutionResult; import org.apache.flink.api.java.ExecutionEnvironment; import org.apache.flink.configuration.Configuration; -import org.apache.flink.configuration.RestOptions; import org.apache.flink.configuration.TaskManagerOptions; import org.apache.flink.runtime.jobgraph.JobGraph; import org.apache.flink.runtime.minicluster.MiniCluster; @@ -94,10 +93,6 @@ public JobExecutionResult execute(String jobName) throws Exception { // transform the streaming program into a JobGraph StreamGraph streamGraph = getStreamGraph(); streamGraph.setJobName(jobName); - return execute(streamGraph); - } - - public JobExecutionResult execute(StreamGraph streamGraph) throws Exception { JobGraph jobGraph = streamGraph.getJobGraph(); jobGraph.setClasspaths(classpaths); @@ -105,38 +100,27 @@ public JobExecutionResult execute(StreamGraph streamGraph) throws Exception { Configuration configuration = new Configuration(); configuration.addAll(jobGraph.getJobConfiguration()); - configuration.setString(TaskManagerOptions.MANAGED_MEMORY_SIZE.key(), "512M"); + configuration.setString(TaskManagerOptions.MANAGED_MEMORY_SIZE, "512M"); configuration.setInteger(TaskManagerOptions.NUM_TASK_SLOTS, jobGraph.getMaximumParallelism()); // add (and override) the settings with what the user defined configuration.addAll(this.conf); - if (!configuration.contains(RestOptions.BIND_PORT)) { - configuration.setString(RestOptions.BIND_PORT, "0"); - } - - int numSlotsPerTaskManager = configuration.getInteger(TaskManagerOptions.NUM_TASK_SLOTS, jobGraph.getMaximumParallelism()); - - MiniClusterConfiguration cfg = new MiniClusterConfiguration.Builder() - .setConfiguration(configuration) - .setNumSlotsPerTaskManager(numSlotsPerTaskManager) - .build(); + MiniClusterConfiguration.Builder configBuilder = new MiniClusterConfiguration.Builder(); + configBuilder.setConfiguration(configuration); if (LOG.isInfoEnabled()) { LOG.info("Running job on local embedded Flink mini cluster"); } - MiniCluster miniCluster = new MiniCluster(cfg); - + MiniCluster exec = new MiniCluster(configBuilder.build()); try { - miniCluster.start(); - configuration.setInteger(RestOptions.PORT, miniCluster.getRestAddress().get().getPort()); - - return miniCluster.executeJobBlocking(jobGraph); + exec.start(); + return exec.executeJobBlocking(jobGraph); } finally { transformations.clear(); - miniCluster.close(); + exec.closeAsync(); } } } diff --git a/core/src/main/java/com/dtstack/flink/sql/environment/StreamEnvConfigManager.java b/core/src/main/java/com/dtstack/flink/sql/environment/StreamEnvConfigManager.java deleted file mode 100644 index ecc68a887..000000000 --- a/core/src/main/java/com/dtstack/flink/sql/environment/StreamEnvConfigManager.java +++ /dev/null @@ -1,358 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.environment; - -import com.dtstack.flink.sql.constrant.ConfigConstrant; -import com.dtstack.flink.sql.enums.EStateBackend; -import com.dtstack.flink.sql.util.MathUtil; -import com.dtstack.flink.sql.util.PropertiesUtils; -import org.apache.commons.lang3.BooleanUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.flink.api.common.ExecutionConfig; -import org.apache.flink.api.common.restartstrategy.RestartStrategies; -import org.apache.flink.api.common.time.Time; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.configuration.Configuration; -import org.apache.flink.contrib.streaming.state.RocksDBStateBackend; -import org.apache.flink.runtime.state.StateBackend; -import org.apache.flink.runtime.state.filesystem.FsStateBackend; -import org.apache.flink.runtime.state.memory.MemoryStateBackend; -import org.apache.flink.streaming.api.CheckpointingMode; -import org.apache.flink.streaming.api.TimeCharacteristic; -import org.apache.flink.streaming.api.environment.CheckpointConfig; -import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; -import org.apache.flink.table.api.TableConfig; -import org.apache.flink.table.api.TableEnvironment; - -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.Map; -import java.util.Optional; -import java.util.Properties; -import java.util.concurrent.TimeUnit; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * - * 流执行环境相关配置 - * Date: 2019/11/22 - * Company: www.dtstack.com - * @author maqi - */ -public final class StreamEnvConfigManager { - private StreamEnvConfigManager() { - throw new AssertionError("Singleton class."); - } - - /** - * 配置StreamExecutionEnvironment运行时参数 - * @param streamEnv - * @param confProperties - */ - public static void streamExecutionEnvironmentConfig(StreamExecutionEnvironment streamEnv, Properties confProperties) - throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, IOException { - - confProperties = PropertiesUtils.propertiesTrim(confProperties); - streamEnv.getConfig().disableClosureCleaner(); - - Configuration globalJobParameters = new Configuration(); - //Configuration unsupported set properties key-value - Method method = Configuration.class.getDeclaredMethod("setValueInternal", String.class, Object.class); - method.setAccessible(true); - for (Map.Entry prop : confProperties.entrySet()) { - method.invoke(globalJobParameters, prop.getKey(), prop.getValue()); - } - - ExecutionConfig exeConfig = streamEnv.getConfig(); - if (exeConfig.getGlobalJobParameters() == null) { - exeConfig.setGlobalJobParameters(globalJobParameters); - } else if (exeConfig.getGlobalJobParameters() instanceof ExecutionConfig.GlobalJobParameters) { - exeConfig.setGlobalJobParameters(globalJobParameters); - } - - getEnvParallelism(confProperties).ifPresent(streamEnv::setParallelism); - getMaxEnvParallelism(confProperties).ifPresent(streamEnv::setMaxParallelism); - getBufferTimeoutMillis(confProperties).ifPresent(streamEnv::setBufferTimeout); - getStreamTimeCharacteristic(confProperties).ifPresent(streamEnv::setStreamTimeCharacteristic); - getAutoWatermarkInterval(confProperties).ifPresent(op -> { - if (streamEnv.getStreamTimeCharacteristic().equals(TimeCharacteristic.EventTime)) { - streamEnv.getConfig().setAutoWatermarkInterval(op); - } - }); - - if(isRestore(confProperties).get()){ - streamEnv.setRestartStrategy(RestartStrategies.failureRateRestart( - ConfigConstrant.FAILUEE_RATE, - Time.of(getFailureInterval(confProperties).get(), TimeUnit.MINUTES), - Time.of(getDelayInterval(confProperties).get(), TimeUnit.SECONDS) - )); - } else { - streamEnv.setRestartStrategy(RestartStrategies.noRestart()); - } - - // checkpoint config - Optional checkpointingEnabled = isCheckpointingEnabled(confProperties); - if (checkpointingEnabled.get()) { - getCheckpointInterval(confProperties).ifPresent(streamEnv::enableCheckpointing); - getCheckpointingMode(confProperties).ifPresent(streamEnv.getCheckpointConfig()::setCheckpointingMode); - getCheckpointTimeout(confProperties).ifPresent(streamEnv.getCheckpointConfig()::setCheckpointTimeout); - getMaxConcurrentCheckpoints(confProperties).ifPresent(streamEnv.getCheckpointConfig()::setMaxConcurrentCheckpoints); - getCheckpointCleanup(confProperties).ifPresent(streamEnv.getCheckpointConfig()::enableExternalizedCheckpoints); - getStateBackend(confProperties).ifPresent(streamEnv::setStateBackend); - } - } - - /** - * 设置TableEnvironment window提前触发 - * @param tableEnv - * @param confProperties - */ - public static void streamTableEnvironmentEarlyTriggerConfig(TableEnvironment tableEnv, Properties confProperties) { - confProperties = PropertiesUtils.propertiesTrim(confProperties); - String triggerTime = confProperties.getProperty(ConfigConstrant.EARLY_TRIGGER); - if (StringUtils.isNumeric(triggerTime)) { - TableConfig qConfig = tableEnv.getConfig(); - qConfig.getConfiguration().setString("table.exec.emit.early-fire.enabled", "true"); - qConfig.getConfiguration().setString("table.exec.emit.early-fire.delay", triggerTime+"s"); - } - } - - /** - * 设置TableEnvironment状态超时时间 - * @param tableEnv - * @param confProperties - */ - public static void streamTableEnvironmentStateTTLConfig(TableEnvironment tableEnv, Properties confProperties) { - confProperties = PropertiesUtils.propertiesTrim(confProperties); - Optional> tableEnvTTL = getTableEnvTTL(confProperties); - if (tableEnvTTL.isPresent()) { - Tuple2 timeRange = tableEnvTTL.get(); - TableConfig qConfig = tableEnv.getConfig(); - qConfig.setIdleStateRetentionTime(timeRange.f0, timeRange.f1); - } - } - - - // -----------------------StreamExecutionEnvironment config----------------------------------------------- - public static Optional getEnvParallelism(Properties properties) { - String parallelismStr = properties.getProperty(ConfigConstrant.SQL_ENV_PARALLELISM); - return StringUtils.isNotBlank(parallelismStr) ? Optional.of(Integer.valueOf(parallelismStr)) : Optional.empty(); - } - - public static Optional getMaxEnvParallelism(Properties properties) { - String parallelismStr = properties.getProperty(ConfigConstrant.SQL_MAX_ENV_PARALLELISM); - return StringUtils.isNotBlank(parallelismStr) ? Optional.of(Integer.valueOf(parallelismStr)) : Optional.empty(); - } - - public static Optional getBufferTimeoutMillis(Properties properties) { - String mills = properties.getProperty(ConfigConstrant.SQL_BUFFER_TIMEOUT_MILLIS); - return StringUtils.isNotBlank(mills) ? Optional.of(Long.valueOf(mills)) : Optional.empty(); - } - - public static Optional getAutoWatermarkInterval(Properties properties) { - String autoWatermarkInterval = properties.getProperty(ConfigConstrant.AUTO_WATERMARK_INTERVAL_KEY); - return StringUtils.isNotBlank(autoWatermarkInterval) ? Optional.of(Long.valueOf(autoWatermarkInterval)) : Optional.empty(); - } - - public static Optional isRestore(Properties properties){ - String restoreEnable = properties.getProperty(ConfigConstrant.RESTOREENABLE, "true"); - return Optional.of(Boolean.valueOf(restoreEnable)); - } - - public static Optional getDelayInterval(Properties properties){ - String delayInterval = properties.getProperty(ConfigConstrant.DELAYINTERVAL, "10"); - return Optional.of(Integer.valueOf(delayInterval)); - } - public static Optional getFailureInterval(Properties properties){ - String failureInterval = properties.getProperty(ConfigConstrant.FAILUREINTERVAL, "6"); - return Optional.of(Integer.valueOf(failureInterval)); - } - - /** - * #ProcessingTime(默认), IngestionTime, EventTime - * @param properties - */ - public static Optional getStreamTimeCharacteristic(Properties properties) { - if (!properties.containsKey(ConfigConstrant.FLINK_TIME_CHARACTERISTIC_KEY)) { - return Optional.empty(); - } - String characteristicStr = properties.getProperty(ConfigConstrant.FLINK_TIME_CHARACTERISTIC_KEY); - Optional characteristic = Arrays.stream(TimeCharacteristic.values()) - .filter(tc -> characteristicStr.equalsIgnoreCase(tc.toString())).findAny(); - - if (!characteristic.isPresent()) { - throw new RuntimeException("illegal property :" + ConfigConstrant.FLINK_TIME_CHARACTERISTIC_KEY); - } - return characteristic; - } - - public static Optional isCheckpointingEnabled(Properties properties) { - boolean checkpointEnabled = !(properties.getProperty(ConfigConstrant.SQL_CHECKPOINT_INTERVAL_KEY) == null - && properties.getProperty(ConfigConstrant.FLINK_CHECKPOINT_INTERVAL_KEY) == null); - return Optional.of(checkpointEnabled); - } - - public static Optional getCheckpointInterval(Properties properties) { - // 两个参数主要用来做上层兼容 - Long sqlInterval = Long.valueOf(properties.getProperty(ConfigConstrant.SQL_CHECKPOINT_INTERVAL_KEY, "0")); - Long flinkInterval = Long.valueOf(properties.getProperty(ConfigConstrant.FLINK_CHECKPOINT_INTERVAL_KEY, "0")); - long checkpointInterval = Math.max(sqlInterval, flinkInterval); - return Optional.of(checkpointInterval); - } - - public static Optional getCheckpointingMode(Properties properties) { - String checkpointingModeStr = properties.getProperty(ConfigConstrant.FLINK_CHECKPOINT_MODE_KEY); - CheckpointingMode checkpointingMode = null; - if (!StringUtils.isEmpty(checkpointingModeStr)) { - checkpointingMode = CheckpointingMode.valueOf(checkpointingModeStr.toUpperCase()); - } - return checkpointingMode == null ? Optional.empty() : Optional.of(checkpointingMode); - } - - public static Optional getCheckpointTimeout(Properties properties) { - String checkpointTimeoutStr = properties.getProperty(ConfigConstrant.FLINK_CHECKPOINT_TIMEOUT_KEY); - - if (!StringUtils.isEmpty(checkpointTimeoutStr)) { - Long checkpointTimeout = Long.valueOf(checkpointTimeoutStr); - return Optional.of(checkpointTimeout); - } - return Optional.empty(); - } - - public static Optional getMaxConcurrentCheckpoints(Properties properties) { - String maxConcurrCheckpointsStr = properties.getProperty(ConfigConstrant.FLINK_MAXCONCURRENTCHECKPOINTS_KEY); - if (!StringUtils.isEmpty(maxConcurrCheckpointsStr)) { - Integer maxConcurrCheckpoints = Integer.valueOf(maxConcurrCheckpointsStr); - return Optional.of(maxConcurrCheckpoints); - } - return Optional.empty(); - } - - public static Optional getCheckpointCleanup(Properties properties) { - Boolean sqlCleanMode = MathUtil.getBoolean(properties.getProperty(ConfigConstrant.SQL_CHECKPOINT_CLEANUPMODE_KEY), false); - Boolean flinkCleanMode = MathUtil.getBoolean(properties.getProperty(ConfigConstrant.FLINK_CHECKPOINT_CLEANUPMODE_KEY), false); - - CheckpointConfig.ExternalizedCheckpointCleanup externalizedCheckpointCleanup = (sqlCleanMode || flinkCleanMode) ? - CheckpointConfig.ExternalizedCheckpointCleanup.DELETE_ON_CANCELLATION : CheckpointConfig.ExternalizedCheckpointCleanup.RETAIN_ON_CANCELLATION; - return Optional.of(externalizedCheckpointCleanup); - } - - public static Optional getStateBackend(Properties properties) throws IOException { - String backendType = properties.getProperty(ConfigConstrant.STATE_BACKEND_KEY); - String checkpointDataUri = properties.getProperty(ConfigConstrant.CHECKPOINTS_DIRECTORY_KEY); - String backendIncremental = properties.getProperty(ConfigConstrant.STATE_BACKEND_INCREMENTAL_KEY, "true"); - - if (!StringUtils.isEmpty(backendType)) { - return createStateBackend(backendType, checkpointDataUri, backendIncremental); - } - return Optional.empty(); - } - - private static Optional createStateBackend(String backendType, String checkpointDataUri, String backendIncremental) throws IOException { - EStateBackend stateBackendType = EStateBackend.convertFromString(backendType); - StateBackend stateBackend = null; - switch (stateBackendType) { - case MEMORY: - stateBackend = new MemoryStateBackend(); - break; - case FILESYSTEM: - checkpointDataUriEmptyCheck(checkpointDataUri, backendType); - stateBackend = new FsStateBackend(checkpointDataUri); - break; - case ROCKSDB: - checkpointDataUriEmptyCheck(checkpointDataUri, backendType); - stateBackend = new RocksDBStateBackend(checkpointDataUri, BooleanUtils.toBoolean(backendIncremental)); - break; - default: - break; - } - return stateBackend == null ? Optional.empty() : Optional.of(stateBackend); - } - - private static void checkpointDataUriEmptyCheck(String checkpointDataUri, String backendType) { - if (StringUtils.isEmpty(checkpointDataUri)) { - throw new RuntimeException(backendType + " backend checkpointDataUri not null!"); - } - } - - // -----------------TableEnvironment state ttl config------------------------------ - - private static final String TTL_PATTERN_STR = "^+?([1-9][0-9]*)([dDhHmMsS])$"; - private static final Pattern TTL_PATTERN = Pattern.compile(TTL_PATTERN_STR); - - public static Optional> getTableEnvTTL(Properties properties) { - String ttlMintimeStr = properties.getProperty(ConfigConstrant.SQL_TTL_MINTIME); - String ttlMaxtimeStr = properties.getProperty(ConfigConstrant.SQL_TTL_MAXTIME); - if (StringUtils.isNotEmpty(ttlMintimeStr) || StringUtils.isNotEmpty(ttlMaxtimeStr)) { - verityTtl(ttlMintimeStr, ttlMaxtimeStr); - Matcher ttlMintimeStrMatcher = TTL_PATTERN.matcher(ttlMintimeStr); - Matcher ttlMaxtimeStrMatcher = TTL_PATTERN.matcher(ttlMaxtimeStr); - - Long ttlMintime = 0L; - Long ttlMaxtime = 0L; - if (ttlMintimeStrMatcher.find()) { - ttlMintime = getTtlTime(Integer.parseInt(ttlMintimeStrMatcher.group(1)), ttlMintimeStrMatcher.group(2)); - } - if (ttlMaxtimeStrMatcher.find()) { - ttlMaxtime = getTtlTime(Integer.parseInt(ttlMaxtimeStrMatcher.group(1)), ttlMaxtimeStrMatcher.group(2)); - } - if (0L != ttlMintime && 0L != ttlMaxtime) { - return Optional.of(new Tuple2<>(Time.milliseconds(ttlMintime), Time.milliseconds(ttlMaxtime))); - } - } - return Optional.empty(); - } - - /** - * ttl 校验 - * @param ttlMintimeStr 最小时间 - * @param ttlMaxtimeStr 最大时间 - */ - private static void verityTtl(String ttlMintimeStr, String ttlMaxtimeStr) { - if (null == ttlMintimeStr - || null == ttlMaxtimeStr - || !TTL_PATTERN.matcher(ttlMintimeStr).find() - || !TTL_PATTERN.matcher(ttlMaxtimeStr).find()) { - throw new RuntimeException("sql.ttl.min 、sql.ttl.max must be set at the same time . example sql.ttl.min=1h,sql.ttl.max=2h"); - } - } - - /** - * 不同单位时间到毫秒的转换 - * @param timeNumber 时间值,如:30 - * @param timeUnit 单位,d:天,h:小时,m:分,s:秒 - * @return - */ - private static Long getTtlTime(Integer timeNumber, String timeUnit) { - if ("d".equalsIgnoreCase(timeUnit)) { - return timeNumber * 1000L * 60 * 60 * 24; - } else if ("h".equalsIgnoreCase(timeUnit)) { - return timeNumber * 1000L * 60 * 60; - } else if ("m".equalsIgnoreCase(timeUnit)) { - return timeNumber * 1000L * 60; - } else if ("s".equalsIgnoreCase(timeUnit)) { - return timeNumber * 1000L; - } else { - throw new RuntimeException("not support " + timeNumber + timeUnit); - } - } -} diff --git a/core/src/main/java/com/dtstack/flink/sql/exception/BaseCodeEnum.java b/core/src/main/java/com/dtstack/flink/sql/exception/BaseCodeEnum.java deleted file mode 100644 index 3e87d0741..000000000 --- a/core/src/main/java/com/dtstack/flink/sql/exception/BaseCodeEnum.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.exception; - -/** - * @author: chuixue - * @create: 2020-11-30 16:23 - * @description: 公共错误码 - **/ -public enum BaseCodeEnum implements ErrorCode { - /** - * 未指明的异常 - */ - UNSPECIFIED("000", "unknow exception"), - ; - - /** - * 错误码 - */ - private final String code; - - /** - * 描述 - */ - private final String description; - - /** - * @param code 错误码 - * @param description 描述 - */ - private BaseCodeEnum(final String code, final String description) { - this.code = code; - this.description = description; - } - - @Override - public String getCode() { - return code; - } - - @Override - public String getDescription() { - return description; - } -} diff --git a/core/src/main/java/com/dtstack/flink/sql/exception/BaseException.java b/core/src/main/java/com/dtstack/flink/sql/exception/BaseException.java deleted file mode 100644 index 0cc86527f..000000000 --- a/core/src/main/java/com/dtstack/flink/sql/exception/BaseException.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.exception; - - -/** - * @author: chuixue - * @create: 2020-11-30 14:48 - * @description:根异常 - **/ -public class BaseException extends RuntimeException { - - /** - * 错误码 - */ - protected final ErrorCode errorCode; - - /** - * 无参默认构造UNSPECIFIED - */ - public BaseException() { - super(BaseCodeEnum.UNSPECIFIED.getDescription()); - errorCode = BaseCodeEnum.UNSPECIFIED; - } - - /** - * 指定错误码构造通用异常 - * - * @param errorCode 错误码 - */ - public BaseException(ErrorCode errorCode) { - super(errorCode.getDescription()); - this.errorCode = errorCode; - } - - /** - * 指定详细描述构造通用异常 - * - * @param detailedMessage 详细描述 - */ - public BaseException(final String detailedMessage) { - super(detailedMessage); - this.errorCode = BaseCodeEnum.UNSPECIFIED; - } - - /** - * 指定导火索构造通用异常 - * - * @param t 导火索 - */ - public BaseException(final Throwable t) { - super(t); - this.errorCode = BaseCodeEnum.UNSPECIFIED; - } - - /** - * 构造通用异常 - * - * @param errorCode 错误码 - * @param detailedMessage 详细描述 - */ - public BaseException(final ErrorCode errorCode, final String detailedMessage) { - super(detailedMessage); - this.errorCode = errorCode; - } - - /** - * 构造通用异常 - * - * @param errorCode 错误码 - * @param t 导火索 - */ - public BaseException(final ErrorCode errorCode, final Throwable t) { - super(errorCode.getDescription(), t); - this.errorCode = errorCode; - } - - /** - * 构造通用异常 - * - * @param detailedMessage 详细描述 - * @param t 导火索 - */ - public BaseException(final String detailedMessage, final Throwable t) { - super(detailedMessage, t); - this.errorCode = BaseCodeEnum.UNSPECIFIED; - } - - /** - * 构造通用异常 - * - * @param errorCode 错误码 - * @param detailedMessage 详细描述 - * @param t 导火索 - */ - public BaseException(final ErrorCode errorCode, final String detailedMessage, - final Throwable t) { - super(detailedMessage, t); - this.errorCode = errorCode; - } - - /** - * 获取错误码 - * - * @return - */ - public ErrorCode getErrorCode() { - return errorCode; - } -} diff --git a/core/src/main/java/com/dtstack/flink/sql/exception/ErrorCode.java b/core/src/main/java/com/dtstack/flink/sql/exception/ErrorCode.java deleted file mode 100644 index 4a5230135..000000000 --- a/core/src/main/java/com/dtstack/flink/sql/exception/ErrorCode.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.dtstack.flink.sql.exception; - -/** - * 错误码 - */ -public interface ErrorCode { - - /** - * 获取错误码 - * - * @return - */ - String getCode(); - - /** - * 获取错误信息 - * - * @return - */ - String getDescription(); -} \ No newline at end of file diff --git a/core/src/main/java/com/dtstack/flink/sql/exception/ExceptionTrace.java b/core/src/main/java/com/dtstack/flink/sql/exception/ExceptionTrace.java deleted file mode 100644 index 102aff550..000000000 --- a/core/src/main/java/com/dtstack/flink/sql/exception/ExceptionTrace.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.dtstack.flink.sql.exception; - -import org.apache.flink.runtime.execution.SuppressRestartsException; - -import java.util.Objects; - -/** - * @author tiezhu - * @date 2021/2/2 星期二 - * Company dtstack - */ -public class ExceptionTrace { - // 追溯当前异常的最原始异常信息 - public static String traceOriginalCause(Throwable e) { - String errorMsg; - if (Objects.nonNull(e.getCause())) { - errorMsg = traceOriginalCause(e.getCause()); - } else { - errorMsg = e.getMessage(); - } - return errorMsg; - } -} diff --git a/core/src/main/java/com/dtstack/flink/sql/exception/sqlparse/SqlParseCodeEnum.java b/core/src/main/java/com/dtstack/flink/sql/exception/sqlparse/SqlParseCodeEnum.java deleted file mode 100644 index c359cc42b..000000000 --- a/core/src/main/java/com/dtstack/flink/sql/exception/sqlparse/SqlParseCodeEnum.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.exception.sqlparse; - -import com.dtstack.flink.sql.exception.ErrorCode; - -/** - * @author: chuixue - * @create: 2020-11-30 16:56 - * @description:sql解析错误码 - **/ -public enum SqlParseCodeEnum implements ErrorCode { - /** - * 流join维表时,select、join、group by等字段未使用t.field - */ - WITHOUT_TABLENAME("001", "field invalid , please use like t.field"), - ; - - /** - * 错误码 - */ - private final String code; - - /** - * 描述 - */ - private final String description; - - /** - * @param code 错误码 - * @param description 描述 - */ - private SqlParseCodeEnum(final String code, final String description) { - this.code = code; - this.description = description; - } - - @Override - public String getCode() { - return code; - } - - @Override - public String getDescription() { - return description; - } -} diff --git a/core/src/main/java/com/dtstack/flink/sql/exec/ApiResult.java b/core/src/main/java/com/dtstack/flink/sql/exec/ApiResult.java deleted file mode 100644 index d67a39a40..000000000 --- a/core/src/main/java/com/dtstack/flink/sql/exec/ApiResult.java +++ /dev/null @@ -1,99 +0,0 @@ -package com.dtstack.flink.sql.exec; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * API调用结果返回 - * Date: 2020/2/24 - * Company: www.dtstack.com - * @author maqi - */ -public class ApiResult { - - private static final Logger LOG = LoggerFactory.getLogger(ApiResult.class); - private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); - - public static final Integer FAIL = 0; - public static final Integer SUCCESS = 1; - - private int code; - private long space; - private Object data; - private String errorMsg; - - public ApiResult() { - } - - public static String createSuccessResultJsonStr(String message,long space) { - ApiResult apiResult = createSuccessResult(SUCCESS, message); - apiResult.setSpace(space); - String result; - try { - result = OBJECT_MAPPER.writeValueAsString(apiResult); - } catch (Exception e) { - LOG.error("", e); - result = "code:" + SUCCESS + ",message:" + message; - } - return result; - } - - public static ApiResult createSuccessResult(int code, String message) { - ApiResult apiResult = new ApiResult(); - apiResult.setCode(code); - apiResult.setData(message); - return apiResult; - } - - public static String createErrorResultJsonStr(String message) { - ApiResult apiResult = createErrorResult(message, FAIL); - String result; - try { - result = OBJECT_MAPPER.writeValueAsString(apiResult); - } catch (Exception e) { - LOG.error("", e); - result = "code:" + FAIL + ",message:" + message; - } - return result; - } - - public static ApiResult createErrorResult(String errMsg, int code) { - ApiResult apiResult = new ApiResult(); - apiResult.setCode(code); - apiResult.setErrorMsg(errMsg); - return apiResult; - } - - public int getCode() { - return code; - } - - public void setCode(int code) { - this.code = code; - } - - public Object getData() { - return data; - } - - public void setData(Object data) { - this.data = data; - } - - public String getErrorMsg() { - return errorMsg; - } - - public void setErrorMsg(String errorMsg) { - this.errorMsg = errorMsg; - } - - public long getSpace() { - return space; - } - - public void setSpace(long space) { - this.space = space; - } -} diff --git a/core/src/main/java/com/dtstack/flink/sql/exec/ExecuteProcessHelper.java b/core/src/main/java/com/dtstack/flink/sql/exec/ExecuteProcessHelper.java deleted file mode 100644 index 1f84926bf..000000000 --- a/core/src/main/java/com/dtstack/flink/sql/exec/ExecuteProcessHelper.java +++ /dev/null @@ -1,460 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.exec; - -import com.dtstack.flink.sql.classloader.ClassLoaderManager; -import com.dtstack.flink.sql.dirtyManager.manager.DirtyDataManager; -import com.dtstack.flink.sql.dirtyManager.manager.DirtyKeys; -import com.dtstack.flink.sql.enums.ClusterMode; -import com.dtstack.flink.sql.enums.ECacheType; -import com.dtstack.flink.sql.enums.EPluginLoadMode; -import com.dtstack.flink.sql.environment.MyLocalStreamEnvironment; -import com.dtstack.flink.sql.environment.StreamEnvConfigManager; -import com.dtstack.flink.sql.function.FunctionManager; -import com.dtstack.flink.sql.option.OptionParser; -import com.dtstack.flink.sql.option.Options; -import com.dtstack.flink.sql.parser.CreateFuncParser; -import com.dtstack.flink.sql.parser.CreateTmpTableParser; -import com.dtstack.flink.sql.parser.FlinkPlanner; -import com.dtstack.flink.sql.parser.InsertSqlParser; -import com.dtstack.flink.sql.parser.SqlParser; -import com.dtstack.flink.sql.parser.SqlTree; -import com.dtstack.flink.sql.resource.ResourceCheck; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.SideSqlExec; -import com.dtstack.flink.sql.sink.StreamSinkFactory; -import com.dtstack.flink.sql.source.StreamSourceFactory; -import com.dtstack.flink.sql.table.AbstractSourceTableInfo; -import com.dtstack.flink.sql.table.AbstractTableInfo; -import com.dtstack.flink.sql.table.AbstractTargetTableInfo; -import com.dtstack.flink.sql.util.DtStringUtil; -import com.dtstack.flink.sql.util.PluginUtil; -import com.dtstack.flink.sql.util.TypeInfoDataTypeConverter; -import com.dtstack.flink.sql.watermarker.WaterMarkerAssigner; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.common.base.Preconditions; -import com.google.common.base.Strings; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import org.apache.calcite.sql.SqlInsert; -import org.apache.calcite.sql.SqlNode; -import org.apache.commons.io.Charsets; -import org.apache.commons.lang3.SerializationUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.streaming.api.datastream.DataStream; -import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; -import org.apache.flink.table.api.EnvironmentSettings; -import org.apache.flink.table.api.Table; -import org.apache.flink.table.api.TableConfig; -import org.apache.flink.table.api.TableEnvironment; -import org.apache.flink.table.api.java.StreamTableEnvironment; -import org.apache.flink.table.api.java.internal.StreamTableEnvironmentImpl; -import org.apache.flink.table.sinks.TableSink; -import org.apache.flink.table.types.DataType; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.lang.reflect.InvocationTargetException; -import java.net.URL; -import java.net.URLClassLoader; -import java.net.URLDecoder; -import java.time.ZoneId; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Properties; -import java.util.Set; -import java.util.TimeZone; -import java.util.stream.Stream; - -/** - * 任务执行时的流程方法 - * Date: 2020/2/17 - * Company: www.dtstack.com - * - * @author maqi - */ -public class ExecuteProcessHelper { - - private static final String CLASS_FILE_NAME_FMT = "class_path_%d"; - private static final Logger LOG = LoggerFactory.getLogger(ExecuteProcessHelper.class); - private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); - - private static final String TIME_ZONE = "timezone"; - private static final String PLUGIN_LOCAL_STR = "pluginPath"; - private static final String PLUGIN_LOAD_STR = "pluginLoadMode"; - - public static FlinkPlanner flinkPlanner = new FlinkPlanner(); - - @SuppressWarnings("unchecked") - public static ParamsInfo parseParams(String[] args) throws Exception { - LOG.info("------------program params-------------------------"); - Arrays.stream(args).forEach(arg -> LOG.info("{}", arg)); - LOG.info("-------------------------------------------"); - - OptionParser optionParser = new OptionParser(args); - Options options = optionParser.getOptions(); - - String sql = URLDecoder.decode(options.getSql(), Charsets.UTF_8.name()); - String name = options.getName(); - String localSqlPluginPath = options.getLocalSqlPluginPath(); - String remoteSqlPluginPath = options.getRemoteSqlPluginPath(); - String pluginLoadMode = options.getPluginLoadMode(); - String deployMode = options.getMode(); - String dirtyStr = options.getDirtyProperties(); - - Preconditions.checkArgument(checkRemoteSqlPluginPath(remoteSqlPluginPath, deployMode, pluginLoadMode), - "Non-local mode or shipfile deployment mode, remoteSqlPluginPath is required"); - String confProp = URLDecoder.decode(options.getConfProp(), Charsets.UTF_8.toString()); - Properties confProperties = PluginUtil.jsonStrToObject(confProp, Properties.class); - Map dirtyProperties = (Map) PluginUtil.jsonStrToObject(Objects.isNull(dirtyStr) ? - DirtyDataManager.buildDefaultDirty() : dirtyStr, Map.class); - - if (Objects.isNull(dirtyProperties.get(PLUGIN_LOAD_STR))) { - dirtyProperties.put(PLUGIN_LOAD_STR, pluginLoadMode); - } - - if (!pluginLoadMode.equalsIgnoreCase(EPluginLoadMode.LOCALTEST.name()) && Objects.isNull(dirtyProperties.get(PLUGIN_LOCAL_STR))) { - dirtyProperties.put(PLUGIN_LOCAL_STR, localSqlPluginPath); - } - - List jarUrlList = getExternalJarUrls(options.getAddjar()); - - return ParamsInfo.builder() - .setSql(sql) - .setName(name) - .setLocalSqlPluginPath(localSqlPluginPath) - .setRemoteSqlPluginPath(remoteSqlPluginPath) - .setPluginLoadMode(pluginLoadMode) - .setDeployMode(deployMode) - .setConfProp(confProperties) - .setJarUrlList(jarUrlList) - .setDirtyProperties(dirtyProperties) - .build(); - - } - - /** - * 非local模式或者shipfile部署模式,remoteSqlPluginPath必填 - * - * @param remoteSqlPluginPath - * @param deployMode - * @param pluginLoadMode - * @return - */ - public static boolean checkRemoteSqlPluginPath(String remoteSqlPluginPath, String deployMode, String pluginLoadMode) { - if (StringUtils.isEmpty(remoteSqlPluginPath)) { - return StringUtils.equalsIgnoreCase(pluginLoadMode, EPluginLoadMode.SHIPFILE.name()) - || StringUtils.equalsIgnoreCase(deployMode, ClusterMode.local.name()); - } - return true; - } - - - public static StreamExecutionEnvironment getStreamExecution(ParamsInfo paramsInfo) throws Exception { - StreamExecutionEnvironment env = ExecuteProcessHelper.getStreamExeEnv(paramsInfo.getConfProp(), paramsInfo.getDeployMode()); - StreamTableEnvironment tableEnv = getStreamTableEnv(env, paramsInfo.getConfProp()); - - ResourceCheck.NEED_CHECK = Boolean.parseBoolean(paramsInfo.getConfProp().getProperty(ResourceCheck.CHECK_STR, "false")); - - SqlParser.setLocalSqlPluginRoot(paramsInfo.getLocalSqlPluginPath()); - SqlTree sqlTree = SqlParser.parseSql(paramsInfo.getSql(), paramsInfo.getPluginLoadMode()); - - Map sideTableMap = Maps.newHashMap(); - Map registerTableCache = Maps.newHashMap(); - - //register udf - ExecuteProcessHelper.registerUserDefinedFunction(sqlTree, paramsInfo.getJarUrlList(), tableEnv, paramsInfo.isGetPlan()); - //register table schema - Set classPathSets = ExecuteProcessHelper.registerTable( - sqlTree - , env - , tableEnv - , paramsInfo.getLocalSqlPluginPath() - , paramsInfo.getRemoteSqlPluginPath() - , paramsInfo.getPluginLoadMode() - , paramsInfo.getDirtyProperties() - , sideTableMap - , registerTableCache); - // cache classPathSets - ExecuteProcessHelper.registerPluginUrlToCachedFile(env, classPathSets); - - ExecuteProcessHelper.sqlTranslation( - paramsInfo.getLocalSqlPluginPath(), - paramsInfo.getPluginLoadMode(), - tableEnv, - sqlTree, - sideTableMap, - registerTableCache); - - if (env instanceof MyLocalStreamEnvironment) { - ((MyLocalStreamEnvironment) env).setClasspaths(ClassLoaderManager.getClassPath()); - } - return env; - } - - @SuppressWarnings("unchecked") - public static List getExternalJarUrls(String addJarListStr) throws java.io.IOException { - List jarUrlList = Lists.newArrayList(); - if (Strings.isNullOrEmpty(addJarListStr)) { - return jarUrlList; - } - - List addJarFileList = OBJECT_MAPPER.readValue(URLDecoder.decode(addJarListStr, Charsets.UTF_8.name()), List.class); - //Get External jar to load - for (String addJarPath : addJarFileList) { - jarUrlList.add(new File(addJarPath).toURI().toURL()); - } - return jarUrlList; - } - - private static void sqlTranslation(String localSqlPluginPath, - String pluginLoadMode, - StreamTableEnvironment tableEnv, - SqlTree sqlTree, - Map sideTableMap, - Map registerTableCache) throws Exception { - - SideSqlExec sideSqlExec = new SideSqlExec(); - sideSqlExec.setLocalSqlPluginPath(localSqlPluginPath); - sideSqlExec.setPluginLoadMode(pluginLoadMode); - - int scope = 0; - for (CreateTmpTableParser.SqlParserResult result : sqlTree.getTmpSqlList()) { - sideSqlExec.exec(result.getExecSql(), sideTableMap, tableEnv, registerTableCache, result, scope + ""); - scope++; - } - - final Map tmpTableMap = new HashMap<>(); - for (InsertSqlParser.SqlParseResult result : sqlTree.getExecSqlList()) { - // prevent current sql use last sql's sideTableInfo - sideTableMap.forEach((s, abstractSideTableInfo) -> tmpTableMap.put(s, SerializationUtils.clone(abstractSideTableInfo))); - - if (LOG.isInfoEnabled()) { - LOG.info("exe-sql:\n" + result.getExecSql()); - } - boolean isSide = false; - for (String tableName : result.getTargetTableList()) { - if (sqlTree.getTmpTableMap().containsKey(tableName)) { - CreateTmpTableParser.SqlParserResult tmp = sqlTree.getTmpTableMap().get(tableName); - String realSql = DtStringUtil.replaceIgnoreQuota(result.getExecSql(), "`", ""); - - SqlNode sqlNode = flinkPlanner.getParser().parse(realSql); - String tmpSql = ((SqlInsert) sqlNode).getSource().toString(); - tmp.setExecSql(tmpSql); - sideSqlExec.exec(tmp.getExecSql(), tmpTableMap, tableEnv, registerTableCache, tmp, scope + ""); - } else { - for (String sourceTable : result.getSourceTableList()) { - if (tmpTableMap.containsKey(sourceTable)) { - isSide = true; - break; - } - } - if (isSide) { - //sql-dimensional table contains the dimension table of execution - sideSqlExec.exec(result.getExecSql(), tmpTableMap, tableEnv, registerTableCache, null, String.valueOf(scope)); - } else { - LOG.info("----------exec sql without dimension join-----------"); - LOG.info("----------real sql exec is--------------------------\n{}", result.getExecSql()); - - FlinkSQLExec.sqlInsert(tableEnv, result.getExecSql(), SideSqlExec.getDimTableNewTable().keySet() ); - if (LOG.isInfoEnabled()) { - LOG.info("exec sql: " + result.getExecSql()); - } - } - } - - scope++; - } - tmpTableMap.clear(); - } - } - - public static void registerUserDefinedFunction(SqlTree sqlTree, List jarUrlList, TableEnvironment tableEnv, boolean getPlan) - throws IllegalAccessException, InvocationTargetException { - // udf和tableEnv须由同一个类加载器加载 - ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader(); - URLClassLoader classLoader = ClassLoaderManager.loadExtraJar(jarUrlList, (URLClassLoader) currentClassLoader); - List funcList = sqlTree.getFunctionList(); - for (CreateFuncParser.SqlParserResult funcInfo : funcList) { - FunctionManager.registerUDF(funcInfo.getType(), funcInfo.getClassName(), funcInfo.getName(), tableEnv, classLoader); - } - } - - /** - * 向Flink注册源表和结果表,返回执行时插件包的全路径 - * - * @param sqlTree - * @param env - * @param tableEnv - * @param localSqlPluginPath - * @param remoteSqlPluginPath - * @param pluginLoadMode 插件加载模式 classpath or shipfile - * @param sideTableMap - * @param registerTableCache - * @return - * @throws Exception - */ - public static Set registerTable( - SqlTree sqlTree - , StreamExecutionEnvironment env - , StreamTableEnvironment tableEnv - , String localSqlPluginPath - , String remoteSqlPluginPath - , String pluginLoadMode - , Map dirtyProperties - , Map sideTableMap - , Map registerTableCache - ) throws Exception { - Set pluginClassPathSets = Sets.newHashSet(); - WaterMarkerAssigner waterMarkerAssigner = new WaterMarkerAssigner(); - for (AbstractTableInfo tableInfo : sqlTree.getTableInfoMap().values()) { - - // 配置dirty manager - tableInfo.setDirtyProperties(dirtyProperties); - - if (tableInfo instanceof AbstractSourceTableInfo) { - - AbstractSourceTableInfo sourceTableInfo = (AbstractSourceTableInfo) tableInfo; - Table table = StreamSourceFactory.getStreamSource(sourceTableInfo, env, tableEnv, localSqlPluginPath, pluginLoadMode); - tableEnv.registerTable(sourceTableInfo.getAdaptName(), table); - //Note --- parameter conversion function can not be used inside a function of the type of polymerization - //Create table in which the function is arranged only need adaptation sql - String adaptSql = sourceTableInfo.getAdaptSelectSql(); - Table adaptTable = adaptSql == null ? table : tableEnv.sqlQuery(adaptSql); - - RowTypeInfo typeInfo = new RowTypeInfo(fromDataTypeToLegacyInfo(adaptTable.getSchema().getFieldDataTypes()), adaptTable.getSchema().getFieldNames()); - DataStream adaptStream = tableEnv.toAppendStream(adaptTable, typeInfo); - - String fields = String.join(",", typeInfo.getFieldNames()); - - if (waterMarkerAssigner.checkNeedAssignWaterMarker(sourceTableInfo)) { - adaptStream = waterMarkerAssigner.assignWaterMarker(adaptStream, typeInfo, sourceTableInfo); - fields += ",ROWTIME.ROWTIME"; - } else { - fields += ",PROCTIME.PROCTIME"; - } - - Table regTable = tableEnv.fromDataStream(adaptStream, fields); - tableEnv.createTemporaryView(tableInfo.getName(), regTable); - if (LOG.isInfoEnabled()) { - LOG.info("registe table {} success.", tableInfo.getName()); - } - registerTableCache.put(tableInfo.getName(), regTable); - - URL sourceTablePathUrl = PluginUtil.buildSourceAndSinkPathByLoadMode(tableInfo.getType(), AbstractSourceTableInfo.SOURCE_SUFFIX, localSqlPluginPath, remoteSqlPluginPath, pluginLoadMode); - pluginClassPathSets.add(sourceTablePathUrl); - } else if (tableInfo instanceof AbstractTargetTableInfo) { - TableSink tableSink = StreamSinkFactory.getTableSink((AbstractTargetTableInfo) tableInfo, localSqlPluginPath, pluginLoadMode); - // TODO Kafka Sink直接注册,其他的Sink要修复才可以。 - if (tableInfo.getType().startsWith("kafka")) { - tableEnv.registerTableSink(tableInfo.getName(), tableSink); - } else { - TypeInformation[] flinkTypes = FunctionManager.transformTypes(tableInfo.getFieldClasses()); - tableEnv.registerTableSink(tableInfo.getName(), tableInfo.getFields(), flinkTypes, tableSink); - } - - URL sinkTablePathUrl = PluginUtil.buildSourceAndSinkPathByLoadMode(tableInfo.getType(), AbstractTargetTableInfo.TARGET_SUFFIX, localSqlPluginPath, remoteSqlPluginPath, pluginLoadMode); - pluginClassPathSets.add(sinkTablePathUrl); - } else if (tableInfo instanceof AbstractSideTableInfo) { - String sideOperator = ECacheType.ALL.name().equalsIgnoreCase(((AbstractSideTableInfo) tableInfo).getCacheType()) ? "all" : "async"; - sideTableMap.put(tableInfo.getName(), (AbstractSideTableInfo) tableInfo); - - URL sideTablePathUrl = PluginUtil.buildSidePathByLoadMode(tableInfo.getType(), sideOperator, AbstractSideTableInfo.TARGET_SUFFIX, localSqlPluginPath, remoteSqlPluginPath, pluginLoadMode); - pluginClassPathSets.add(sideTablePathUrl); - } else { - throw new RuntimeException("not support table type:" + tableInfo.getType()); - } - } - if (localSqlPluginPath == null || localSqlPluginPath.isEmpty()) { - return Sets.newHashSet(); - } - pluginClassPathSets.add(PluginUtil.buildDirtyPluginUrl( - String.valueOf(dirtyProperties.get(DirtyKeys.PLUGIN_TYPE_STR)), - localSqlPluginPath, - remoteSqlPluginPath, - pluginLoadMode - )); - return pluginClassPathSets; - } - - /** - * perjob模式将job依赖的插件包路径存储到cacheFile,在外围将插件包路径传递给jobgraph - * - * @param env - * @param classPathSet - */ - public static void registerPluginUrlToCachedFile(StreamExecutionEnvironment env, Set classPathSet) { - int i = 0; - for (URL url : classPathSet) { - String classFileName = String.format(CLASS_FILE_NAME_FMT, i); - env.registerCachedFile(url.getPath(), classFileName, true); - i++; - } - } - - public static StreamExecutionEnvironment getStreamExeEnv(Properties confProperties, String deployMode) throws Exception { - StreamExecutionEnvironment env = !ClusterMode.local.name().equals(deployMode) ? - StreamExecutionEnvironment.getExecutionEnvironment() : - new MyLocalStreamEnvironment(); - - StreamEnvConfigManager.streamExecutionEnvironmentConfig(env, confProperties); - return env; - } - - - public static StreamTableEnvironment getStreamTableEnv(StreamExecutionEnvironment env, Properties confProperties) { - // use blink and streammode - EnvironmentSettings settings = EnvironmentSettings.newInstance() - .useBlinkPlanner() - .inStreamingMode() - .build(); - - TableConfig tableConfig = new TableConfig(); - - timeZoneCheck(confProperties.getProperty(TIME_ZONE, TimeZone.getDefault().getID())); - - tableConfig.setLocalTimeZone(ZoneId.of(confProperties.getProperty(TIME_ZONE, TimeZone.getDefault().getID()))); - - StreamTableEnvironment tableEnv = StreamTableEnvironmentImpl.create(env, settings, tableConfig); - StreamEnvConfigManager.streamTableEnvironmentStateTTLConfig(tableEnv, confProperties); - StreamEnvConfigManager.streamTableEnvironmentEarlyTriggerConfig(tableEnv, confProperties); - return tableEnv; - } - - private static void timeZoneCheck(String timeZone) { - ArrayList zones = Lists.newArrayList(TimeZone.getAvailableIDs()); - if (!zones.contains(timeZone)) { - throw new IllegalArgumentException(String.format(" timezone of %s is Incorrect!", timeZone)); - } - } - - private static TypeInformation[] fromDataTypeToLegacyInfo(DataType[] dataType) { - return Stream.of(dataType) - .map(TypeInfoDataTypeConverter::toLegacyTypeInfo) - .toArray(TypeInformation[]::new); - } -} \ No newline at end of file diff --git a/core/src/main/java/com/dtstack/flink/sql/exec/FlinkSQLExec.java b/core/src/main/java/com/dtstack/flink/sql/exec/FlinkSQLExec.java index e99404c87..6bcc25251 100644 --- a/core/src/main/java/com/dtstack/flink/sql/exec/FlinkSQLExec.java +++ b/core/src/main/java/com/dtstack/flink/sql/exec/FlinkSQLExec.java @@ -18,143 +18,67 @@ package com.dtstack.flink.sql.exec; -import com.dtstack.flink.sql.util.TableUtils; import org.apache.calcite.sql.SqlIdentifier; +import org.apache.calcite.sql.SqlInsert; import org.apache.calcite.sql.SqlNode; -import org.apache.flink.sql.parser.dml.RichSqlInsert; import org.apache.flink.table.api.Table; -import org.apache.flink.table.api.internal.TableEnvironmentImpl; -import org.apache.flink.table.api.internal.TableImpl; +import org.apache.flink.table.api.TableEnvironment; +import org.apache.flink.table.api.TableException; +import org.apache.flink.table.api.ValidationException; import org.apache.flink.table.api.java.StreamTableEnvironment; -import org.apache.flink.table.api.java.internal.StreamTableEnvironmentImpl; -import org.apache.flink.table.catalog.ObjectIdentifier; -import org.apache.flink.table.operations.Operation; -import org.apache.flink.table.operations.QueryOperation; -import org.apache.flink.table.planner.calcite.FlinkPlannerImpl; -import org.apache.flink.table.planner.delegation.PlannerBase; -import org.apache.flink.table.planner.delegation.StreamPlanner; -import org.apache.flink.table.planner.operations.SqlToOperationConverter; -import org.apache.flink.table.planner.plan.QueryOperationConverter; -import org.apache.flink.table.sinks.TableSink; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.apache.flink.table.calcite.FlinkPlannerImpl; +import org.apache.flink.table.plan.logical.LogicalRelNode; +import org.apache.flink.table.plan.schema.TableSinkTable; +import org.apache.flink.table.plan.schema.TableSourceSinkTable; import scala.Option; -import scala.Tuple2; -import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.Collection; - /** - * @description: mapping by name when insert into sink table + * @description: mapping by name when insert into sink table * @author: maqi * @create: 2019/08/15 11:09 */ public class FlinkSQLExec { - private static final Logger LOG = LoggerFactory.getLogger(FlinkSQLExec.class); - - public static void sqlInsert(StreamTableEnvironment tableEnv, SqlNode sqlNode, Collection newRegisterTableList) throws Exception{ - boolean isGroupByTimeWindow = TableUtils.checkIsDimTableGroupBy(sqlNode, newRegisterTableList); - if(isGroupByTimeWindow){ - QueryOperationConverter.setProducesUpdates(true); - } - sqlInsert(tableEnv, (RichSqlInsert) sqlNode); - QueryOperationConverter.setProducesUpdates(false); - } + public static void sqlUpdate(StreamTableEnvironment tableEnv, String stmt) throws Exception { - public static void sqlInsert(StreamTableEnvironment tableEnv, String stmt, Collection newRegisterTableList) throws Exception{ - StreamTableEnvironmentImpl tableEnvImpl = ((StreamTableEnvironmentImpl) tableEnv); - StreamPlanner streamPlanner = (StreamPlanner) tableEnvImpl.getPlanner(); - FlinkPlannerImpl flinkPlanner = streamPlanner.createFlinkPlanner(); + FlinkPlannerImpl planner = new FlinkPlannerImpl(tableEnv.getFrameworkConfig(), tableEnv.getPlanner(), tableEnv.getTypeFactory()); + SqlNode insert = planner.parse(stmt); - RichSqlInsert insert = (RichSqlInsert) flinkPlanner.validate(flinkPlanner.parser().parse(stmt)); - boolean isGroupByTimeWindow = TableUtils.checkIsDimTableGroupBy(insert, newRegisterTableList); - if(isGroupByTimeWindow){ - QueryOperationConverter.setProducesUpdates(true); + if (!(insert instanceof SqlInsert)) { + throw new TableException( + "Unsupported SQL query! sqlUpdate() only accepts SQL statements of type INSERT."); } + SqlNode query = ((SqlInsert) insert).getSource(); - sqlInsert(tableEnv, insert); - QueryOperationConverter.setProducesUpdates(false); - } + SqlNode validatedQuery = planner.validate(query); - public static Table sqlQuery(StreamTableEnvironment tableEnv, SqlNode sqlNode, Collection newRegisterTableList){ - boolean isGroupByTimeWindow = TableUtils.checkIsDimTableGroupBy(sqlNode, newRegisterTableList); - if(isGroupByTimeWindow){ - QueryOperationConverter.setProducesUpdates(true); - } + Table queryResult = new Table(tableEnv, new LogicalRelNode(planner.rel(validatedQuery).rel)); + String targetTableName = ((SqlIdentifier) ((SqlInsert) insert).getTargetTable()).names.get(0); - Table resultTable = tableEnv.sqlQuery(sqlNode.toString()); - QueryOperationConverter.setProducesUpdates(false); - return resultTable; - } + Method method = TableEnvironment.class.getDeclaredMethod("getTable", String.class); + method.setAccessible(true); + Option sinkTab = (Option)method.invoke(tableEnv, targetTableName); - public static void insertInto(StreamTableEnvironment tableEnv, - SqlNode sqlNode, - String targetTableName, - Table fromTable, - Collection newRegisterTableList){ - boolean isGroupByTimeWindow = TableUtils.checkIsDimTableGroupBy(sqlNode, newRegisterTableList); - if(isGroupByTimeWindow){ - QueryOperationConverter.setProducesUpdates(true); + if (sinkTab.isEmpty()) { + throw new ValidationException("Sink table " + targetTableName + "not found in flink"); } - tableEnv.insertInto(targetTableName, fromTable); - QueryOperationConverter.setProducesUpdates(false); - } - - public static void sqlInsert(StreamTableEnvironment tableEnv, RichSqlInsert insert) throws Exception { - StreamTableEnvironmentImpl tableEnvImpl = ((StreamTableEnvironmentImpl) tableEnv); - StreamPlanner streamPlanner = (StreamPlanner) tableEnvImpl.getPlanner(); - FlinkPlannerImpl flinkPlanner = streamPlanner.createFlinkPlanner(); - - TableImpl queryResult = extractQueryTableFromInsertCaluse(tableEnvImpl, flinkPlanner, insert); - String targetTableName = ((SqlIdentifier) insert.getTargetTable()).names.get(0); - TableSink tableSink = getTableSinkByPlanner(streamPlanner, targetTableName); + TableSourceSinkTable targetTable = (TableSourceSinkTable) sinkTab.get(); + TableSinkTable tableSinkTable = (TableSinkTable)targetTable.tableSinkTable().get(); + String[] fieldNames = tableSinkTable.tableSink().getFieldNames(); - String[] sinkFieldNames = tableSink.getTableSchema().getFieldNames(); - String[] queryFieldNames = queryResult.getSchema().getFieldNames(); - Table newTable; + Table newTable = null; try { - newTable = queryResult.select(String.join(",", sinkFieldNames)); - tableEnv.insertInto(targetTableName, newTable); + newTable = queryResult.select(String.join(",", fieldNames)); } catch (Exception e) { - LOG.warn(String.format("Query result and registered TableSink do not match \n input field list:%s \n output field list:%s ", Arrays.toString(queryFieldNames), Arrays.toString(sinkFieldNames))); - newTable = queryResult.select(String.join(",", ignoreCase(queryFieldNames, sinkFieldNames))); - tableEnv.insertInto(targetTableName, newTable); + throw new ValidationException( + "Field name of query result and registered TableSink "+targetTableName +" do not match.\n" + + "Query result schema: " + String.join(",", queryResult.getSchema().getColumnNames()) + "\n" + + "TableSink schema: " + String.join(",", fieldNames)); } - } - - private static TableSink getTableSinkByPlanner(StreamPlanner streamPlanner, String targetTableName) - throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { - Method getTableSink = PlannerBase.class.getDeclaredMethod("getTableSink", ObjectIdentifier.class); - getTableSink.setAccessible(true); - ObjectIdentifier objectIdentifier = ObjectIdentifier.of(streamPlanner.catalogManager().getCurrentCatalog(), streamPlanner.catalogManager().getCurrentDatabase(), targetTableName); - Option tableSinkOption = (Option) getTableSink.invoke(streamPlanner, objectIdentifier); - return (TableSink) ((Tuple2) tableSinkOption.get())._2; - } - - private static TableImpl extractQueryTableFromInsertCaluse(StreamTableEnvironmentImpl tableEnvImpl, FlinkPlannerImpl flinkPlanner, RichSqlInsert insert) - throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { - StreamPlanner streamPlanner = (StreamPlanner) tableEnvImpl.getPlanner(); - Operation queryOperation = SqlToOperationConverter.convert(flinkPlanner, streamPlanner.catalogManager(), insert.getSource()).get(); - Method createTableMethod = TableEnvironmentImpl.class.getDeclaredMethod("createTable", QueryOperation.class); - createTableMethod.setAccessible(true); - return (TableImpl) createTableMethod.invoke(tableEnvImpl, queryOperation); - } - private static String[] ignoreCase(String[] queryFieldNames, String[] sinkFieldNames) { - String[] newFieldNames = sinkFieldNames; - for (int i = 0; i < newFieldNames.length; i++) { - for (String queryFieldName : queryFieldNames) { - if (newFieldNames[i].equalsIgnoreCase(queryFieldName)) { - newFieldNames[i] = queryFieldName; - break; - } - } - } - return newFieldNames; + tableEnv.insertInto(newTable, targetTableName, tableEnv.queryConfig()); } } \ No newline at end of file diff --git a/core/src/main/java/com/dtstack/flink/sql/exec/ParamsInfo.java b/core/src/main/java/com/dtstack/flink/sql/exec/ParamsInfo.java deleted file mode 100644 index aaff5a12a..000000000 --- a/core/src/main/java/com/dtstack/flink/sql/exec/ParamsInfo.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.exec; - - -import java.net.URL; -import java.util.List; -import java.util.Map; -import java.util.Properties; - -/** - * 解析传递的参数信息 - * Date: 2020/2/24 - * Company: www.dtstack.com - * - * @author maqi - */ -public class ParamsInfo { - - private String sql; - private String name; - private List jarUrlList; - private String localSqlPluginPath; - private String remoteSqlPluginPath; - private String pluginLoadMode; - private String deployMode; - private Properties confProp; - private boolean getPlan = false; - private Map dirtyProperties; - - public ParamsInfo( - String sql - , String name, List jarUrlList - , String localSqlPluginPath - , String remoteSqlPluginPath - , String pluginLoadMode - , String deployMode - , Properties confProp - , Map dirtyProperties) { - this.sql = sql; - this.name = name; - this.jarUrlList = jarUrlList; - this.localSqlPluginPath = localSqlPluginPath; - this.remoteSqlPluginPath = remoteSqlPluginPath; - this.pluginLoadMode = pluginLoadMode; - this.deployMode = deployMode; - this.confProp = confProp; - this.dirtyProperties = dirtyProperties; - } - - public static ParamsInfo.Builder builder() { - return new ParamsInfo.Builder(); - } - - public boolean isGetPlan() { - return getPlan; - } - - public void setGetPlan(boolean getPlan) { - this.getPlan = getPlan; - } - - public String getSql() { - return sql; - } - - public String getName() { - return name; - } - - public List getJarUrlList() { - return jarUrlList; - } - - public String getLocalSqlPluginPath() { - return localSqlPluginPath; - } - - public String getRemoteSqlPluginPath() { - return remoteSqlPluginPath; - } - - public String getPluginLoadMode() { - return pluginLoadMode; - } - - public String getDeployMode() { - return deployMode; - } - - public Properties getConfProp() { - return confProp; - } - - public Map getDirtyProperties() { - return dirtyProperties; - } - - @Override - public String toString() { - return "ParamsInfo{" + - "sql='" + sql + '\'' + - ", name='" + name + '\'' + - ", jarUrlList=" + jarUrlList + - ", localSqlPluginPath='" + localSqlPluginPath + '\'' + - ", remoteSqlPluginPath='" + remoteSqlPluginPath + '\'' + - ", pluginLoadMode='" + pluginLoadMode + '\'' + - ", deployMode='" + deployMode + '\'' + - ", confProp=" + confProp + - ", getPlan=" + getPlan + - ", dirtyProperties='" + dirtyProperties + '\'' + - '}'; - } - - public String convertJarUrlListToString(List jarUrlList) { - return jarUrlList.stream().map(URL::toString).reduce((pre, last) -> pre + last).orElse(""); - } - - public static class Builder { - - private String sql; - private String name; - private List jarUrlList; - private String localSqlPluginPath; - private String remoteSqlPluginPath; - private String pluginLoadMode; - private String deployMode; - private Properties confProp; - private Map dirtyProperties; - - public ParamsInfo.Builder setSql(String sql) { - this.sql = sql; - return this; - } - - public ParamsInfo.Builder setName(String name) { - this.name = name; - return this; - } - - public ParamsInfo.Builder setJarUrlList(List jarUrlList) { - this.jarUrlList = jarUrlList; - return this; - } - - public ParamsInfo.Builder setLocalSqlPluginPath(String localSqlPluginPath) { - this.localSqlPluginPath = localSqlPluginPath; - return this; - } - - public ParamsInfo.Builder setRemoteSqlPluginPath(String remoteSqlPluginPath) { - this.remoteSqlPluginPath = remoteSqlPluginPath; - return this; - } - - public ParamsInfo.Builder setPluginLoadMode(String pluginLoadMode) { - this.pluginLoadMode = pluginLoadMode; - return this; - } - - public ParamsInfo.Builder setDeployMode(String deployMode) { - this.deployMode = deployMode; - return this; - } - - - public ParamsInfo.Builder setConfProp(Properties confProp) { - this.confProp = confProp; - return this; - } - - public ParamsInfo.Builder setDirtyProperties(Map dirtyProperties) { - this.dirtyProperties = dirtyProperties; - return this; - } - - public ParamsInfo build() { - return new ParamsInfo( - sql - , name - , jarUrlList - , localSqlPluginPath - , remoteSqlPluginPath - , pluginLoadMode - , deployMode - , confProp - , dirtyProperties); - } - } -} diff --git a/core/src/main/java/com/dtstack/flink/sql/factory/DTThreadFactory.java b/core/src/main/java/com/dtstack/flink/sql/factory/DTThreadFactory.java index ec4065f40..e9f9dfa64 100644 --- a/core/src/main/java/com/dtstack/flink/sql/factory/DTThreadFactory.java +++ b/core/src/main/java/com/dtstack/flink/sql/factory/DTThreadFactory.java @@ -16,6 +16,7 @@ * limitations under the License. */ + package com.dtstack.flink.sql.factory; @@ -32,7 +33,6 @@ public class DTThreadFactory implements ThreadFactory { private final static AtomicInteger THREAD_NUMBER = new AtomicInteger(1); private final ThreadGroup group; private final String namePrefix; - private Boolean isDaemon = false; public DTThreadFactory(String factoryName) { SecurityManager s = System.getSecurityManager(); @@ -43,29 +43,14 @@ public DTThreadFactory(String factoryName) { "-thread-"; } - public DTThreadFactory(String factoryName, Boolean isDaemon) { - SecurityManager s = System.getSecurityManager(); - group = (s != null) ? s.getThreadGroup() : - Thread.currentThread().getThreadGroup(); - namePrefix = factoryName + "-pool-" + - POOL_NUMBER.getAndIncrement() + - "-thread-"; - this.isDaemon = isDaemon; - } - @Override public Thread newThread(Runnable r) { Thread t = new Thread(group, r, namePrefix + THREAD_NUMBER.getAndIncrement(), 0); - if (this.isDaemon) { - t.setDaemon(true); - } else { - if (t.isDaemon()) { - t.setDaemon(false); - } + if (t.isDaemon()) { + t.setDaemon(false); } - if (t.getPriority() != Thread.NORM_PRIORITY) { t.setPriority(Thread.NORM_PRIORITY); } diff --git a/core/src/main/java/com/dtstack/flink/sql/format/DeserializationMetricWrapper.java b/core/src/main/java/com/dtstack/flink/sql/format/DeserializationMetricWrapper.java deleted file mode 100644 index 39c58c075..000000000 --- a/core/src/main/java/com/dtstack/flink/sql/format/DeserializationMetricWrapper.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.format; - -import com.dtstack.flink.sql.dirtyManager.manager.DirtyDataManager; -import com.dtstack.flink.sql.exception.ExceptionTrace; -import com.dtstack.flink.sql.metric.MetricConstant; -import org.apache.flink.api.common.functions.RuntimeContext; -import org.apache.flink.api.common.serialization.AbstractDeserializationSchema; -import org.apache.flink.api.common.serialization.DeserializationSchema; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.metrics.Counter; -import org.apache.flink.metrics.Meter; -import org.apache.flink.metrics.MeterView; -import org.apache.flink.types.Row; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.nio.charset.StandardCharsets; - -/** - * add metric for source - *

- * company: www.dtstack.com - * author: toutian - * create: 2019/12/24 - */ -public class DeserializationMetricWrapper extends AbstractDeserializationSchema { - - private static final Logger LOG = LoggerFactory.getLogger(DeserializationMetricWrapper.class); - - private static int dataPrintFrequency = 1000; - - private DeserializationSchema deserializationSchema; - - private transient RuntimeContext runtimeContext; - - protected transient Counter dirtyDataCounter; - - /** - * tps ransactions Per Second - */ - protected transient Counter numInRecord; - - protected transient Meter numInRate; - - /** - * rps Record Per Second: deserialize data and out record num - */ - protected transient Counter numInResolveRecord; - - protected transient Meter numInResolveRate; - - protected transient Counter numInBytes; - - protected transient Meter numInBytesRate; - - protected DirtyDataManager dirtyDataManager; - - public DeserializationMetricWrapper( - TypeInformation typeInfo - , DeserializationSchema deserializationSchema - , DirtyDataManager dirtyDataManager) { - super(typeInfo); - this.deserializationSchema = deserializationSchema; - this.dirtyDataManager = dirtyDataManager; - } - - public void initMetric() { - dirtyDataCounter = runtimeContext.getMetricGroup().counter(MetricConstant.DT_DIRTY_DATA_COUNTER); - - numInRecord = runtimeContext.getMetricGroup().counter(MetricConstant.DT_NUM_RECORDS_IN_COUNTER); - numInRate = runtimeContext.getMetricGroup().meter(MetricConstant.DT_NUM_RECORDS_IN_RATE, new MeterView(numInRecord, 20)); - - numInBytes = runtimeContext.getMetricGroup().counter(MetricConstant.DT_NUM_BYTES_IN_COUNTER); - numInBytesRate = runtimeContext.getMetricGroup().meter(MetricConstant.DT_NUM_BYTES_IN_RATE, new MeterView(numInBytes, 20)); - - numInResolveRecord = runtimeContext.getMetricGroup().counter(MetricConstant.DT_NUM_RECORDS_RESOVED_IN_COUNTER); - numInResolveRate = runtimeContext.getMetricGroup().meter(MetricConstant.DT_NUM_RECORDS_RESOVED_IN_RATE, new MeterView(numInResolveRecord, 20)); - } - - @Override - public Row deserialize(byte[] message) throws IOException { - try { - if (numInRecord.getCount() % dataPrintFrequency == 0) { - LOG.info("receive source data:" + new String(message, StandardCharsets.UTF_8)); - } - numInRecord.inc(); - numInBytes.inc(message.length); - beforeDeserialize(); - Row row = deserializationSchema.deserialize(message); - afterDeserialize(); - numInResolveRecord.inc(); - return row; - } catch (Exception e) { - //add metric of dirty data - dirtyDataManager.execute(); - dirtyDataManager.collectDirtyData( - new String(message), ExceptionTrace.traceOriginalCause(e)); - dirtyDataCounter.inc(); - return null; - } - } - - protected void beforeDeserialize() throws IOException { - } - - protected void afterDeserialize() throws IOException { - } - - public DeserializationSchema getDeserializationSchema() { - return deserializationSchema; - } - - public RuntimeContext getRuntimeContext() { - return runtimeContext; - } - - public void setRuntimeContext(RuntimeContext runtimeContext) { - this.runtimeContext = runtimeContext; - } -} diff --git a/core/src/main/java/com/dtstack/flink/sql/format/FormatType.java b/core/src/main/java/com/dtstack/flink/sql/format/FormatType.java deleted file mode 100644 index 532e18dc4..000000000 --- a/core/src/main/java/com/dtstack/flink/sql/format/FormatType.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.format; - -/** - * indicate source table input data format type - * company: www.dtstack.com - * author: toutian - * create: 2019/12/24 - */ -public enum FormatType { - //Indicates that the data is in nest json format(default) - DT_NEST, - //Indicates that the data is in json format - JSON, - //Indicates that the data is in avro format - AVRO, - //Indicates that the data is in csv format - CSV -} diff --git a/core/src/main/java/com/dtstack/flink/sql/format/SerializationMetricWrapper.java b/core/src/main/java/com/dtstack/flink/sql/format/SerializationMetricWrapper.java deleted file mode 100644 index 9210ebb9a..000000000 --- a/core/src/main/java/com/dtstack/flink/sql/format/SerializationMetricWrapper.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.format; - -import com.dtstack.flink.sql.metric.MetricConstant; -import org.apache.flink.api.common.functions.RuntimeContext; -import org.apache.flink.api.common.serialization.SerializationSchema; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.metrics.Counter; -import org.apache.flink.metrics.Meter; -import org.apache.flink.metrics.MeterView; -import org.apache.flink.types.Row; - - -/** - * add metric for source - *

- * company: www.dtstack.com - * author: toutian - * create: 2019/12/24 - */ -public class SerializationMetricWrapper implements SerializationSchema> { - - private static final long serialVersionUID = 1L; - - private SerializationSchema> serializationSchema; - - private transient RuntimeContext runtimeContext; - - protected transient Counter dtNumRecordsOut; - - protected transient Meter dtNumRecordsOutRate; - - - public SerializationMetricWrapper(SerializationSchema> serializationSchema) { - this.serializationSchema = serializationSchema; - } - - public void initMetric() { - dtNumRecordsOut = runtimeContext.getMetricGroup().counter(MetricConstant.DT_NUM_RECORDS_OUT); - dtNumRecordsOutRate = runtimeContext.getMetricGroup().meter(MetricConstant.DT_NUM_RECORDS_OUT_RATE, new MeterView(dtNumRecordsOut, 20)); - } - - @Override - public byte[] serialize(Tuple2 element) { - beforeSerialize(); - byte[] row = serializationSchema.serialize(element); - afterSerialize(); - return row; - } - - protected void beforeSerialize() { - } - - protected void afterSerialize() { - dtNumRecordsOut.inc(); - } - - public RuntimeContext getRuntimeContext() { - return runtimeContext; - } - - public void setRuntimeContext(RuntimeContext runtimeContext) { - this.runtimeContext = runtimeContext; - } - - public SerializationSchema> getSerializationSchema() { - return serializationSchema; - } - -} diff --git a/core/src/main/java/com/dtstack/flink/sql/format/dtnest/DtNestRowDeserializationSchema.java b/core/src/main/java/com/dtstack/flink/sql/format/dtnest/DtNestRowDeserializationSchema.java deleted file mode 100644 index 17764fdd6..000000000 --- a/core/src/main/java/com/dtstack/flink/sql/format/dtnest/DtNestRowDeserializationSchema.java +++ /dev/null @@ -1,283 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.format.dtnest; - -import com.dtstack.flink.sql.table.AbstractTableInfo; -import com.google.common.base.Strings; -import com.google.common.collect.Maps; -import org.apache.flink.api.common.serialization.AbstractDeserializationSchema; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.common.typeinfo.Types; -import org.apache.flink.api.java.typeutils.ObjectArrayTypeInfo; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.core.JsonProcessingException; -import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.JsonNode; -import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.ObjectMapper; -import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.node.ArrayNode; -import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.node.NullNode; -import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.node.ObjectNode; -import org.apache.flink.types.Row; - -import java.io.IOException; -import java.lang.reflect.Array; -import java.sql.Clob; -import java.sql.Date; -import java.sql.NClob; -import java.sql.Time; -import java.sql.Timestamp; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.regex.Pattern; - -/** - * source data parse to json format - *

- * Date: 2019/12/12 - * Company: www.dtstack.com - * - * @author maqi - */ -public class DtNestRowDeserializationSchema extends AbstractDeserializationSchema { - - private final ObjectMapper objectMapper = new ObjectMapper(); - - private final Map rowAndFieldMapping; - private final Map nodeAndJsonNodeMapping = Maps.newHashMap(); - - private final String[] fieldNames; - private final TypeInformation[] fieldTypes; - private TypeInformation typeInfo; - private final List fieldExtraInfos; - private final String charsetName; - - private static final Pattern TIMESTAMP_PATTERN = Pattern.compile("^\\d+$"); - private static final Pattern TIMESTAMP_FORMAT_PATTERN = Pattern.compile("[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}?.*"); - private static final Pattern TIME_FORMAT_PATTERN = Pattern.compile("[0-9]{2}:[0-9]{2}:[0-9]{2}?.*"); - private static final Pattern DATE_FORMAT_PATTERN = Pattern.compile("[0-9]{4}-[0-9]{2}-[0-9]{2}"); - - public DtNestRowDeserializationSchema(TypeInformation typeInfo, Map rowAndFieldMapping, - List fieldExtraInfos, - String charsetName) { - this.typeInfo = typeInfo; - this.fieldNames = ((RowTypeInfo) typeInfo).getFieldNames(); - this.fieldTypes = ((RowTypeInfo) typeInfo).getFieldTypes(); - this.rowAndFieldMapping = rowAndFieldMapping; - this.fieldExtraInfos = fieldExtraInfos; - this.charsetName = charsetName; - } - - @Override - public Row deserialize(byte[] message) throws IOException { - String decoderStr = new String(message, charsetName); - JsonNode root = objectMapper.readTree(decoderStr); - this.parseTree(root, null); - return convertTopRow(); - } - - private void parseTree(JsonNode jsonNode, String prefix) { - if (jsonNode.isArray()) { - ArrayNode array = (ArrayNode) jsonNode; - for (int i = 0; i < array.size(); i++) { - JsonNode child = array.get(i); - String nodeKey = getNodeKey(prefix, i); - - if (child.isValueNode()) { - nodeAndJsonNodeMapping.put(nodeKey, child); - } else { - if (rowAndFieldMapping.containsValue(nodeKey)) { - nodeAndJsonNodeMapping.put(nodeKey, child); - } - parseTree(child, nodeKey); - } - } - return; - } - Iterator iterator = jsonNode.fieldNames(); - while (iterator.hasNext()) { - String next = iterator.next(); - JsonNode child = jsonNode.get(next); - String nodeKey = getNodeKey(prefix, next); - - nodeAndJsonNodeMapping.put(nodeKey, child); - parseTree(child, nodeKey); - } - } - - private JsonNode getIgnoreCase(String key) { - String nodeMappingKey = rowAndFieldMapping.getOrDefault(key, key); - return nodeAndJsonNodeMapping.get(nodeMappingKey); - } - - private String getNodeKey(String prefix, String nodeName) { - if (Strings.isNullOrEmpty(prefix)) { - return nodeName; - } - return prefix + "." + nodeName; - } - - private String getNodeKey(String prefix, int i) { - if (Strings.isNullOrEmpty(prefix)) { - return "[" + i + "]"; - } - return prefix + "[" + i + "]"; - } - - private Object convert(JsonNode node, TypeInformation info) { - if (info.getTypeClass().equals(Types.BOOLEAN.getTypeClass())) { - return node.asBoolean(); - } else if (info.getTypeClass().equals(Types.STRING.getTypeClass())) { - if (node instanceof ObjectNode) { - return node.toString(); - } else if (node instanceof NullNode) { - return null; - } else { - return node.asText(); - } - } else if (info.getTypeClass().equals(Clob.class)) { - return node.asText(); - } else if (info.getTypeClass().equals(NClob.class)) { - return node.asText(); - } else if (info.getTypeClass().equals(Types.SQL_DATE.getTypeClass())) { - return convertToDate(node.asText()); - } else if (info.getTypeClass().equals(Types.SQL_TIME.getTypeClass())) { - // local zone - return convertToTime(node.asText()); - } else if (info.getTypeClass().equals(Types.SQL_TIMESTAMP.getTypeClass())) { - // local zone - return convertToTimestamp(node.asText()); - } else if (info instanceof RowTypeInfo) { - return convertRow(node, (RowTypeInfo) info); - } else if (info instanceof ObjectArrayTypeInfo) { - return convertObjectArray(node, ((ObjectArrayTypeInfo) info).getComponentInfo()); - } else { - // for types that were specified without JSON schema - // e.g. POJOs - try { - return objectMapper.treeToValue(node, info.getTypeClass()); - } catch (JsonProcessingException e) { - throw new IllegalStateException("Unsupported type information '" + info + "' for node: " + node); - } - } - } - - /** 将 2020-09-07 14:49:10.0 和 1598446699685 两种格式都转化为 Timestamp */ - private Timestamp convertToTimestamp(String timestamp) { - if (TIMESTAMP_PATTERN.matcher(timestamp).find()) { - return new Timestamp(Long.parseLong(timestamp)); - } - if (TIMESTAMP_FORMAT_PATTERN.matcher(timestamp).find()) { - return Timestamp.valueOf(timestamp); - } - throw new IllegalArgumentException( - String.format( - "Incorrect timestamp format [yyyy-MM-dd hh:mm:ss] of timestamp type. Input value: [%s]", - timestamp)); - } - - private Date convertToDate(String date) { - if (TIMESTAMP_PATTERN.matcher(date).find()) { - return new Date(Long.parseLong(date)); - } - if (TIMESTAMP_FORMAT_PATTERN.matcher(date).find()) { - return new Date(Timestamp.valueOf(date).getTime()); - } - if (DATE_FORMAT_PATTERN.matcher(date).find()) { - return Date.valueOf(date); - } - throw new IllegalArgumentException( - String.format( - "Incorrect date format [yyyy-MM-dd] of date type. Input value: [%s]", - date)); - } - - private Time convertToTime(String timestamp) { - if (TIMESTAMP_PATTERN.matcher(timestamp).find()) { - return new Time(Long.parseLong(timestamp)); - } - if (TIMESTAMP_FORMAT_PATTERN.matcher(timestamp).find()) { - long time = Timestamp.valueOf(timestamp).getTime(); - return new Time(time); - } - if (TIME_FORMAT_PATTERN.matcher(timestamp).find()) { - return Time.valueOf(timestamp); - } - throw new IllegalArgumentException( - String.format( - "Incorrect time format [hh:mm:ss] of time type. Input value: [%s]", - timestamp)); - } - - private Row convertTopRow() { - Row row = new Row(fieldNames.length); - try { - for (int i = 0; i < fieldNames.length; i++) { - JsonNode node = getIgnoreCase(fieldNames[i]); - AbstractTableInfo.FieldExtraInfo fieldExtraInfo = fieldExtraInfos.get(i); - - if (node == null || node instanceof NullNode) { - if (fieldExtraInfo != null && fieldExtraInfo.getNotNull()) { - throw new IllegalStateException("Failed to find field with name '" - + fieldNames[i] + "'."); - } else { - row.setField(i, null); - } - } else { - // Read the value as specified type - Object value = convert(node, fieldTypes[i]); - row.setField(i, value); - } - } - return row; - } finally { - nodeAndJsonNodeMapping.clear(); - } - } - - private Row convertRow(JsonNode node, RowTypeInfo info) { - final String[] names = info.getFieldNames(); - final TypeInformation[] types = info.getFieldTypes(); - - final Row row = new Row(names.length); - for (int i = 0; i < names.length; i++) { - final String name = names[i]; - final JsonNode subNode = node.get(name); - if (subNode == null) { - row.setField(i, null); - } else { - row.setField(i, convert(subNode, types[i])); - } - } - - return row; - } - - private Object convertObjectArray(JsonNode node, TypeInformation elementType) { - final Object[] array = (Object[]) Array.newInstance(elementType.getTypeClass(), node.size()); - for (int i = 0; i < node.size(); i++) { - array[i] = convert(node.get(i), elementType); - } - return array; - } - - @Override - public TypeInformation getProducedType() { - return typeInfo; - } -} diff --git a/core/src/main/java/com/dtstack/flink/sql/function/FunctionManager.java b/core/src/main/java/com/dtstack/flink/sql/function/FunctionManager.java deleted file mode 100644 index 51d914a68..000000000 --- a/core/src/main/java/com/dtstack/flink/sql/function/FunctionManager.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.function; - - -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.table.api.TableEnvironment; -import org.apache.flink.table.api.java.StreamTableEnvironment; -import org.apache.flink.table.functions.ScalarFunction; -import org.apache.flink.table.functions.TableFunction; -import org.apache.flink.table.functions.AggregateFunction; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - - -/** - * 自定义函数管理类 - * Reason: - * Date: 2017/2/21 - * Company: www.dtstack.com - * @author xuchao - */ - -public class FunctionManager { - private static final Logger logger = LoggerFactory.getLogger(FunctionManager.class); - - /** - * TABLE|SCALA|AGGREGATE - * 注册UDF到table env - */ - public static void registerUDF(String type, String classPath, String funcName, TableEnvironment tableEnv, ClassLoader classLoader) { - if ("SCALA".equalsIgnoreCase(type)) { - registerScalaUDF(classPath, funcName, tableEnv, classLoader); - } else if ("TABLE".equalsIgnoreCase(type)) { - registerTableUDF(classPath, funcName, tableEnv, classLoader); - } else if ("AGGREGATE".equalsIgnoreCase(type)) { - registerAggregateUDF(classPath, funcName, tableEnv, classLoader); - } else { - throw new RuntimeException("not support of UDF which is not in (TABLE, SCALA, AGGREGATE)"); - } - } - - /** - * 注册自定义方法到env上 - * @param classPath - * @param funcName - * @param tableEnv - */ - public static void registerScalaUDF(String classPath, String funcName, TableEnvironment tableEnv, ClassLoader classLoader) { - try { - ScalarFunction udfFunc = Class.forName(classPath, false, classLoader) - .asSubclass(ScalarFunction.class).newInstance(); - tableEnv.registerFunction(funcName, udfFunc); - logger.info("register scala function:{} success.", funcName); - } catch (Exception e) { - logger.error("", e); - throw new RuntimeException("register UDF exception:", e); - } - } - - /** - * 注册自定义TABLEFFUNC方法到env上 - * - * @param classPath - * @param funcName - * @param tableEnv - */ - public static void registerTableUDF(String classPath, String funcName, TableEnvironment tableEnv, ClassLoader classLoader) { - try { - checkStreamTableEnv(tableEnv); - TableFunction udtf = Class.forName(classPath, false, classLoader) - .asSubclass(TableFunction.class).newInstance(); - - ((StreamTableEnvironment) tableEnv).registerFunction(funcName, udtf); - logger.info("register table function:{} success.", funcName); - } catch (Exception e) { - logger.error("", e); - throw new RuntimeException("register Table UDF exception:", e); - } - } - - private static void checkStreamTableEnv(TableEnvironment tableEnv) { - if (!(tableEnv instanceof StreamTableEnvironment)) { - throw new RuntimeException("no support tableEnvironment class for " + tableEnv.getClass().getName()); - } - } - - /** - * 注册自定义Aggregate FUNC方法到env上 - * - * @param classPath - * @param funcName - * @param tableEnv - */ - public static void registerAggregateUDF(String classPath, String funcName, TableEnvironment tableEnv, ClassLoader classLoader) { - try { - checkStreamTableEnv(tableEnv); - - AggregateFunction udaf = Class.forName(classPath, false, classLoader) - .asSubclass(AggregateFunction.class).newInstance(); - ((StreamTableEnvironment) tableEnv).registerFunction(funcName, udaf); - logger.info("register Aggregate function:{} success.", funcName); - } catch (Exception e) { - logger.error("", e); - throw new RuntimeException("register Aggregate UDF exception:", e); - } - } - - public static TypeInformation[] transformTypes(Class[] fieldTypes) { - TypeInformation[] types = new TypeInformation[fieldTypes.length]; - for (int i = 0; i < fieldTypes.length; i++) { - types[i] = TypeInformation.of(fieldTypes[i]); - } - return types; - } - -} \ No newline at end of file diff --git a/core/src/main/java/com/dtstack/flink/sql/krb/KerberosTable.java b/core/src/main/java/com/dtstack/flink/sql/krb/KerberosTable.java deleted file mode 100644 index a071ea8c0..000000000 --- a/core/src/main/java/com/dtstack/flink/sql/krb/KerberosTable.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.krb; - -import com.google.common.base.Strings; - -/** - * @program: flinkStreamSQL - * @author: wuren - * @create: 2020/09/15 - **/ -public interface KerberosTable { - - String getPrincipal(); - - void setPrincipal(String principal); - - String getKeytab(); - - void setKeytab(String keytab); - - String getKrb5conf(); - - void setKrb5conf(String krb5conf); - - boolean isEnableKrb(); - - void setEnableKrb(boolean enableKrb); - - default void judgeKrbEnable() { - boolean allSet = - !Strings.isNullOrEmpty(getPrincipal()) && - !Strings.isNullOrEmpty(getKeytab()) && - !Strings.isNullOrEmpty(getKrb5conf()); - - boolean allNotSet = - Strings.isNullOrEmpty(getPrincipal()) && - Strings.isNullOrEmpty(getKeytab()) && - Strings.isNullOrEmpty(getKrb5conf()); - - if (allSet) { - setEnableKrb(true); - } else if (allNotSet) { - setEnableKrb(false); - } else { - throw new RuntimeException( - "Missing kerberos parameter! all kerberos params must be set, or all kerberos params are not set"); - } - } -} diff --git a/core/src/main/java/com/dtstack/flink/sql/metric/MetricConstant.java b/core/src/main/java/com/dtstack/flink/sql/metric/MetricConstant.java index e9c1902c7..17bb75e82 100644 --- a/core/src/main/java/com/dtstack/flink/sql/metric/MetricConstant.java +++ b/core/src/main/java/com/dtstack/flink/sql/metric/MetricConstant.java @@ -47,8 +47,6 @@ public class MetricConstant { public static final String DT_NUM_DIRTY_RECORDS_OUT = "dtNumDirtyRecordsOut"; - public static final String DT_NUM_SIDE_PARSE_ERROR_RECORDS = "dtNumSideParseErrorRecords"; - public static final String DT_NUM_RECORDS_OUT_RATE = "dtNumRecordsOutRate"; public static final String DT_EVENT_DELAY_GAUGE = "dtEventDelay"; diff --git a/core/src/main/java/com/dtstack/flink/sql/option/OptionParser.java b/core/src/main/java/com/dtstack/flink/sql/option/OptionParser.java index d294ae015..07860b608 100644 --- a/core/src/main/java/com/dtstack/flink/sql/option/OptionParser.java +++ b/core/src/main/java/com/dtstack/flink/sql/option/OptionParser.java @@ -20,19 +20,18 @@ import com.google.common.collect.Lists; import com.dtstack.flink.sql.util.PluginUtil; +import org.apache.commons.cli.BasicParser; import org.apache.commons.cli.CommandLine; -import org.apache.commons.cli.DefaultParser; import org.apache.commons.cli.ParseException; import org.apache.commons.lang.StringUtils; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Field; -import java.nio.charset.StandardCharsets; import java.util.List; import java.util.Map; import java.io.File; +import java.io.FileInputStream; import java.net.URLEncoder; - -import org.apache.flink.util.FileUtils; +import org.apache.commons.codec.Charsets; /** @@ -47,7 +46,7 @@ public class OptionParser { private org.apache.commons.cli.Options options = new org.apache.commons.cli.Options(); - private DefaultParser parser = new DefaultParser(); + private BasicParser parser = new BasicParser(); private Options properties = new Options(); @@ -93,21 +92,29 @@ public Options getOptions(){ } public List getProgramExeArgList() throws Exception { - Map mapConf = PluginUtil.objectToMap(properties); + Map mapConf = PluginUtil.ObjectToMap(properties); List args = Lists.newArrayList(); - for (Map.Entry one : mapConf.entrySet()) { + for(Map.Entry one : mapConf.entrySet()){ String key = one.getKey(); Object value = one.getValue(); - if (value == null) { + if(value == null){ continue; - } else if (OPTION_SQL.equalsIgnoreCase(key)) { + }else if(OPTION_SQL.equalsIgnoreCase(key)){ File file = new File(value.toString()); - String content = FileUtils.readFile(file, StandardCharsets.UTF_8.name()); - value = URLEncoder.encode(content, StandardCharsets.UTF_8.name()); + FileInputStream in = new FileInputStream(file); + byte[] filecontent = new byte[(int) file.length()]; + in.read(filecontent); + String content = new String(filecontent, Charsets.UTF_8.name()); + value = URLEncoder.encode(content, Charsets.UTF_8.name()); } args.add("-" + key); args.add(value.toString()); } return args; } + + public static void main(String[] args) throws Exception { + OptionParser OptionParser = new OptionParser(args); + System.out.println(OptionParser.getOptions()); + } } diff --git a/core/src/main/java/com/dtstack/flink/sql/option/Options.java b/core/src/main/java/com/dtstack/flink/sql/option/Options.java index 0e5b52cb3..a653aa42e 100644 --- a/core/src/main/java/com/dtstack/flink/sql/option/Options.java +++ b/core/src/main/java/com/dtstack/flink/sql/option/Options.java @@ -6,9 +6,9 @@ * 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. @@ -31,31 +31,37 @@ public class Options { @OptionRequired(description = "Running mode") - private String mode = ClusterMode.local.name(); + private String mode = ClusterMode.local.name(); - @OptionRequired(required = true, description = "Job name") - private String name; + @OptionRequired(required = true,description = "Job name") + private String name; - @OptionRequired(required = true, description = "Job sql file") - private String sql; + @OptionRequired(required = true,description = "Job sql file") + private String sql; @OptionRequired(description = "Flink configuration directory") - private String flinkconf; + private String flinkconf; @OptionRequired(description = "Yarn and Hadoop configuration directory") - private String yarnconf; + private String yarnconf; - @OptionRequired(description = "Sql local plugin root") - private String localSqlPluginPath; + @OptionRequired(required = true,description = "Sql local plugin root") + private String localSqlPluginPath; - @OptionRequired(description = "Sql remote plugin root") - private String remoteSqlPluginPath; + @OptionRequired(required = true,description = "Sql remote plugin root") + private String remoteSqlPluginPath ; @OptionRequired(description = "sql ext jar,eg udf jar") - private String addjar; + private String addjar; @OptionRequired(description = "sql ref prop,eg specify event time") - private String confProp = "{}"; + private String confProp = "{}"; + + @OptionRequired(description = "Savepoint restore path") + private String savePointPath; + + @OptionRequired(description = "Flag indicating whether non restored state is allowed if the savepoint") + private String allowNonRestoredState = "false"; @OptionRequired(description = "flink jar path for submit of perjob mode") private String flinkJarPath; @@ -69,12 +75,6 @@ public class Options { @OptionRequired(description = "plugin load mode, by classpath or shipfile") private String pluginLoadMode = EPluginLoadMode.CLASSPATH.name(); - @OptionRequired(description = "file add to ship file") - private String addShipfile; - - @OptionRequired(description = "dirty plugin properties") - private String dirtyProperties; - public String getMode() { return mode; } @@ -147,6 +147,22 @@ public void setConfProp(String confProp) { this.confProp = confProp; } + public String getSavePointPath() { + return savePointPath; + } + + public void setSavePointPath(String savePointPath) { + this.savePointPath = savePointPath; + } + + public String getAllowNonRestoredState() { + return allowNonRestoredState; + } + + public void setAllowNonRestoredState(String allowNonRestoredState) { + this.allowNonRestoredState = allowNonRestoredState; + } + public String getFlinkJarPath() { return flinkJarPath; } @@ -178,20 +194,4 @@ public String getPluginLoadMode() { public void setPluginLoadMode(String pluginLoadMode) { this.pluginLoadMode = pluginLoadMode; } - - public String getAddShipfile() { - return addShipfile; - } - - public void setAddShipfile(String addShipfile) { - this.addShipfile = addShipfile; - } - - public String getDirtyProperties() { - return dirtyProperties; - } - - public void setDirtyProperties(String dirtyProperties) { - this.dirtyProperties = dirtyProperties; - } } diff --git a/core/src/main/java/com/dtstack/flink/sql/parser/CreateFuncParser.java b/core/src/main/java/com/dtstack/flink/sql/parser/CreateFuncParser.java index fc6a7e16c..670d98a7e 100644 --- a/core/src/main/java/com/dtstack/flink/sql/parser/CreateFuncParser.java +++ b/core/src/main/java/com/dtstack/flink/sql/parser/CreateFuncParser.java @@ -32,18 +32,18 @@ public class CreateFuncParser implements IParser { - private static final String FUNC_PATTERN_STR = "(?i)\\s*create\\s+(scala|table|aggregate)\\s+function\\s+(\\S+)\\s+WITH\\s+(\\S+)"; + private static final String funcPatternStr = "(?i)\\s*create\\s+(scala|table|aggregate)\\s+function\\s+(\\S+)\\s+WITH\\s+(\\S+)"; - private static final Pattern FUNC_PATTERN = Pattern.compile(FUNC_PATTERN_STR); + private static final Pattern funcPattern = Pattern.compile(funcPatternStr); @Override public boolean verify(String sql) { - return FUNC_PATTERN.matcher(sql).find(); + return funcPattern.matcher(sql).find(); } @Override public void parseSql(String sql, SqlTree sqlTree) { - Matcher matcher = FUNC_PATTERN.matcher(sql); + Matcher matcher = funcPattern.matcher(sql); if(matcher.find()){ String type = matcher.group(1); String funcName = matcher.group(2); diff --git a/core/src/main/java/com/dtstack/flink/sql/parser/CreateTableParser.java b/core/src/main/java/com/dtstack/flink/sql/parser/CreateTableParser.java index 42024ec21..ae6e1f708 100644 --- a/core/src/main/java/com/dtstack/flink/sql/parser/CreateTableParser.java +++ b/core/src/main/java/com/dtstack/flink/sql/parser/CreateTableParser.java @@ -16,10 +16,11 @@ * limitations under the License. */ + + package com.dtstack.flink.sql.parser; import com.dtstack.flink.sql.util.DtStringUtil; -import com.google.common.base.Preconditions; import com.google.common.collect.Maps; import java.util.List; @@ -67,14 +68,13 @@ public void parseSql(String sql, SqlTree sqlTree) { } } - private Map parseProp(String propsStr){ - List strings = DtStringUtil.splitIgnoreQuota(propsStr.trim(), ','); + private Map parseProp(String propsStr){ + String[] strs = propsStr.trim().split("'\\s*,"); Map propMap = Maps.newHashMap(); - for (String str : strings) { - List ss = DtStringUtil.splitIgnoreQuota(str, '='); - Preconditions.checkState(ss.size() == 2, str + " Format error"); + for(int i=0; i ss = DtStringUtil.splitIgnoreQuota(strs[i], '='); String key = ss.get(0).trim(); - String value = DtStringUtil.removeStartAndEndQuota(ss.get(1).trim()); + String value = ss.get(1).trim().replaceAll("'", "").trim(); propMap.put(key, value); } diff --git a/core/src/main/java/com/dtstack/flink/sql/parser/CreateTmpTableParser.java b/core/src/main/java/com/dtstack/flink/sql/parser/CreateTmpTableParser.java index bd475240f..de7141eb5 100644 --- a/core/src/main/java/com/dtstack/flink/sql/parser/CreateTmpTableParser.java +++ b/core/src/main/java/com/dtstack/flink/sql/parser/CreateTmpTableParser.java @@ -17,17 +17,15 @@ */ + package com.dtstack.flink.sql.parser; import com.dtstack.flink.sql.util.DtStringUtil; +import org.apache.calcite.config.Lex; +import org.apache.calcite.sql.*; +import org.apache.calcite.sql.parser.SqlParseException; +import org.apache.calcite.sql.parser.SqlParser; import com.google.common.collect.Lists; -import org.apache.calcite.sql.SqlBasicCall; -import org.apache.calcite.sql.SqlJoin; -import org.apache.calcite.sql.SqlKind; -import org.apache.calcite.sql.SqlMatchRecognize; -import org.apache.calcite.sql.SqlNode; -import org.apache.calcite.sql.SqlSelect; - import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -38,7 +36,6 @@ * parser create tmp table sql * Date: 2018/6/26 * Company: www.dtstack.com - * * @author yanxi */ public class CreateTmpTableParser implements IParser { @@ -52,75 +49,13 @@ public class CreateTmpTableParser implements IParser { private static final Pattern EMPTYVIEW = Pattern.compile(EMPTY_STR); - private final FlinkPlanner flinkPlanner = new FlinkPlanner(); - - public static CreateTmpTableParser newInstance() { + public static CreateTmpTableParser newInstance(){ return new CreateTmpTableParser(); } - private static void parseNode(SqlNode sqlNode, CreateTmpTableParser.SqlParserResult sqlParseResult) { - SqlKind sqlKind = sqlNode.getKind(); - switch (sqlKind) { - case SELECT: - SqlNode sqlFrom = ((SqlSelect) sqlNode).getFrom(); - if (sqlFrom.getKind() == IDENTIFIER) { - sqlParseResult.addSourceTable(sqlFrom.toString()); - } else { - parseNode(sqlFrom, sqlParseResult); - } - break; - case JOIN: - SqlNode leftNode = ((SqlJoin) sqlNode).getLeft(); - SqlNode rightNode = ((SqlJoin) sqlNode).getRight(); - - if (leftNode.getKind() == IDENTIFIER) { - sqlParseResult.addSourceTable(leftNode.toString()); - } else { - parseNode(leftNode, sqlParseResult); - } - - if (rightNode.getKind() == IDENTIFIER) { - sqlParseResult.addSourceTable(rightNode.toString()); - } else { - parseNode(rightNode, sqlParseResult); - } - break; - case AS: - //不解析column,所以 as 相关的都是表 - SqlNode identifierNode = ((SqlBasicCall) sqlNode).getOperands()[0]; - if (identifierNode.getKind() != IDENTIFIER) { - parseNode(identifierNode, sqlParseResult); - } else { - sqlParseResult.addSourceTable(identifierNode.toString()); - } - break; - case UNION: - SqlNode unionLeft = ((SqlBasicCall) sqlNode).getOperands()[0]; - SqlNode unionRight = ((SqlBasicCall) sqlNode).getOperands()[1]; - if (unionLeft.getKind() == IDENTIFIER) { - sqlParseResult.addSourceTable(unionLeft.toString()); - } else { - parseNode(unionLeft, sqlParseResult); - } - if (unionRight.getKind() == IDENTIFIER) { - sqlParseResult.addSourceTable(unionRight.toString()); - } else { - parseNode(unionRight, sqlParseResult); - } - break; - case MATCH_RECOGNIZE: - SqlMatchRecognize node = (SqlMatchRecognize) sqlNode; - sqlParseResult.addSourceTable(node.getTableRef().toString()); - break; - default: - //do nothing - break; - } - } - @Override public boolean verify(String sql) { - if (Pattern.compile(EMPTY_STR).matcher(sql).find()) { + if (Pattern.compile(EMPTY_STR).matcher(sql).find()){ return true; } return NONEMPTYVIEW.matcher(sql).find(); @@ -128,19 +63,25 @@ public boolean verify(String sql) { @Override public void parseSql(String sql, SqlTree sqlTree) { - if (NONEMPTYVIEW.matcher(sql).find()) { + if (NONEMPTYVIEW.matcher(sql).find()){ Matcher matcher = NONEMPTYVIEW.matcher(sql); String tableName = null; String selectSql = null; - if (matcher.find()) { + if(matcher.find()) { tableName = matcher.group(1); selectSql = "select " + matcher.group(2); } + SqlParser.Config config = SqlParser + .configBuilder() + .setLex(Lex.MYSQL) + .build(); + SqlParser sqlParser = SqlParser.create(selectSql,config); + SqlNode sqlNode = null; try { - sqlNode = flinkPlanner.getParser().parse(selectSql); - } catch (Exception e) { + sqlNode = sqlParser.parseStmt(); + } catch (SqlParseException e) { throw new RuntimeException("", e); } @@ -153,11 +94,12 @@ public void parseSql(String sql, SqlTree sqlTree) { sqlTree.addTmpSql(sqlParseResult); sqlTree.addTmplTableInfo(tableName, sqlParseResult); } else { - if (EMPTYVIEW.matcher(sql).find()) { + if (EMPTYVIEW.matcher(sql).find()) + { Matcher matcher = EMPTYVIEW.matcher(sql); String tableName = null; String fieldsInfoStr = null; - if (matcher.find()) { + if (matcher.find()){ tableName = matcher.group(1); fieldsInfoStr = matcher.group(2); } @@ -166,6 +108,64 @@ public void parseSql(String sql, SqlTree sqlTree) { sqlParseResult.setTableName(tableName); sqlTree.addTmplTableInfo(tableName, sqlParseResult); } + + } + + } + + private static void parseNode(SqlNode sqlNode, CreateTmpTableParser.SqlParserResult sqlParseResult){ + SqlKind sqlKind = sqlNode.getKind(); + switch (sqlKind){ + case SELECT: + SqlNode sqlFrom = ((SqlSelect)sqlNode).getFrom(); + if(sqlFrom.getKind() == IDENTIFIER){ + sqlParseResult.addSourceTable(sqlFrom.toString()); + }else{ + parseNode(sqlFrom, sqlParseResult); + } + break; + case JOIN: + SqlNode leftNode = ((SqlJoin)sqlNode).getLeft(); + SqlNode rightNode = ((SqlJoin)sqlNode).getRight(); + + if(leftNode.getKind() == IDENTIFIER){ + sqlParseResult.addSourceTable(leftNode.toString()); + }else{ + parseNode(leftNode, sqlParseResult); + } + + if(rightNode.getKind() == IDENTIFIER){ + sqlParseResult.addSourceTable(rightNode.toString()); + }else{ + parseNode(rightNode, sqlParseResult); + } + break; + case AS: + //不解析column,所以 as 相关的都是表 + SqlNode identifierNode = ((SqlBasicCall)sqlNode).getOperands()[0]; + if(identifierNode.getKind() != IDENTIFIER){ + parseNode(identifierNode, sqlParseResult); + }else { + sqlParseResult.addSourceTable(identifierNode.toString()); + } + break; + case UNION: + SqlNode unionLeft = ((SqlBasicCall)sqlNode).getOperands()[0]; + SqlNode unionRight = ((SqlBasicCall)sqlNode).getOperands()[1]; + if(unionLeft.getKind() == IDENTIFIER){ + sqlParseResult.addSourceTable(unionLeft.toString()); + }else{ + parseNode(unionLeft, sqlParseResult); + } + if(unionRight.getKind() == IDENTIFIER){ + sqlParseResult.addSourceTable(unionRight.toString()); + }else{ + parseNode(unionRight, sqlParseResult); + } + break; + default: + //do nothing + break; } } @@ -202,12 +202,13 @@ public void setFieldsInfoStr(String fieldsInfoStr) { this.fieldsInfoStr = fieldsInfoStr; } - public void addSourceTable(String sourceTable) { + public void addSourceTable(String sourceTable){ sourceTableList.add(sourceTable); } public List getSourceTableList() { return sourceTableList; } + } } \ No newline at end of file diff --git a/core/src/main/java/com/dtstack/flink/sql/parser/FlinkPlanner.java b/core/src/main/java/com/dtstack/flink/sql/parser/FlinkPlanner.java deleted file mode 100644 index d600a320f..000000000 --- a/core/src/main/java/com/dtstack/flink/sql/parser/FlinkPlanner.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.parser; - -import org.apache.flink.table.api.EnvironmentSettings; -import org.apache.flink.table.api.SqlDialect; -import org.apache.flink.table.api.TableConfig; -import org.apache.flink.table.catalog.Catalog; -import org.apache.flink.table.catalog.CatalogManager; -import org.apache.flink.table.catalog.FunctionCatalog; -import org.apache.flink.table.catalog.GenericInMemoryCatalog; -import org.apache.flink.table.module.ModuleManager; -import org.apache.flink.table.planner.calcite.CalciteParser; -import org.apache.flink.table.planner.catalog.CatalogManagerCalciteSchema; -import org.apache.flink.table.planner.delegation.PlannerContext; - -import java.util.ArrayList; - -import static org.apache.calcite.jdbc.CalciteSchemaBuilder.asRootSchema; - -/** - * 废弃。之后删除 - * Date: 2020/3/31 - * Company: www.dtstack.com - * @author maqi - */ -@Deprecated -public class FlinkPlanner { - - private final TableConfig tableConfig = new TableConfig(); - - private final Catalog catalog = new GenericInMemoryCatalog(EnvironmentSettings.DEFAULT_BUILTIN_CATALOG, - EnvironmentSettings.DEFAULT_BUILTIN_DATABASE); - private final CatalogManager catalogManager = - new CatalogManager("builtin", catalog); - private final ModuleManager moduleManager = new ModuleManager(); - private final FunctionCatalog functionCatalog = new FunctionCatalog( - tableConfig, - catalogManager, - moduleManager); - private final PlannerContext plannerContext = - new PlannerContext( - tableConfig, - functionCatalog, - catalogManager, - asRootSchema(new CatalogManagerCalciteSchema(catalogManager, false)), - new ArrayList<>()); - - - public FlinkPlanner() { - } - - public CalciteParser getParser(){ - return getParserBySqlDialect(SqlDialect.DEFAULT); - } - - public CalciteParser getParserBySqlDialect(SqlDialect sqlDialect) { - tableConfig.setSqlDialect(sqlDialect); - return plannerContext.createCalciteParser(); - } -} diff --git a/core/src/main/java/com/dtstack/flink/sql/parser/IParser.java b/core/src/main/java/com/dtstack/flink/sql/parser/IParser.java index 9503b21bb..87f91d223 100644 --- a/core/src/main/java/com/dtstack/flink/sql/parser/IParser.java +++ b/core/src/main/java/com/dtstack/flink/sql/parser/IParser.java @@ -41,5 +41,5 @@ public interface IParser { * @param sql * @param sqlTree */ - void parseSql(String sql, SqlTree sqlTree) throws Exception; + void parseSql(String sql, SqlTree sqlTree); } diff --git a/core/src/main/java/com/dtstack/flink/sql/parser/InsertSqlParser.java b/core/src/main/java/com/dtstack/flink/sql/parser/InsertSqlParser.java index 2b4bd89d2..a7c6db9eb 100644 --- a/core/src/main/java/com/dtstack/flink/sql/parser/InsertSqlParser.java +++ b/core/src/main/java/com/dtstack/flink/sql/parser/InsertSqlParser.java @@ -16,24 +16,16 @@ * limitations under the License. */ + package com.dtstack.flink.sql.parser; -import org.apache.calcite.sql.SqlInsert; -import org.apache.calcite.sql.SqlJoin; -import org.apache.calcite.sql.SqlKind; -import org.apache.calcite.sql.SqlNode; -import org.apache.calcite.sql.SqlSelect; -import org.apache.calcite.sql.SqlNodeList; -import org.apache.calcite.sql.SqlBasicCall; -import org.apache.calcite.sql.SqlMatchRecognize; -import org.apache.calcite.sql.SqlOrderBy; -import org.apache.calcite.sql.SqlIdentifier; -import org.apache.calcite.sql.SqlAsOperator; -import org.apache.calcite.sql.parser.SqlParserPos; +import org.apache.calcite.config.Lex; +import org.apache.calcite.sql.*; +import org.apache.calcite.sql.parser.SqlParseException; +import org.apache.calcite.sql.parser.SqlParser; import org.apache.commons.lang3.StringUtils; import com.google.common.collect.Lists; -import org.apache.flink.table.planner.calcite.FlinkPlannerImpl; import java.util.List; @@ -49,11 +41,6 @@ public class InsertSqlParser implements IParser { - private FlinkPlanner flinkPlanner = new FlinkPlanner(); - - // 用来标识当前解析节点的上一层节点是否为 insert 节点 - private static Boolean parentIsInsert = false; - @Override public boolean verify(String sql) { return StringUtils.isNotBlank(sql) && sql.trim().toLowerCase().startsWith("insert"); @@ -65,10 +52,18 @@ public static InsertSqlParser newInstance(){ } @Override - public void parseSql(String sql, SqlTree sqlTree) throws Exception { - - - SqlNode sqlNode = flinkPlanner.getParser().parse(sql); + public void parseSql(String sql, SqlTree sqlTree) { + SqlParser.Config config = SqlParser + .configBuilder() + .setLex(Lex.MYSQL) + .build(); + SqlParser sqlParser = SqlParser.create(sql,config); + SqlNode sqlNode = null; + try { + sqlNode = sqlParser.parseStmt(); + } catch (SqlParseException e) { + throw new RuntimeException("", e); + } SqlParseResult sqlParseResult = new SqlParseResult(); parseNode(sqlNode, sqlParseResult); @@ -83,19 +78,13 @@ private static void parseNode(SqlNode sqlNode, SqlParseResult sqlParseResult){ SqlNode sqlTarget = ((SqlInsert)sqlNode).getTargetTable(); SqlNode sqlSource = ((SqlInsert)sqlNode).getSource(); sqlParseResult.addTargetTable(sqlTarget.toString()); - parentIsInsert = true; parseNode(sqlSource, sqlParseResult); break; case SELECT: - SqlSelect sqlSelect = (SqlSelect) sqlNode; - if (parentIsInsert) { - rebuildSelectNode(sqlSelect.getSelectList(), sqlSelect); - } - SqlNode sqlFrom = ((SqlSelect) sqlNode).getFrom(); - if (sqlFrom.getKind() == IDENTIFIER) { + SqlNode sqlFrom = ((SqlSelect)sqlNode).getFrom(); + if(sqlFrom.getKind() == IDENTIFIER){ sqlParseResult.addSourceTable(sqlFrom.toString()); - } else { - parentIsInsert = false; + }else{ parseNode(sqlFrom, sqlParseResult); } break; @@ -152,64 +141,6 @@ private static void parseNode(SqlNode sqlNode, SqlParseResult sqlParseResult){ } } - /** - * 将第一层 select 中的 sqlNode 转化为 AsNode,解决字段名冲突问题 - * 仅对 table.xx 这种类型的字段进行替换 - * @param selectList select Node 的 select 字段 - * @param sqlSelect 第一层解析出来的 selectNode - */ - private static void rebuildSelectNode(SqlNodeList selectList, SqlSelect sqlSelect) { - SqlNodeList sqlNodes = new SqlNodeList(selectList.getParserPosition()); - - for (int index = 0; index < selectList.size(); index++) { - SqlNode sqlNode = selectList.get(index); - // 判断sqlNode的类型是否属于 't1.f1 as f2' - boolean isAsNode = sqlNode.getKind().equals(SqlKind.AS); - - // 判断sqlNode的结构是否属于'f1' 或者 't.*' - boolean isIdentifierOrStar = sqlNode.getClass().equals(SqlIdentifier.class) - // sqlNode like 'f1' - && (((SqlIdentifier) sqlNode).isSimple() - // sqlNode like 't.*' - || ((SqlIdentifier) sqlNode).isStar()); - - if (isAsNode || isIdentifierOrStar) { - sqlNodes.add(sqlNode); - continue; - } - - if (!sqlNode.getClass().equals(SqlIdentifier.class)) { - if (sqlNode.getKind().equals(SqlKind.LITERAL)) { - throw new IllegalArgumentException(String.format("Constants %s in the SELECT statement must be aliased!", - sqlNode.toString())); - } - throw new RuntimeException(String.format("Illegal statement! Please check the statement: %s", - sqlNode.toString())); - } - - sqlNodes.add(transformToAsNode(sqlNode)); - } - sqlSelect.setSelectList(sqlNodes); - } - - /** - * 将 sqlNode 转化为 AsNode - * @param sqlNode 需要转化的 sqlNode - * @return 重新构造的 AsNode - */ - public static SqlBasicCall transformToAsNode(SqlNode sqlNode) { - String asName = ""; - SqlParserPos pos = new SqlParserPos(sqlNode.getParserPosition().getLineNum(), - sqlNode.getParserPosition().getEndColumnNum()); - if (sqlNode.getKind().equals(SqlKind.IDENTIFIER)) { - asName = ((SqlIdentifier) sqlNode).names.get(1); - } - SqlNode[] operands = new SqlNode[2]; - operands[0] = sqlNode; - operands[1] = new SqlIdentifier(asName, null, pos); - return new SqlBasicCall(new SqlAsOperator(), operands, pos); - } - public static class SqlParseResult { private List sourceTableList = Lists.newArrayList(); diff --git a/core/src/main/java/com/dtstack/flink/sql/parser/SqlParser.java b/core/src/main/java/com/dtstack/flink/sql/parser/SqlParser.java index 36dcaab67..a76c1b31a 100644 --- a/core/src/main/java/com/dtstack/flink/sql/parser/SqlParser.java +++ b/core/src/main/java/com/dtstack/flink/sql/parser/SqlParser.java @@ -16,42 +16,38 @@ * limitations under the License. */ + package com.dtstack.flink.sql.parser; import com.dtstack.flink.sql.enums.ETableType; -import com.dtstack.flink.sql.table.AbstractTableInfo; -import com.dtstack.flink.sql.table.AbstractTableInfoParser; +import com.dtstack.flink.sql.table.TableInfo; +import com.dtstack.flink.sql.table.TableInfoParser; import com.dtstack.flink.sql.util.DtStringUtil; -import com.google.common.base.Strings; -import com.google.common.collect.Lists; import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.google.common.collect.Lists; +import com.google.common.base.Strings; import java.util.List; import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; /** * Reason: * Date: 2018/6/22 * Company: www.dtstack.com - * * @author xuchao */ public class SqlParser { - private static final Logger LOG = LoggerFactory.getLogger(SqlParser.class); private static final char SQL_DELIMITER = ';'; - private static final Pattern ADD_FILE_AND_JAR_PATTERN = Pattern.compile("(?i).*add\\s+file\\s+.+|(?i).*add\\s+jar\\s+.+"); + private static String LOCAL_SQL_PLUGIN_ROOT; + private static List sqlParserList = Lists.newArrayList(CreateFuncParser.newInstance(), CreateTableParser.newInstance(), InsertSqlParser.newInstance(), CreateTmpTableParser.newInstance()); - public static void setLocalSqlPluginRoot(String localSqlPluginRoot) { + public static void setLocalSqlPluginRoot(String localSqlPluginRoot){ LOCAL_SQL_PLUGIN_ROOT = localSqlPluginRoot; } @@ -60,130 +56,102 @@ public static void setLocalSqlPluginRoot(String localSqlPluginRoot) { * CREATE TABLE sls_stream() with (); * CREATE (TABLE|SCALA) FUNCTION fcnName WITH com.dtstack.com; * insert into tb1 select * from tb2; - * * @param sql */ - public static SqlTree parseSql(String sql, String pluginLoadMode) throws Exception { + public static SqlTree parseSql(String sql) throws Exception { - if (StringUtils.isBlank(sql)) { - throw new IllegalArgumentException("SQL must be not empty!"); + if(StringUtils.isBlank(sql)){ + throw new RuntimeException("sql is not null"); } - sql = DtStringUtil.dealSqlComment(sql) + if(LOCAL_SQL_PLUGIN_ROOT == null){ + throw new RuntimeException("need to set local sql plugin root"); + } + + sql = sql.replaceAll("--.*", "") .replaceAll("\r\n", " ") .replaceAll("\n", " ") .replace("\t", " ").trim(); List sqlArr = DtStringUtil.splitIgnoreQuota(sql, SQL_DELIMITER); - sqlArr = removeAddFileAndJarStmt(sqlArr); SqlTree sqlTree = new SqlTree(); - AbstractTableInfoParser tableInfoParser = new AbstractTableInfoParser(); - for (String childSql : sqlArr) { - if (Strings.isNullOrEmpty(childSql)) { + TableInfoParser tableInfoParser = new TableInfoParser(); + for(String childSql : sqlArr){ + if(Strings.isNullOrEmpty(childSql)){ continue; } boolean result = false; - for (IParser sqlParser : sqlParserList) { - try { - if (!sqlParser.verify(childSql)) { - continue; - } - - sqlParser.parseSql(childSql, sqlTree); - result = true; - break; - } catch (Exception e) { - LOG.error("'{}' parser error, detail info: {}", childSql, e.getMessage(), e); - throw e; + for(IParser sqlParser : sqlParserList){ + if(!sqlParser.verify(childSql)){ + continue; } + + sqlParser.parseSql(childSql, sqlTree); + result = true; + break; } - if (!result) { - throw new RuntimeException(String.format("%s \nSyntax like this does not support, the format of SQL like 'insert into tb1 select field from tb2'.", childSql)); + if(!result){ + throw new RuntimeException(String.format("%s:Syntax does not support,the format of SQL like insert into tb1 select * from tb2.", childSql)); } } //解析exec-sql - if (sqlTree.getExecSqlList().size() == 0) { + if(sqlTree.getExecSqlList().size() == 0){ throw new RuntimeException("sql no executable statement"); } - for (InsertSqlParser.SqlParseResult result : sqlTree.getExecSqlList()) { + for(InsertSqlParser.SqlParseResult result : sqlTree.getExecSqlList()){ List sourceTableList = result.getSourceTableList(); List targetTableList = result.getTargetTableList(); Set tmpTableList = sqlTree.getTmpTableMap().keySet(); - for (String tableName : sourceTableList) { - if (!tmpTableList.contains(tableName)) { + for(String tableName : sourceTableList){ + if (!tmpTableList.contains(tableName)){ CreateTableParser.SqlParserResult createTableResult = sqlTree.getPreDealTableMap().get(tableName); - if (createTableResult == null) { + if(createTableResult == null){ throw new RuntimeException("can't find table " + tableName); } - AbstractTableInfo tableInfo = tableInfoParser.parseWithTableType( - ETableType.SOURCE.getType(), - createTableResult, - LOCAL_SQL_PLUGIN_ROOT, - pluginLoadMode - ); + TableInfo tableInfo = tableInfoParser.parseWithTableType(ETableType.SOURCE.getType(), + createTableResult, LOCAL_SQL_PLUGIN_ROOT); sqlTree.addTableInfo(tableName, tableInfo); } } - for (String tableName : targetTableList) { - if (!tmpTableList.contains(tableName)) { + for(String tableName : targetTableList){ + if (!tmpTableList.contains(tableName)){ CreateTableParser.SqlParserResult createTableResult = sqlTree.getPreDealTableMap().get(tableName); - if (createTableResult == null) { + if(createTableResult == null){ throw new RuntimeException("can't find table " + tableName); } - AbstractTableInfo tableInfo = tableInfoParser.parseWithTableType( - ETableType.SINK.getType(), - createTableResult, - LOCAL_SQL_PLUGIN_ROOT, - pluginLoadMode - ); + TableInfo tableInfo = tableInfoParser.parseWithTableType(ETableType.SINK.getType(), + createTableResult, LOCAL_SQL_PLUGIN_ROOT); sqlTree.addTableInfo(tableName, tableInfo); } } } - for (CreateTmpTableParser.SqlParserResult result : sqlTree.getTmpSqlList()) { + for (CreateTmpTableParser.SqlParserResult result : sqlTree.getTmpSqlList()){ List sourceTableList = result.getSourceTableList(); - for (String tableName : sourceTableList) { - if (!sqlTree.getTableInfoMap().containsKey(tableName)) { + for(String tableName : sourceTableList){ + if (!sqlTree.getTableInfoMap().keySet().contains(tableName)){ CreateTableParser.SqlParserResult createTableResult = sqlTree.getPreDealTableMap().get(tableName); - if (createTableResult == null) { + if(createTableResult == null){ CreateTmpTableParser.SqlParserResult tmpTableResult = sqlTree.getTmpTableMap().get(tableName); - if (tmpTableResult == null) { + if (tmpTableResult == null){ throw new RuntimeException("can't find table " + tableName); } } else { - AbstractTableInfo tableInfo = tableInfoParser.parseWithTableType( - ETableType.SOURCE.getType(), - createTableResult, - LOCAL_SQL_PLUGIN_ROOT, - pluginLoadMode - ); + TableInfo tableInfo = tableInfoParser.parseWithTableType(ETableType.SOURCE.getType(), + createTableResult, LOCAL_SQL_PLUGIN_ROOT); sqlTree.addTableInfo(tableName, tableInfo); } } } } - return sqlTree; - } - /** - * remove add file and jar with statment etc. add file /etc/krb5.conf, add jar xxx.jar; - */ - private static List removeAddFileAndJarStmt(List stmts) { - List cleanedStmts = Lists.newArrayList(); - for (String stmt : stmts) { - Matcher matcher = ADD_FILE_AND_JAR_PATTERN.matcher(stmt); - if (!matcher.matches()) { - cleanedStmts.add(stmt); - } - } - return cleanedStmts; + return sqlTree; } } diff --git a/core/src/main/java/com/dtstack/flink/sql/parser/SqlTree.java b/core/src/main/java/com/dtstack/flink/sql/parser/SqlTree.java index 5252ee022..1b64b7c68 100644 --- a/core/src/main/java/com/dtstack/flink/sql/parser/SqlTree.java +++ b/core/src/main/java/com/dtstack/flink/sql/parser/SqlTree.java @@ -21,7 +21,7 @@ package com.dtstack.flink.sql.parser; -import com.dtstack.flink.sql.table.AbstractTableInfo; +import com.dtstack.flink.sql.table.TableInfo; import com.google.common.collect.Maps; import com.google.common.collect.Lists; @@ -41,7 +41,7 @@ public class SqlTree { private Map preDealTableMap = Maps.newHashMap(); - private Map tableInfoMap = Maps.newLinkedHashMap(); + private Map tableInfoMap = Maps.newLinkedHashMap(); private List execSqlList = Lists.newArrayList(); @@ -89,11 +89,11 @@ public List getTmpSqlList(){ return tmpSqlList; } - public Map getTableInfoMap() { + public Map getTableInfoMap() { return tableInfoMap; } - public void addTableInfo(String tableName, AbstractTableInfo tableInfo){ + public void addTableInfo(String tableName, TableInfo tableInfo){ tableInfoMap.put(tableName, tableInfo); } } diff --git a/core/src/main/java/com/dtstack/flink/sql/side/AbstractSideTableInfo.java b/core/src/main/java/com/dtstack/flink/sql/side/AbstractSideTableInfo.java deleted file mode 100644 index 359d05b2a..000000000 --- a/core/src/main/java/com/dtstack/flink/sql/side/AbstractSideTableInfo.java +++ /dev/null @@ -1,260 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side; - -import com.dtstack.flink.sql.table.AbstractTableInfo; -import com.google.common.collect.Lists; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.table.runtime.typeutils.BaseRowTypeInfo; -import org.apache.flink.table.types.DataType; -import org.apache.flink.table.types.logical.DecimalType; -import org.apache.flink.table.types.logical.LogicalType; -import org.apache.flink.table.types.utils.ClassDataTypeConverter; -import org.apache.flink.table.types.utils.TypeConversions; - -import java.io.Serializable; -import java.math.BigDecimal; -import java.util.List; -import java.util.Objects; -import java.util.Optional; - -/** - * Reason: - * Date: 2018/7/25 - * Company: www.dtstack.com - * @author xuchao - */ - -public abstract class AbstractSideTableInfo extends AbstractTableInfo implements Serializable { - - public static final String FAST_CHECK = "fastCheck"; - - public static final String TARGET_SUFFIX = "Side"; - - public static final String CACHE_KEY = "cache"; - - public static final String CACHE_SIZE_KEY = "cacheSize"; - - public static final String CACHE_TTLMS_KEY = "cacheTTLMs"; - - public static final String PARTITIONED_JOIN_KEY = "partitionedJoin"; - - public static final String CACHE_MODE_KEY = "cacheMode"; - - public static final String ASYNC_CAP_KEY = "asyncCapacity"; - - public static final String ASYNC_TIMEOUT_KEY = "asyncTimeout"; - - public static final String ASYNC_FAIL_MAX_NUM_KEY = "asyncFailMaxNum"; - - public static final String CONNECT_RETRY_MAX_NUM_KEY = "connectRetryMaxNum"; - - public static final String ASYNC_REQ_POOL_KEY = "asyncPoolSize"; - - private String cacheType = "none"; - - private int cacheSize = 10000; - - private long cacheTimeout = 60 * 1000L; - - private int asyncCapacity=100; - - private int asyncTimeout=10000; - - /** - * async operator req outside conn pool size, egg rdb conn pool size - */ - private int asyncPoolSize = 0; - - private boolean partitionedJoin = false; - - private String cacheMode="ordered"; - - private Long asyncFailMaxNum; - - private Integer connectRetryMaxNum; - - private List predicateInfoes = Lists.newArrayList(); - - private List fullPredicateInfoes = Lists.newArrayList(); - - private boolean fastCheck; - - public RowTypeInfo getRowTypeInfo(){ - Class[] fieldClass = getFieldClasses(); - TypeInformation[] types = new TypeInformation[fieldClass.length]; - String[] fieldNames = getFields(); - for(int i=0; i optionalDataType = ClassDataTypeConverter.extractDataType(fieldClass[i]); - if(!optionalDataType.isPresent()){ - throw new RuntimeException(String.format("not support table % field %s type %s", getName(), fieldNames[i], fieldClass[i])); - } - - logicalTypes[i] = optionalDataType.get().getLogicalType(); - } - - return new BaseRowTypeInfo(logicalTypes, fieldNames); - } - - public String getCacheType() { - return cacheType; - } - - public void setCacheType(String cacheType) { - this.cacheType = cacheType; - } - - public int getCacheSize() { - return cacheSize; - } - - public void setCacheSize(int cacheSize) { - this.cacheSize = cacheSize; - } - - public long getCacheTimeout() { - return cacheTimeout; - } - - public void setCacheTimeout(long cacheTimeout) { - this.cacheTimeout = cacheTimeout; - } - - public boolean isPartitionedJoin() { - return partitionedJoin; - } - - public void setPartitionedJoin(boolean partitionedJoin) { - this.partitionedJoin = partitionedJoin; - } - - public String getCacheMode() { - return cacheMode; - } - - public void setCacheMode(String cacheMode) { - this.cacheMode = cacheMode; - } - - public int getAsyncCapacity() { - return asyncCapacity; - } - - public void setAsyncCapacity(int asyncCapacity) { - this.asyncCapacity = asyncCapacity; - } - - public int getAsyncTimeout() { - return asyncTimeout; - } - - public void setAsyncTimeout(int asyncTimeout) { - this.asyncTimeout = asyncTimeout; - } - - public void setPredicateInfoes(List predicateInfoes) { - this.predicateInfoes = predicateInfoes; - } - - public List getPredicateInfoes() { - return predicateInfoes; - } - - public void addPredicateInfo(PredicateInfo predicateInfo) { - this.predicateInfoes.add(predicateInfo); - } - - public List getFullPredicateInfoes() { - return fullPredicateInfoes; - } - - public void addFullPredicateInfoes(PredicateInfo predicateInfo) { - this.fullPredicateInfoes.add(predicateInfo); - } - - public Long getAsyncFailMaxNum(Long defaultValue) { - return Objects.isNull(asyncFailMaxNum) ? defaultValue : asyncFailMaxNum; - } - - public void setAsyncFailMaxNum(Long asyncFailMaxNum) { - this.asyncFailMaxNum = asyncFailMaxNum; - } - - - public int getAsyncPoolSize() { - return asyncPoolSize; - } - - public void setAsyncPoolSize(int asyncPoolSize) { - this.asyncPoolSize = asyncPoolSize; - } - - - public Integer getConnectRetryMaxNum(Integer defaultValue) { - return Objects.isNull(connectRetryMaxNum) ? defaultValue : connectRetryMaxNum; - } - - public void setConnectRetryMaxNum(Integer connectRetryMaxNum) { - this.connectRetryMaxNum = connectRetryMaxNum; - } - - public boolean getFastCheck() { - return fastCheck; - } - - public void setFastCheck(boolean fastCheck) { - this.fastCheck = fastCheck; - } - - @Override - public String toString() { - return "Cache Info{" + - "cacheType='" + cacheType + '\'' + - ", cacheSize=" + cacheSize + - ", cacheTimeout=" + cacheTimeout + - ", asyncCapacity=" + asyncCapacity + - ", asyncTimeout=" + asyncTimeout + - ", asyncPoolSize=" + asyncPoolSize + - ", asyncFailMaxNum=" + asyncFailMaxNum + - ", partitionedJoin=" + partitionedJoin + - ", fastCheck='" + fastCheck + - ", cacheMode='" + cacheMode + '\'' + - '}'; - } - -} diff --git a/core/src/main/java/com/dtstack/flink/sql/side/AllReqRow.java b/core/src/main/java/com/dtstack/flink/sql/side/AllReqRow.java new file mode 100644 index 000000000..e788cf139 --- /dev/null +++ b/core/src/main/java/com/dtstack/flink/sql/side/AllReqRow.java @@ -0,0 +1,67 @@ +/* + * 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 com.dtstack.flink.sql.side; + +import com.dtstack.flink.sql.factory.DTThreadFactory; +import org.apache.flink.api.common.functions.RichFlatMapFunction; +import org.apache.flink.configuration.Configuration; +import org.apache.flink.types.Row; + +import java.sql.SQLException; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +/** + * Reason: + * Date: 2018/9/18 + * Company: www.dtstack.com + * @author xuchao + */ + +public abstract class AllReqRow extends RichFlatMapFunction implements ISideReqRow { + + protected SideInfo sideInfo; + + private ScheduledExecutorService es; + + public AllReqRow(SideInfo sideInfo){ + this.sideInfo = sideInfo; + + } + + protected abstract void initCache() throws SQLException; + + protected abstract void reloadCache(); + + @Override + public void open(Configuration parameters) throws Exception { + super.open(parameters); + initCache(); + System.out.println("----- all cacheRef init end-----"); + + //start reload cache thread + SideTableInfo sideTableInfo = sideInfo.getSideTableInfo(); + es = Executors.newSingleThreadScheduledExecutor(new DTThreadFactory("cache-all-reload")); + es.scheduleAtFixedRate(() -> reloadCache(), sideTableInfo.getCacheTimeout(), sideTableInfo.getCacheTimeout(), TimeUnit.MILLISECONDS); + } + +} diff --git a/core/src/main/java/com/dtstack/flink/sql/side/AsyncReqRow.java b/core/src/main/java/com/dtstack/flink/sql/side/AsyncReqRow.java new file mode 100644 index 000000000..a496730e4 --- /dev/null +++ b/core/src/main/java/com/dtstack/flink/sql/side/AsyncReqRow.java @@ -0,0 +1,117 @@ +/* + * 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 com.dtstack.flink.sql.side; + +import com.dtstack.flink.sql.enums.ECacheType; +import com.dtstack.flink.sql.side.cache.AbsSideCache; +import com.dtstack.flink.sql.side.cache.CacheObj; +import com.dtstack.flink.sql.side.cache.LRUSideCache; +import org.apache.calcite.sql.JoinType; +import org.apache.flink.configuration.Configuration; +import org.apache.flink.streaming.api.functions.async.ResultFuture; +import org.apache.flink.streaming.api.functions.async.RichAsyncFunction; +import org.apache.flink.streaming.api.operators.async.queue.StreamRecordQueueEntry; +import org.apache.flink.types.Row; + +import java.util.Collection; +import java.util.Collections; +import java.util.concurrent.TimeoutException; + +/** + * All interfaces inherit naming rules: type + "AsyncReqRow" such as == "MysqlAsyncReqRow + * only support Left join / inner join(join),not support right join + * Date: 2018/7/9 + * Company: www.dtstack.com + * @author xuchao + */ + +public abstract class AsyncReqRow extends RichAsyncFunction implements ISideReqRow { + + private static final long serialVersionUID = 2098635244857937717L; + + protected SideInfo sideInfo; + + public AsyncReqRow(SideInfo sideInfo){ + this.sideInfo = sideInfo; + } + + @Override + public void timeout(Row input, ResultFuture resultFuture) throws Exception { + StreamRecordQueueEntry future = (StreamRecordQueueEntry)resultFuture; + try { + if (null == future.get()) { + new TimeoutException("Async function call has timed out."); + } + } catch (Exception e) { + throw new Exception(e); + } + } + + private void initCache(){ + SideTableInfo sideTableInfo = sideInfo.getSideTableInfo(); + if(sideTableInfo.getCacheType() == null || ECacheType.NONE.name().equalsIgnoreCase(sideTableInfo.getCacheType())){ + return; + } + + AbsSideCache sideCache; + if(ECacheType.LRU.name().equalsIgnoreCase(sideTableInfo.getCacheType())){ + sideCache = new LRUSideCache(sideTableInfo); + sideInfo.setSideCache(sideCache); + }else{ + throw new RuntimeException("not support side cache with type:" + sideTableInfo.getCacheType()); + } + + sideCache.initCache(); + } + + protected CacheObj getFromCache(String key){ + return sideInfo.getSideCache().getFromCache(key); + } + + protected void putCache(String key, CacheObj value){ + sideInfo.getSideCache().putCache(key, value); + } + + protected boolean openCache(){ + return sideInfo.getSideCache() != null; + } + + protected void dealMissKey(Row input, ResultFuture resultFuture){ + if(sideInfo.getJoinType() == JoinType.LEFT){ + //Reserved left table data + Row row = fillData(input, null); + resultFuture.complete(Collections.singleton(row)); + }else{ + resultFuture.complete(null); + } + } + + @Override + public void open(Configuration parameters) throws Exception { + super.open(parameters); + initCache(); + } + + @Override + public void close() throws Exception { + super.close(); + } +} diff --git a/core/src/main/java/com/dtstack/flink/sql/side/BaseAllReqRow.java b/core/src/main/java/com/dtstack/flink/sql/side/BaseAllReqRow.java deleted file mode 100644 index c35c57bc8..000000000 --- a/core/src/main/java/com/dtstack/flink/sql/side/BaseAllReqRow.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side; - -import com.dtstack.flink.sql.factory.DTThreadFactory; -import com.dtstack.flink.sql.util.RowDataComplete; -import org.apache.calcite.sql.JoinType; -import org.apache.flink.api.common.functions.RichFlatMapFunction; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.configuration.Configuration; -import org.apache.flink.table.dataformat.BaseRow; -import org.apache.flink.table.dataformat.GenericRow; -import org.apache.flink.table.typeutils.TimeIndicatorTypeInfo; -import org.apache.flink.util.Collector; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.sql.SQLException; -import java.sql.Timestamp; -import java.time.LocalDateTime; -import java.util.Map; -import java.util.TimeZone; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -/** - * Reason: - * Date: 2018/9/18 - * Company: www.dtstack.com - * - * @author xuchao - */ - -public abstract class BaseAllReqRow extends RichFlatMapFunction implements ISideReqRow { - - private static final Logger LOG = LoggerFactory.getLogger(BaseAllReqRow.class); - - public static final long LOAD_DATA_ERROR_SLEEP_TIME = 5_000L; - - public static final TimeZone LOCAL_TZ = TimeZone.getDefault(); - - protected BaseSideInfo sideInfo; - - private ScheduledExecutorService es; - - public BaseAllReqRow(BaseSideInfo sideInfo) { - this.sideInfo = sideInfo; - - } - - protected abstract void initCache() throws SQLException; - - protected abstract void reloadCache(); - - @Override - public void open(Configuration parameters) throws Exception { - super.open(parameters); - initCache(); - LOG.info("----- all cacheRef init end-----"); - - //start reload cache thread - AbstractSideTableInfo sideTableInfo = sideInfo.getSideTableInfo(); - es = new ScheduledThreadPoolExecutor(1, new DTThreadFactory("cache-all-reload")); - es.scheduleAtFixedRate(() -> reloadCache(), sideTableInfo.getCacheTimeout(), sideTableInfo.getCacheTimeout(), TimeUnit.MILLISECONDS); - } - - protected Object convertTimeIndictorTypeInfo(Integer index, Object obj) { - boolean isTimeIndicatorTypeInfo = TimeIndicatorTypeInfo.class.isAssignableFrom(sideInfo.getRowTypeInfo().getTypeAt(index).getClass()); - - //Type information for indicating event or processing time. However, it behaves like a regular SQL timestamp but is serialized as Long. - if (obj instanceof LocalDateTime && isTimeIndicatorTypeInfo) { - //去除上一层OutputRowtimeProcessFunction 调用时区导致的影响 - obj = ((Timestamp) obj).getTime() + (long)LOCAL_TZ.getOffset(((Timestamp) obj).getTime()); - } - return obj; - } - - protected void sendOutputRow(BaseRow value, Object sideInput, Collector out) { - if (sideInput == null && sideInfo.getJoinType() != JoinType.LEFT) { - return; - } - BaseRow row = fillData(value, sideInput); - RowDataComplete.collectBaseRow(out, row); - } - - @Override - public BaseRow fillData(BaseRow input, Object sideInput) { - GenericRow genericRow = (GenericRow) input; - Map cacheInfo = (Map) sideInput; - GenericRow row = new GenericRow(sideInfo.getOutFieldInfoList().size()); - row.setHeader(genericRow.getHeader()); - for (Map.Entry entry : sideInfo.getInFieldIndex().entrySet()) { - // origin value - Object obj = genericRow.getField(entry.getValue()); - obj = dealTimeAttributeType(sideInfo.getRowTypeInfo().getTypeAt(entry.getValue()).getClass(), obj); - row.setField(entry.getKey(), obj); - } - - for (Map.Entry entry : sideInfo.getSideFieldNameIndex().entrySet()) { - if (cacheInfo == null) { - row.setField(entry.getKey(), null); - } else { - row.setField(entry.getKey(), cacheInfo.get(entry.getValue())); - } - } - return row; - } - - /** - * covert flink time attribute.Type information for indicating event or processing time. - * However, it behaves like a regular SQL timestamp but is serialized as Long. - * - * @param entry - * @param obj - * @return - */ - protected Object dealTimeAttributeType(Class entry, Object obj) { - boolean isTimeIndicatorTypeInfo = TimeIndicatorTypeInfo.class.isAssignableFrom(entry); - if (obj instanceof Timestamp && isTimeIndicatorTypeInfo) { - //去除上一层OutputRowtimeProcessFunction 调用时区导致的影响 - obj = ((Timestamp) obj).getTime() + (long)LOCAL_TZ.getOffset(((Timestamp) obj).getTime()); - } - return obj; - } - - @Override - public void close() throws Exception { - if (null != es && !es.isShutdown()) { - es.shutdown(); - } - } -} diff --git a/core/src/main/java/com/dtstack/flink/sql/side/BaseAsyncReqRow.java b/core/src/main/java/com/dtstack/flink/sql/side/BaseAsyncReqRow.java deleted file mode 100644 index a9cb0d7c4..000000000 --- a/core/src/main/java/com/dtstack/flink/sql/side/BaseAsyncReqRow.java +++ /dev/null @@ -1,314 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side; - -import com.dtstack.flink.sql.enums.ECacheContentType; -import com.dtstack.flink.sql.enums.ECacheType; -import com.dtstack.flink.sql.exception.ExceptionTrace; -import com.dtstack.flink.sql.metric.MetricConstant; -import com.dtstack.flink.sql.side.cache.AbstractSideCache; -import com.dtstack.flink.sql.side.cache.CacheObj; -import com.dtstack.flink.sql.side.cache.LRUSideCache; -import com.dtstack.flink.sql.util.ReflectionUtils; -import com.dtstack.flink.sql.util.RowDataComplete; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import org.apache.calcite.sql.JoinType; -import org.apache.commons.collections.MapUtils; -import org.apache.commons.collections.map.CaseInsensitiveMap; -import org.apache.flink.api.common.functions.RuntimeContext; -import org.apache.flink.configuration.Configuration; -import org.apache.flink.metrics.Counter; -import org.apache.flink.runtime.execution.SuppressRestartsException; -import org.apache.flink.streaming.api.functions.async.ResultFuture; -import org.apache.flink.streaming.api.functions.async.RichAsyncFunction; -import org.apache.flink.streaming.api.operators.StreamingRuntimeContext; -import org.apache.flink.streaming.runtime.tasks.ProcessingTimeService; -import org.apache.flink.table.dataformat.BaseRow; -import org.apache.flink.table.dataformat.GenericRow; -import org.apache.flink.table.typeutils.TimeIndicatorTypeInfo; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.sql.Timestamp; -import java.time.LocalDateTime; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.TimeZone; -import java.util.concurrent.ScheduledFuture; - -/** - * All interfaces inherit naming rules: type + "AsyncReqRow" such as == "MysqlAsyncReqRow - * only support Left join / inner join(join),not support right join - * Date: 2018/7/9 - * Company: www.dtstack.com - * - * @author xuchao - */ - -public abstract class BaseAsyncReqRow extends RichAsyncFunction implements ISideReqRow { - private static final Logger LOG = LoggerFactory.getLogger(BaseAsyncReqRow.class); - private static final long serialVersionUID = 2098635244857937717L; - private RuntimeContext runtimeContext; - private static int TIMEOUT_LOG_FLUSH_NUM = 10; - private int timeOutNum = 0; - protected BaseSideInfo sideInfo; - protected transient Counter parseErrorRecords; - private static final TimeZone LOCAL_TZ = TimeZone.getDefault(); - // 异步维表连接是否共享 - protected boolean clientShare = false; - // 异步维表共享连接池默认大小 - protected int poolSize = 5; - - public BaseAsyncReqRow(BaseSideInfo sideInfo) { - this.sideInfo = sideInfo; - } - - @Override - public void setRuntimeContext(RuntimeContext runtimeContext) { - super.setRuntimeContext(runtimeContext); - this.runtimeContext = runtimeContext; - - Map globalJobParameters = runtimeContext.getExecutionConfig().getGlobalJobParameters().toMap(); - Map sensitiveParameters = new CaseInsensitiveMap(); - sensitiveParameters.putAll(globalJobParameters); - this.clientShare = Boolean.parseBoolean(sensitiveParameters.getOrDefault("async.side.clientShare", "false")); - this.poolSize = Integer.parseInt(sensitiveParameters.getOrDefault("async.side.poolSize", "5")); - } - - @Override - public void open(Configuration parameters) throws Exception { - super.open(parameters); - initCache(); - initMetric(); - LOG.info("async dim table config info: {} ", sideInfo.getSideTableInfo().toString()); - } - - private void initCache() { - AbstractSideTableInfo sideTableInfo = sideInfo.getSideTableInfo(); - if (sideTableInfo.getCacheType() == null || ECacheType.NONE.name().equalsIgnoreCase(sideTableInfo.getCacheType())) { - return; - } - - AbstractSideCache sideCache; - if (ECacheType.LRU.name().equalsIgnoreCase(sideTableInfo.getCacheType())) { - sideCache = new LRUSideCache(sideTableInfo); - sideInfo.setSideCache(sideCache); - } else { - throw new RuntimeException("not support side cache with type:" + sideTableInfo.getCacheType()); - } - - sideCache.initCache(); - } - - private void initMetric() { - parseErrorRecords = getRuntimeContext().getMetricGroup().counter(MetricConstant.DT_NUM_SIDE_PARSE_ERROR_RECORDS); - } - - - protected Object convertTimeIndictorTypeInfo(Integer index, Object obj) { - boolean isTimeIndicatorTypeInfo = TimeIndicatorTypeInfo.class.isAssignableFrom(sideInfo.getRowTypeInfo().getTypeAt(index).getClass()); - - //Type information for indicating event or processing time. However, it behaves like a regular SQL timestamp but is serialized as Long. - if (obj instanceof LocalDateTime && isTimeIndicatorTypeInfo) { - //去除上一层OutputRowtimeProcessFunction 调用时区导致的影响 - obj = ((Timestamp) obj).getTime() + (long)LOCAL_TZ.getOffset(((Timestamp) obj).getTime()); - } - return obj; - } - - protected CacheObj getFromCache(String key) { - return sideInfo.getSideCache().getFromCache(key); - } - - protected void putCache(String key, CacheObj value) { - sideInfo.getSideCache().putCache(key, value); - } - - protected boolean openCache() { - return sideInfo.getSideCache() != null; - } - - protected void dealMissKey(BaseRow input, ResultFuture resultFuture) { - if (sideInfo.getJoinType() == JoinType.LEFT) { - //Reserved left table data - try { - BaseRow row = fillData(input, null); - RowDataComplete.completeBaseRow(resultFuture, row); - } catch (Exception e) { - LOG.error( - String.format( - "Fill data error. \nRow: %s\nCause: %s", - input.toString(), - ExceptionTrace.traceOriginalCause(e)) - ); - dealFillDataError(input, resultFuture, e); - } - } else { - resultFuture.complete(Collections.EMPTY_LIST); - } - } - - protected void dealCacheData(String key, CacheObj missKeyObj) { - if (openCache()) { - putCache(key, missKeyObj); - } - } - - @Override - public void timeout(BaseRow input, ResultFuture resultFuture) throws Exception { - - if (timeOutNum % TIMEOUT_LOG_FLUSH_NUM == 0) { - LOG.info("Async function call has timed out. input:{}, timeOutNum:{}", input.toString(), timeOutNum); - } - timeOutNum++; - - if (timeOutNum > sideInfo.getSideTableInfo().getErrorLimit()) { - resultFuture.completeExceptionally( - new SuppressRestartsException( - new Throwable( - String.format( - "Async function call timedOutNum beyond limit. %s", - sideInfo.getSideTableInfo().getErrorLimit() - ) - ) - )); - } else { - resultFuture.complete(Collections.EMPTY_LIST); - } - } - - protected void preInvoke(BaseRow input, ResultFuture resultFuture) - throws InvocationTargetException, IllegalAccessException { - registerTimerAndAddToHandler(input, resultFuture); - } - - @Override - public void asyncInvoke(BaseRow row, ResultFuture resultFuture) throws Exception { - preInvoke(row, resultFuture); - Map inputParams = parseInputParam(row); - if (MapUtils.isEmpty(inputParams)) { - dealMissKey(row, resultFuture); - return; - } - if (isUseCache(inputParams)) { - invokeWithCache(inputParams, row, resultFuture); - return; - } - handleAsyncInvoke(inputParams, row, resultFuture); - } - - private Map parseInputParam(BaseRow input) { - GenericRow genericRow = (GenericRow) input; - Map inputParams = Maps.newLinkedHashMap(); - for (int i = 0; i < sideInfo.getEqualValIndex().size(); i++) { - Integer conValIndex = sideInfo.getEqualValIndex().get(i); - Object equalObj = genericRow.getField(conValIndex); - // comment by tiezhu - // 假设SQL中有三个主键[a, b, c],同时主键[b]的值为null,那么 - // inputParams中只会有主键[a]的值,主键[b, c]都不包含,导致 - // 后面rdb 维表替换where 条件时缺少 value,查询SQL 执行失败 -// if (equalObj == null) { -// return inputParams; -// } - String columnName = sideInfo.getEqualFieldList().get(i); - inputParams.put(columnName, equalObj); - } - return inputParams; - } - - protected boolean isUseCache(Map inputParams) { - return openCache() && getFromCache(buildCacheKey(inputParams)) != null; - } - - private void invokeWithCache(Map inputParams, BaseRow input, ResultFuture resultFuture) { - if (openCache()) { - CacheObj val = getFromCache(buildCacheKey(inputParams)); - if (val != null) { - if (ECacheContentType.MissVal == val.getType()) { - dealMissKey(input, resultFuture); - } else if (ECacheContentType.SingleLine == val.getType()) { - try { - BaseRow row = fillData(input, val.getContent()); - RowDataComplete.completeBaseRow(resultFuture, row); - } catch (Exception e) { - dealFillDataError(input, resultFuture, e); - } - } else if (ECacheContentType.MultiLine == val.getType()) { - try { - List rowList = Lists.newArrayList(); - for (Object one : (List) val.getContent()) { - BaseRow row = fillData(input, one); - rowList.add(row); - } - RowDataComplete.completeBaseRow(resultFuture,rowList); - } catch (Exception e) { - dealFillDataError(input, resultFuture, e); - } - } else { - resultFuture.completeExceptionally(new RuntimeException("not support cache obj type " + val.getType())); - } - } - } - } - - public abstract void handleAsyncInvoke(Map inputParams, BaseRow input, ResultFuture resultFuture) throws Exception; - - public abstract String buildCacheKey(Map inputParams); - - private ProcessingTimeService getProcessingTimeService() { - return ((StreamingRuntimeContext) this.runtimeContext).getProcessingTimeService(); - } - - protected ScheduledFuture registerTimer(BaseRow input, ResultFuture resultFuture) { - long timeoutTimestamp = sideInfo.getSideTableInfo().getAsyncTimeout() + getProcessingTimeService().getCurrentProcessingTime(); - return getProcessingTimeService().registerTimer( - timeoutTimestamp, - timestamp -> timeout(input, resultFuture)); - } - - protected void registerTimerAndAddToHandler(BaseRow input, ResultFuture resultFuture) - throws InvocationTargetException, IllegalAccessException { - ScheduledFuture timeFuture = registerTimer(input, resultFuture); - // resultFuture 是ResultHandler 的实例 - Method setTimeoutTimer = ReflectionUtils.getDeclaredMethod(resultFuture, "setTimeoutTimer", ScheduledFuture.class); - setTimeoutTimer.setAccessible(true); - setTimeoutTimer.invoke(resultFuture, timeFuture); - } - - - protected void dealFillDataError(BaseRow input, ResultFuture resultFuture, Throwable e) { - parseErrorRecords.inc(); - if (parseErrorRecords.getCount() > sideInfo.getSideTableInfo().getErrorLimit()) { - LOG.info("dealFillDataError", e); - resultFuture.completeExceptionally(new SuppressRestartsException(e)); - } else { - dealMissKey(input, resultFuture); - } - } - - @Override - public void close() throws Exception { - super.close(); - } -} diff --git a/core/src/main/java/com/dtstack/flink/sql/side/BaseSideInfo.java b/core/src/main/java/com/dtstack/flink/sql/side/BaseSideInfo.java deleted file mode 100644 index 8579afe8f..000000000 --- a/core/src/main/java/com/dtstack/flink/sql/side/BaseSideInfo.java +++ /dev/null @@ -1,363 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side; - -import com.dtstack.flink.sql.side.cache.AbstractSideCache; -import com.google.common.base.Preconditions; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import org.apache.calcite.sql.JoinType; -import org.apache.calcite.sql.SqlBasicCall; -import org.apache.calcite.sql.SqlIdentifier; -import org.apache.calcite.sql.SqlKind; -import org.apache.calcite.sql.SqlLiteral; -import org.apache.calcite.sql.SqlNode; -import org.apache.calcite.util.NlsString; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.table.runtime.typeutils.BaseRowTypeInfo; - -import java.io.Serializable; -import java.util.List; -import java.util.Map; - -/** - * Reason: - * Date: 2018/9/18 - * Company: www.dtstack.com - * @author xuchao - */ - -public abstract class BaseSideInfo implements Serializable{ - - protected static final String QUOTE = "'"; - protected static final String ESCAPEQUOTE = "''"; - - protected RowTypeInfo rowTypeInfo; - - protected List outFieldInfoList; - - protected List equalFieldList = Lists.newArrayList(); - - protected List equalValIndex = Lists.newArrayList(); - - protected String sqlCondition = ""; - - protected String sideSelectFields = ""; - - protected Map sideSelectFieldsType = Maps.newHashMap(); - - protected JoinType joinType; - - //key:Returns the value of the position, value: the ref field index​in the input table - protected Map inFieldIndex = Maps.newHashMap(); - - //key:Returns the value of the position, value: the ref field index​in the side table - protected Map sideFieldIndex = Maps.newHashMap(); - - //key:Returns the value of the position, value: the ref field name​in the side table - protected Map sideFieldNameIndex = Maps.newHashMap(); - - protected AbstractSideTableInfo sideTableInfo; - - protected AbstractSideCache sideCache; - - protected JoinInfo joinInfo; - - public BaseSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, - AbstractSideTableInfo sideTableInfo){ - this.rowTypeInfo = rowTypeInfo; - this.outFieldInfoList = outFieldInfoList; - this.joinType = joinInfo.getJoinType(); - this.sideTableInfo = sideTableInfo; - this.joinInfo = joinInfo; - parseSelectFields(joinInfo); - buildEqualInfo(joinInfo, sideTableInfo); - } - - public void parseSelectFields(JoinInfo joinInfo){ - String sideTableName = joinInfo.getSideTableName(); - String nonSideTableName = joinInfo.getNonSideTable(); - List fields = Lists.newArrayList(); - int sideTableFieldIndex = 0; - - for( int i=0; i getOutFieldInfoList() { - return outFieldInfoList; - } - - public void setOutFieldInfoList(List outFieldInfoList) { - this.outFieldInfoList = outFieldInfoList; - } - - public List getEqualFieldList() { - return equalFieldList; - } - - public void setEqualFieldList(List equalFieldList) { - this.equalFieldList = equalFieldList; - } - - public List getEqualValIndex() { - return equalValIndex; - } - - public void setEqualValIndex(List equalValIndex) { - this.equalValIndex = equalValIndex; - } - - public String getSqlCondition() { - return sqlCondition; - } - - public void setSqlCondition(String sqlCondition) { - this.sqlCondition = sqlCondition; - } - - public String getSideSelectFields() { - return sideSelectFields; - } - - public void setSideSelectFields(String sideSelectFields) { - this.sideSelectFields = sideSelectFields; - } - - public JoinType getJoinType() { - return joinType; - } - - public void setJoinType(JoinType joinType) { - this.joinType = joinType; - } - - public Map getInFieldIndex() { - return inFieldIndex; - } - - public void setInFieldIndex(Map inFieldIndex) { - this.inFieldIndex = inFieldIndex; - } - - public Map getSideFieldIndex() { - return sideFieldIndex; - } - - public void setSideFieldIndex(Map sideFieldIndex) { - this.sideFieldIndex = sideFieldIndex; - } - - public AbstractSideTableInfo getSideTableInfo() { - return sideTableInfo; - } - - public void setSideTableInfo(AbstractSideTableInfo sideTableInfo) { - this.sideTableInfo = sideTableInfo; - } - - public AbstractSideCache getSideCache() { - return sideCache; - } - - public void setSideCache(AbstractSideCache sideCache) { - this.sideCache = sideCache; - } - - public Map getSideFieldNameIndex() { - return sideFieldNameIndex; - } - - public void setSideFieldNameIndex(Map sideFieldNameIndex) { - this.sideFieldNameIndex = sideFieldNameIndex; - } - - public Map getSideSelectFieldsType() { - return sideSelectFieldsType; - } - - public void setSideSelectFieldsType(Map sideSelectFieldsType) { - this.sideSelectFieldsType = sideSelectFieldsType; - } - - public String getSelectSideFieldType(int index){ - return sideSelectFieldsType.get(index); - } - - public String[] getFieldNames(){ - - int fieldTypeLength = rowTypeInfo.getFieldTypes().length; - if( fieldTypeLength == 2 - && rowTypeInfo.getFieldTypes()[1].getClass().equals(BaseRowTypeInfo.class)){ - return ((BaseRowTypeInfo)rowTypeInfo.getFieldTypes()[1]).getFieldNames(); - } else if(fieldTypeLength ==1 - && rowTypeInfo.getFieldTypes()[0].getClass().equals(BaseRowTypeInfo.class)){ - return ((BaseRowTypeInfo)rowTypeInfo.getFieldTypes()[0]).getFieldNames(); - }else { - return rowTypeInfo.getFieldNames(); - } - } -} diff --git a/core/src/main/java/com/dtstack/flink/sql/side/FieldInfo.java b/core/src/main/java/com/dtstack/flink/sql/side/FieldInfo.java index 2367331b7..f8ba77383 100644 --- a/core/src/main/java/com/dtstack/flink/sql/side/FieldInfo.java +++ b/core/src/main/java/com/dtstack/flink/sql/side/FieldInfo.java @@ -16,20 +16,18 @@ * limitations under the License. */ + package com.dtstack.flink.sql.side; import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.table.types.logical.LogicalType; import java.io.Serializable; -import java.util.Objects; /** * Reason: * Date: 2018/7/23 * Company: www.dtstack.com - * * @author xuchao */ @@ -43,8 +41,6 @@ public class FieldInfo implements Serializable { private TypeInformation typeInformation; - private LogicalType logicalType; - public String getTable() { return table; } @@ -68,42 +64,4 @@ public TypeInformation getTypeInformation() { public void setTypeInformation(TypeInformation typeInformation) { this.typeInformation = typeInformation; } - - public LogicalType getLogicalType() { - return logicalType; - } - - public void setLogicalType(LogicalType logicalType) { - this.logicalType = logicalType; - } - - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - - if (o == null || getClass() != o.getClass()) { - return false; - } - - FieldInfo fieldInfo = (FieldInfo) o; - return Objects.equals(table, fieldInfo.table) && - Objects.equals(fieldName, fieldInfo.fieldName); - } - - @Override - public int hashCode() { - return Objects.hash(table, fieldName); - } - - @Override - public String toString() { - return "FieldInfo{" + - "table='" + table + '\'' + - ", fieldName='" + fieldName + '\'' + - ", typeInformation=" + typeInformation + - '}'; - } } diff --git a/core/src/main/java/com/dtstack/flink/sql/side/FieldReplaceInfo.java b/core/src/main/java/com/dtstack/flink/sql/side/FieldReplaceInfo.java index dfab231ca..37b23d046 100644 --- a/core/src/main/java/com/dtstack/flink/sql/side/FieldReplaceInfo.java +++ b/core/src/main/java/com/dtstack/flink/sql/side/FieldReplaceInfo.java @@ -21,11 +21,9 @@ package com.dtstack.flink.sql.side; import com.google.common.collect.HashBasedTable; -import org.apache.commons.lang3.StringUtils; - /** - * 用于记录转换之后的表和原来表直接字段的关联关系 + * Reason: * Date: 2018/8/30 * Company: www.dtstack.com * @author xuchao @@ -39,8 +37,6 @@ public class FieldReplaceInfo { private String targetTableAlias = null; - private FieldReplaceInfo preNode = null; - public void setMappingTable(HashBasedTable mappingTable) { this.mappingTable = mappingTable; } @@ -61,39 +57,7 @@ public String getTargetTableAlias() { return targetTableAlias; } - public FieldReplaceInfo getPreNode() { - return preNode; - } - - public void setPreNode(FieldReplaceInfo preNode) { - this.preNode = preNode; - } - public void setTargetTableAlias(String targetTableAlias) { this.targetTableAlias = targetTableAlias; } - - /** - * 根据原始的tableName + fieldName 获取转换之后的fieldName - * @param tableName - * @param fieldName - * @return - */ - public String getTargetFieldName(String tableName, String fieldName) { - String targetFieldName = mappingTable.get(tableName, fieldName); - if(StringUtils.isNotBlank(targetFieldName)){ - return targetFieldName; - } - - if(preNode == null){ - return null; - } - - String preNodeTargetFieldName = preNode.getTargetFieldName(tableName, fieldName); - if(StringUtils.isBlank(preNodeTargetFieldName)){ - return null; - } - - return mappingTable.get(preNode.getTargetTableAlias(), preNodeTargetFieldName); - } } diff --git a/core/src/main/java/com/dtstack/flink/sql/side/ISideReqRow.java b/core/src/main/java/com/dtstack/flink/sql/side/ISideReqRow.java index 11a54d329..88066e37f 100644 --- a/core/src/main/java/com/dtstack/flink/sql/side/ISideReqRow.java +++ b/core/src/main/java/com/dtstack/flink/sql/side/ISideReqRow.java @@ -18,7 +18,7 @@ package com.dtstack.flink.sql.side; -import org.apache.flink.table.dataformat.BaseRow; +import org.apache.flink.types.Row; /** * @@ -28,6 +28,6 @@ */ public interface ISideReqRow { - BaseRow fillData(BaseRow input, Object sideInput); + Row fillData(Row input, Object sideInput); } diff --git a/core/src/main/java/com/dtstack/flink/sql/side/JoinInfo.java b/core/src/main/java/com/dtstack/flink/sql/side/JoinInfo.java index 547cab12b..6fde02493 100644 --- a/core/src/main/java/com/dtstack/flink/sql/side/JoinInfo.java +++ b/core/src/main/java/com/dtstack/flink/sql/side/JoinInfo.java @@ -20,9 +20,6 @@ package com.dtstack.flink.sql.side; -import com.dtstack.flink.sql.util.TableUtils; -import com.google.common.collect.HashBasedTable; -import com.google.common.collect.Maps; import org.apache.calcite.sql.JoinType; import org.apache.calcite.sql.SqlNode; import com.google.common.base.Strings; @@ -34,6 +31,7 @@ * Join信息 * Date: 2018/7/24 * Company: www.dtstack.com + * * @author xuchao */ @@ -42,7 +40,9 @@ public class JoinInfo implements Serializable { private static final long serialVersionUID = -1L; //左表是否是维表 - private boolean leftIsSideTable = false; + private boolean leftIsSideTable; + //左表是 转换后的中间表 + private boolean leftIsMidTable; //右表是否是维表 private boolean rightIsSideTable; @@ -55,31 +55,19 @@ public class JoinInfo implements Serializable { private String rightTableAlias; - private transient SqlNode leftNode; + private SqlNode leftNode; - private transient SqlNode rightNode; + private SqlNode rightNode; - private transient SqlNode condition; + private SqlNode condition; - private transient SqlNode selectFields; + private SqlNode selectFields; - private transient SqlNode selectNode; + private SqlNode selectNode; private JoinType joinType; - - private String scope = ""; - - private String newTableName = null; - - /** - * 左表需要查询的字段信息和output的时候对应的列名称 - */ - private Map leftSelectFieldInfo = Maps.newHashMap(); - - /** - * 右表需要查询的字段信息和output的时候对应的列名称 - */ - private Map rightSelectFieldInfo = Maps.newHashMap(); + // 左边是中间转换表,做表映射关系,给替换属性名称使用 + private Map leftTabMapping; public String getSideTableName(){ if(leftIsSideTable){ @@ -98,16 +86,30 @@ public String getNonSideTable(){ } public String getNewTableName(){ - return this.newTableName; + //兼容左边表是as 的情况 + String leftStr = leftTableName; + leftStr = Strings.isNullOrEmpty(leftStr) ? leftTableAlias : leftStr; + return leftStr + "_" + rightTableName; + } + + public boolean isLeftIsMidTable() { + return leftIsMidTable; } - public void setNewTableName(String newTableName){ - this.newTableName = newTableName; + public void setLeftIsMidTable(boolean leftIsMidTable) { + this.leftIsMidTable = leftIsMidTable; + } + + public Map getLeftTabMapping() { + return leftTabMapping; + } + + public void setLeftTabMapping(Map leftTabMapping) { + this.leftTabMapping = leftTabMapping; } public String getNewTableAlias(){ - String newName = leftTableAlias + "_" + rightTableAlias; - return TableUtils.buildTableNameWithScope(newName, scope); + return leftTableAlias + "_" + rightTableAlias; } public boolean isLeftIsSideTable() { @@ -209,57 +211,4 @@ public JoinType getJoinType() { public void setJoinType(JoinType joinType) { this.joinType = joinType; } - - public Map getLeftSelectFieldInfo() { - return leftSelectFieldInfo; - } - - public void setLeftSelectFieldInfo(Map leftSelectFieldInfo) { - this.leftSelectFieldInfo = leftSelectFieldInfo; - } - - public Map getRightSelectFieldInfo() { - return rightSelectFieldInfo; - } - - public void setRightSelectFieldInfo(Map rightSelectFieldInfo) { - this.rightSelectFieldInfo = rightSelectFieldInfo; - } - - public HashBasedTable getTableFieldRef(){ - HashBasedTable mappingTable = HashBasedTable.create(); - getLeftSelectFieldInfo().forEach((key, value) -> { - mappingTable.put(getLeftTableAlias(), key, value); - }); - - getRightSelectFieldInfo().forEach((key, value) -> { - mappingTable.put(getRightTableAlias(), key, value); - }); - - return mappingTable; - } - - public String getScope() { - return scope; - } - - public void setScope(String scope) { - this.scope = scope; - } - - @Override - public String toString() { - return "JoinInfo{" + - "leftIsSideTable=" + leftIsSideTable + - ", rightIsSideTable=" + rightIsSideTable + - ", leftTableName='" + leftTableName + '\'' + - ", leftTableAlias='" + leftTableAlias + '\'' + - ", rightTableName='" + rightTableName + '\'' + - ", rightTableAlias='" + rightTableAlias + '\'' + - ", condition=" + condition + - ", selectFields=" + selectFields + - ", selectNode=" + selectNode + - ", joinType=" + joinType + - '}'; - } } diff --git a/core/src/main/java/com/dtstack/flink/sql/side/JoinNodeDealer.java b/core/src/main/java/com/dtstack/flink/sql/side/JoinNodeDealer.java deleted file mode 100644 index 0a0ae5d1a..000000000 --- a/core/src/main/java/com/dtstack/flink/sql/side/JoinNodeDealer.java +++ /dev/null @@ -1,995 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side; - -import com.dtstack.flink.sql.exception.sqlparse.WithoutTableNameException; -import com.dtstack.flink.sql.parser.FlinkPlanner; -import com.dtstack.flink.sql.util.ParseUtils; -import com.dtstack.flink.sql.util.TableUtils; -import com.esotericsoftware.minlog.Log; -import com.google.common.base.Preconditions; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import com.google.common.collect.HashBiMap; -import org.apache.calcite.sql.JoinType; -import org.apache.calcite.sql.SqlAsOperator; -import org.apache.calcite.sql.SqlBasicCall; -import org.apache.calcite.sql.SqlBinaryOperator; -import org.apache.calcite.sql.SqlDataTypeSpec; -import org.apache.calcite.sql.SqlIdentifier; -import org.apache.calcite.sql.SqlJoin; -import org.apache.calcite.sql.SqlKind; -import org.apache.calcite.sql.SqlLiteral; -import org.apache.calcite.sql.SqlNode; -import org.apache.calcite.sql.SqlNodeList; -import org.apache.calcite.sql.SqlOperator; -import org.apache.calcite.sql.fun.SqlCase; -import org.apache.calcite.sql.fun.SqlStdOperatorTable; -import org.apache.calcite.sql.parser.SqlParserPos; -import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.flink.api.java.tuple.Tuple2; - -import java.util.List; -import java.util.Map; -import java.util.Queue; -import java.util.Set; -import java.util.Arrays; -import java.util.stream.Stream; - -import static org.apache.calcite.sql.SqlKind.*; - -/** - * 处理join 节点 - * 1:如果包含维表节点替换为临时查询 - * Date: 2020/2/27 - * Company: www.dtstack.com - * @author xuchao - */ - -public class JoinNodeDealer { - - //用来构建临时的中间查询 - private static final String SELECT_TEMP_SQL = "select %s from %s %s"; - - private SideSQLParser sideSQLParser; - - private FlinkPlanner flinkPlanner = new FlinkPlanner(); - - // 内置无参函数的临时解决方法,防止被误判为表的字段 - private List builtInFunctionNames = Arrays.asList("LOCALTIMESTAMP", "LOCALTIME", "CURRENT_TIMESTAMP", "CURRENT_TIME", "CURRENT_DATE", "PI"); - - public JoinNodeDealer(SideSQLParser sideSQLParser){ - this.sideSQLParser = sideSQLParser; - } - - /** - * 解析 join 操作 - * @param joinNode - * @param sideTableSet 标明哪些表名是维表 - * @param queueInfo sql执行队列 - * @param parentWhere join 关联的最上层的where 节点 - * @param parentSelectList join 关联的最上层的select 节点 - * @param joinFieldSet - * @param tableRef 存储构建临时表查询后源表和新表之间的关联关系 - * @return - */ - public JoinInfo dealJoinNode(SqlJoin joinNode, - Set sideTableSet, - Queue queueInfo, - SqlNode parentWhere, - SqlNodeList parentSelectList, - SqlNodeList parentGroupByList, - Set> joinFieldSet, - Map tableRef, - Map fieldRef, - String scope, - Set joinTableNames) { - - SqlNode leftNode = joinNode.getLeft(); - SqlNode rightNode = joinNode.getRight(); - JoinType joinType = joinNode.getJoinType(); - - String leftTbName = ""; - String leftTbAlias = ""; - String rightTableName = ""; - String rightTableAlias = ""; - - //抽取join中的的条件 - extractJoinField(joinNode.getCondition(), joinFieldSet); - - if (leftNode.getKind() == JOIN) { - //处理连续join - dealNestJoin(joinNode, sideTableSet, queueInfo, parentWhere, parentSelectList, - parentGroupByList, joinFieldSet, tableRef, fieldRef, scope, joinTableNames); - leftNode = joinNode.getLeft(); - } - - if (leftNode.getKind() == AS) { - AliasInfo aliasInfo = (AliasInfo) sideSQLParser.parseSql(leftNode, sideTableSet, queueInfo, - parentWhere, parentSelectList, parentGroupByList, scope, joinTableNames); - leftTbName = aliasInfo.getName(); - leftTbAlias = aliasInfo.getAlias(); - } else if(leftNode.getKind() == IDENTIFIER){ - leftTbName = leftNode.toString(); - leftTbAlias = leftTbName; - } - - boolean leftIsSide = checkIsSideTable(leftTbName, sideTableSet); - Preconditions.checkState(!leftIsSide, "side-table must be at the right of join operator"); - - Tuple2 rightTableNameAndAlias = parseRightNode(rightNode, sideTableSet, queueInfo, - parentWhere, parentSelectList, parentGroupByList, scope, joinTableNames); - rightTableName = rightTableNameAndAlias.f0; - rightTableAlias = rightTableNameAndAlias.f1; - - boolean rightIsSide = checkIsSideTable(rightTableName, sideTableSet); - if(rightIsSide && joinType == JoinType.RIGHT){ - throw new RuntimeException("side join not support join type of right[current support inner join and left join]"); - } - - JoinInfo tableInfo = new JoinInfo(); - tableInfo.setLeftTableName(leftTbName); - tableInfo.setRightTableName(rightTableName); - - leftTbAlias = StringUtils.isEmpty(leftTbAlias) ? leftTbName : leftTbAlias; - rightTableAlias = StringUtils.isEmpty(rightTableAlias) ? rightTableName : rightTableAlias; - - tableInfo.setLeftTableAlias(leftTbAlias); - tableInfo.setRightTableAlias(rightTableAlias); - tableInfo.setRightIsSideTable(rightIsSide); - tableInfo.setLeftNode(leftNode); - tableInfo.setRightNode(rightNode); - tableInfo.setJoinType(joinType); - tableInfo.setCondition(joinNode.getCondition()); - tableInfo.setScope(scope); - tableInfo.setNewTableName(TableUtils.buildTableNameWithScope(leftTbName, leftTbAlias, rightTableName, scope, joinTableNames)); - joinTableNames.add(tableInfo.getNewTableName()); - TableUtils.replaceJoinFieldRefTableName(joinNode.getCondition(), fieldRef); - - //extract 需要查询的字段信息 - if(rightIsSide){ - extractJoinNeedSelectField(leftNode, rightNode, parentWhere, parentSelectList, parentGroupByList, tableRef, joinFieldSet, fieldRef, tableInfo); - } - - if(tableInfo.getLeftNode().getKind() != AS){ - return tableInfo; - } - - SqlKind asNodeFirstKind = ((SqlBasicCall)tableInfo.getLeftNode()).operands[0].getKind(); - if(asNodeFirstKind == SELECT){ - queueInfo.offer(tableInfo.getLeftNode()); - tableInfo.setLeftNode(((SqlBasicCall)tableInfo.getLeftNode()).operands[1]); - } - - return tableInfo; - } - - /** - * 获取join 之后需要查询的字段信息 - */ - public void extractJoinNeedSelectField(SqlNode leftNode, - SqlNode rightNode, - SqlNode parentWhere, - SqlNodeList parentSelectList, - SqlNodeList parentGroupByList, - Map tableRef, - Set> joinFieldSet, - Map fieldRef, - JoinInfo tableInfo){ - - Set extractSelectField = extractField(leftNode, parentWhere, parentSelectList, parentGroupByList, tableRef, joinFieldSet); - Set rightExtractSelectField = extractField(rightNode, parentWhere, parentSelectList, parentGroupByList, tableRef, joinFieldSet); - - //重命名right 中和 left 重名的 - Map leftTbSelectField = Maps.newHashMap(); - Map rightTbSelectField = Maps.newHashMap(); - String newTableName = tableInfo.getNewTableAlias(); - - for(String tmpField : extractSelectField){ - String[] tmpFieldSplit = StringUtils.split(tmpField, '.'); - leftTbSelectField.put(tmpFieldSplit[1], tmpFieldSplit[1]); - fieldRef.put(tmpField, TableUtils.buildTableField(newTableName, tmpFieldSplit[1])); - } - - for(String tmpField : rightExtractSelectField){ - String[] tmpFieldSplit = StringUtils.split(tmpField, '.'); - String originalFieldName = tmpFieldSplit[1]; - String targetFieldName = originalFieldName; - if(leftTbSelectField.containsKey(originalFieldName)){ - targetFieldName = ParseUtils.dealDuplicateFieldName(leftTbSelectField, originalFieldName); - } - - rightTbSelectField.put(originalFieldName, targetFieldName); - fieldRef.put(tmpField, TableUtils.buildTableField(newTableName, targetFieldName)); - } - - tableInfo.setLeftSelectFieldInfo(leftTbSelectField); - tableInfo.setRightSelectFieldInfo(rightTbSelectField); - } - - /** - * 指定的节点关联到的 select 中的字段和 where中的字段 - * @param sqlNode - * @param parentWhere - * @param parentSelectList - * @param parentGroupByList - * @param tableRef - * @param joinFieldSet - * @return - */ - public Set extractField(SqlNode sqlNode, - SqlNode parentWhere, - SqlNodeList parentSelectList, - SqlNodeList parentGroupByList, - Map tableRef, - Set> joinFieldSet){ - Set fromTableNameSet = Sets.newHashSet(); - TableUtils.getFromTableInfo(sqlNode, fromTableNameSet); - Set extractCondition = Sets.newHashSet(); - - extractWhereCondition(fromTableNameSet, (SqlBasicCall) parentWhere, extractCondition); - Set extractSelectField = extractSelectFields(parentSelectList, fromTableNameSet, tableRef); - Set fieldFromJoinCondition = extractSelectFieldFromJoinCondition(joinFieldSet, fromTableNameSet, tableRef); - - Set extractGroupByField = extractFieldFromGroupByList(parentGroupByList, fromTableNameSet, tableRef); - extractSelectField.addAll(extractCondition); - extractSelectField.addAll(fieldFromJoinCondition); - extractSelectField.addAll(extractGroupByField); - - return extractSelectField; - } - - - /** - * 处理多层join - * 判断左节点是否需要创建临时查询 - * (1)右节点是维表 - * (2)左节点不是 as 节点 - */ - private JoinInfo dealNestJoin(SqlJoin joinNode, - Set sideTableSet, - Queue queueInfo, - SqlNode parentWhere, - SqlNodeList parentSelectList, - SqlNodeList parentGroupByList, - Set> joinFieldSet, - Map tableRef, - Map fieldRef, - String scope, - Set joinTableNames){ - - SqlJoin leftJoinNode = (SqlJoin) joinNode.getLeft(); - SqlNode parentRightJoinNode = joinNode.getRight(); - SqlNode rightNode = leftJoinNode.getRight(); - - Tuple2 rightTableNameAndAlias = parseRightNode(rightNode, sideTableSet, queueInfo, - parentWhere, parentSelectList, parentGroupByList, scope, joinTableNames); - Tuple2 parentRightJoinInfo = parseRightNode(parentRightJoinNode, sideTableSet, - queueInfo, parentWhere, parentSelectList, parentGroupByList, scope, joinTableNames); - boolean parentRightIsSide = checkIsSideTable(parentRightJoinInfo.f0, sideTableSet); - - JoinInfo joinInfo = dealJoinNode(leftJoinNode, sideTableSet, queueInfo, parentWhere, parentSelectList, - parentGroupByList, joinFieldSet, tableRef, fieldRef, scope, joinTableNames); - - String rightTableName = rightTableNameAndAlias.f0; - boolean rightIsSide = checkIsSideTable(rightTableName, sideTableSet); - SqlBasicCall buildAs = TableUtils.buildAsNodeByJoinInfo(joinInfo, null, null); - - if(rightIsSide){ - addSideInfoToExeQueue(queueInfo, joinInfo, joinNode, parentSelectList, parentGroupByList, parentWhere, tableRef, fieldRef); - } - - SqlNode newLeftNode = joinNode.getLeft(); - - // 双流JOIN再维表JOIN情况 - if(newLeftNode.getKind() != AS && parentRightIsSide){ - - String leftTbAlias = buildAs.getOperands()[1].toString(); - extractTemporaryQuery(newLeftNode, leftTbAlias, (SqlBasicCall) parentWhere, - parentSelectList, queueInfo, joinFieldSet, tableRef, fieldRef); - - //替换leftNode 为新的查询 - joinNode.setLeft(buildAs); - replaceSelectAndWhereField(buildAs, leftJoinNode, tableRef, fieldRef, parentSelectList, parentGroupByList, parentWhere); - } - - return joinInfo; - } - - /** - * 右边表是维表需要重新构建左表的临时查询 - * 并将joinInfo 添加到执行队列里面 - * @param queueInfo - * @param joinInfo - * @param joinNode - * @param parentSelectList - * @param parentGroupByList - * @param parentWhere - * @param tableRef - */ - public void addSideInfoToExeQueue(Queue queueInfo, - JoinInfo joinInfo, - SqlJoin joinNode, - SqlNodeList parentSelectList, - SqlNodeList parentGroupByList, - SqlNode parentWhere, - Map tableRef, - Map fieldRef){ - //只处理维表 - if(!joinInfo.isRightIsSideTable()){ - return; - } - - SqlBasicCall buildAs = TableUtils.buildAsNodeByJoinInfo(joinInfo, null, null); - SqlNode leftJoinNode = joinNode.getLeft(); - queueInfo.offer(joinInfo); - //替换左表为新的表名称 - joinNode.setLeft(buildAs); - - replaceSelectAndWhereField(buildAs, leftJoinNode, tableRef, fieldRef, parentSelectList, parentGroupByList, parentWhere); - } - - /** - * 替换指定的查询和条件节点中的字段为新的字段 - * @param buildAs - * @param leftJoinNode - * @param tableRef - * @param parentSelectList - * @param parentGroupByList - * @param parentWhere - */ - public void replaceSelectAndWhereField(SqlBasicCall buildAs, - SqlNode leftJoinNode, - Map tableRef, - Map fieldRef, - SqlNodeList parentSelectList, - SqlNodeList parentGroupByList, - SqlNode parentWhere){ - - String newLeftTableName = buildAs.getOperands()[1].toString(); - Set fromTableNameSet = Sets.newHashSet(); - TableUtils.getFromTableInfo(leftJoinNode, fromTableNameSet); - - for(String tbTmp : fromTableNameSet){ - tableRef.put(tbTmp, newLeftTableName); - } - - //替换select field 中的对应字段 - for(SqlNode sqlNode : parentSelectList.getList()){ - for(String tbTmp : fromTableNameSet) { - TableUtils.replaceSelectFieldTable(sqlNode, tbTmp, newLeftTableName, fieldRef); - } - } - - //TODO 应该根据上面的查询字段的关联关系来替换 - //替换where 中的条件相关 - for(String tbTmp : fromTableNameSet){ - TableUtils.replaceWhereCondition(parentWhere, tbTmp, newLeftTableName, fieldRef); - } - - if(parentGroupByList != null){ - for(SqlNode sqlNode : parentGroupByList.getList()){ - for(String tbTmp : fromTableNameSet) { - TableUtils.replaceSelectFieldTable(sqlNode, tbTmp, newLeftTableName, fieldRef); - } - } - } - - } - - /** - * 抽取出中间查询表 - * @param node - * @param tableAlias - * @param parentWhere - * @param parentSelectList - * @param queueInfo - * @param joinFieldSet - * @param tableRef - * @return 源自段和新生成字段之间的映射关系 - */ - private void extractTemporaryQuery(SqlNode node, String tableAlias, - SqlBasicCall parentWhere, - SqlNodeList parentSelectList, - Queue queueInfo, - Set> joinFieldSet, - Map tableRef, - Map fieldRef){ - try{ - //父一级的where 条件中如果只和临时查询相关的条件都截取进来 - Set fromTableNameSet = Sets.newHashSet(); - List extractCondition = Lists.newArrayList(); - - TableUtils.getFromTableInfo(node, fromTableNameSet); - checkAndRemoveWhereCondition(fromTableNameSet, parentWhere, extractCondition); - - if(node.getKind() == JOIN){ - checkAndReplaceJoinCondition(((SqlJoin)node).getCondition(), tableRef); - } - - Set extractSelectField = extractSelectFields(parentSelectList, fromTableNameSet, tableRef); - Set fieldFromJoinCondition = extractSelectFieldFromJoinCondition(joinFieldSet, fromTableNameSet, tableRef); - Set newFields = buildSelectNode(extractSelectField, fieldFromJoinCondition); - String extractSelectFieldStr = StringUtils.join(newFields, ','); - - Map oldRefNewField = buildTmpTableFieldRefOriField(newFields, tableAlias); - fieldRef.putAll(oldRefNewField); - - String extractConditionStr = buildCondition(extractCondition); - - String tmpSelectSql = String.format(SELECT_TEMP_SQL, - extractSelectFieldStr, - node.toString(), - extractConditionStr); - - SqlNode sqlNode = flinkPlanner.getParser().parse(tmpSelectSql); - - SqlBasicCall sqlBasicCall = buildAsSqlNode(tableAlias, sqlNode); - queueInfo.offer(sqlBasicCall); - - //替换select中的表结构 - for(SqlNode tmpSelect : parentSelectList.getList()){ - for(String tbTmp : fromTableNameSet) { - TableUtils.replaceSelectFieldTable(tmpSelect, tbTmp, tableAlias, fieldRef); - } - } - - //替换where 中的条件相关 - for(String tbTmp : fromTableNameSet){ - TableUtils.replaceWhereCondition(parentWhere, tbTmp, tableAlias, fieldRef); - } - - for(String tbTmp : fromTableNameSet){ - tableRef.put(tbTmp, tableAlias); - } - - Log.info("-------build temporary query-----------\n{}", tmpSelectSql); - Log.info("---------------------------------------"); - - }catch (Exception e){ - Log.error("", e); - throw new RuntimeException(e); - } - } - - /** - * 抽取上层需用使用到的字段 - * 由于where字段已经抽取到上一层了所以不用查询出来 - * @param parentSelectList - * @param fromTableNameSet - * @return - */ - private Set extractSelectFields(SqlNodeList parentSelectList, - Set fromTableNameSet, - Map tableRef){ - Set extractFieldList = Sets.newHashSet(); - for(SqlNode selectNode : parentSelectList.getList()){ - extractSelectField(selectNode, extractFieldList, fromTableNameSet, tableRef); - } - - return extractFieldList; - } - - private Set extractSelectFieldFromJoinCondition(Set> joinFieldSet, - Set fromTableNameSet, - Map tableRef){ - Set extractFieldList = Sets.newHashSet(); - for(Tuple2 field : joinFieldSet){ - if(fromTableNameSet.contains(field.f0)){ - extractFieldList.add(field.f0 + "." + field.f1); - } - - if(tableRef.containsKey(field.f0)){ - if(checkContainIterationTableName(fromTableNameSet, field.f0, tableRef)){ - extractFieldList.add(tableRef.get(field.f0) + "." + field.f1); - } - } - } - - return extractFieldList; - } - - private boolean checkContainIterationTableName(Set fromTableNameSet, String checkTableName, Map mappingTableName) { - for (int i = 0; i < mappingTableName.size() + 1; i++) { - if (fromTableNameSet.contains(checkTableName)) { - return true; - } - - checkTableName = mappingTableName.get(checkTableName); - if (checkTableName == null) { - return false; - } - } - return true; - } - - private Set extractFieldFromGroupByList(SqlNodeList parentGroupByList, - Set fromTableNameSet, - Map tableRef){ - - if(parentGroupByList == null){ - return Sets.newHashSet(); - } - - Set extractFieldList = Sets.newHashSet(); - for(SqlNode selectNode : parentGroupByList.getList()){ - extractSelectField(selectNode, extractFieldList, fromTableNameSet, tableRef); - } - - return extractFieldList; - } - - /** - * 从join的条件中获取字段信息 - * @param condition - * @param joinFieldSet - */ - private void extractJoinField(SqlNode condition, Set> joinFieldSet){ - if (null == condition || condition.getKind() == LITERAL) { - return; - } - - SqlKind joinKind = condition.getKind(); - if ( AGGREGATE.contains(condition.getKind()) - || AVG_AGG_FUNCTIONS.contains(joinKind) - || COMPARISON.contains(joinKind) - || FUNCTION.contains(joinKind) - || COVAR_AVG_AGG_FUNCTIONS.contains(joinKind) - || BINARY_ARITHMETIC.contains(joinKind) - || BINARY_COMPARISON.contains(joinKind) - || joinKind == NOT_IN - || joinKind == OR - || joinKind == AND - || joinKind == TUMBLE - || joinKind == TUMBLE_START - || joinKind == TUMBLE_END - || joinKind == SESSION - || joinKind == SESSION_START - || joinKind == SESSION_END - || joinKind == HOP - || joinKind == HOP_START - || joinKind == HOP_END - || joinKind == BETWEEN - || joinKind == IS_NULL - || joinKind == IS_NOT_NULL - || joinKind == CONTAINS - || joinKind == TIMESTAMP_ADD - || joinKind == TIMESTAMP_DIFF - || joinKind == LIKE - || joinKind == COALESCE - ){ - - SqlBasicCall sqlBasicCall = (SqlBasicCall) condition; - for(int i=0; i tuple2 = Tuple2.of(((SqlIdentifier)condition).names.get(0), ((SqlIdentifier)condition).names.get(1)); - joinFieldSet.add(tuple2); - } - } - - - private void extractSelectField(SqlNode selectNode, - Set extractFieldSet, - Set fromTableNameSet, - Map tableRef){ - if (selectNode.getKind() == AS) { - SqlNode leftNode = ((SqlBasicCall) selectNode).getOperands()[0]; - extractSelectField(leftNode, extractFieldSet, fromTableNameSet, tableRef); - - }else if(selectNode.getKind() == IDENTIFIER) { - SqlIdentifier sqlIdentifier = (SqlIdentifier) selectNode; - - if (sqlIdentifier.names.size() == 1) { - if (builtInFunctionNames.contains(sqlIdentifier.toString().toUpperCase())) { - return; - } else { - throw new WithoutTableNameException(sqlIdentifier + " field invalid , please use like t." + sqlIdentifier); - } - } - - String tableName = sqlIdentifier.names.get(0); - //TODO - if(fromTableNameSet.contains(tableName)){ - extractFieldSet.add(sqlIdentifier.toString()); - } else if(fromTableNameSet.contains(tableRef.get(tableName))){ - //TODO extractFieldSet.add(sqlIdentifier.setName(0, tableRef.get(tableName)).toString()); - } - - }else if( AGGREGATE.contains(selectNode.getKind()) - || AVG_AGG_FUNCTIONS.contains(selectNode.getKind()) - || COMPARISON.contains(selectNode.getKind()) - || FUNCTION.contains(selectNode.getKind()) - || COVAR_AVG_AGG_FUNCTIONS.contains(selectNode.getKind()) - || BINARY_ARITHMETIC.contains(selectNode.getKind()) - || BINARY_COMPARISON.contains(selectNode.getKind()) - || selectNode.getKind() == NOT_IN - || selectNode.getKind() == OR - || selectNode.getKind() == AND - || selectNode.getKind() == TUMBLE - || selectNode.getKind() == TUMBLE_START - || selectNode.getKind() == TUMBLE_END - || selectNode.getKind() == SESSION - || selectNode.getKind() == SESSION_START - || selectNode.getKind() == SESSION_END - || selectNode.getKind() == HOP - || selectNode.getKind() == HOP_START - || selectNode.getKind() == HOP_END - || selectNode.getKind() == BETWEEN - || selectNode.getKind() == IS_NULL - || selectNode.getKind() == IS_NOT_NULL - || selectNode.getKind() == CONTAINS - || selectNode.getKind() == TIMESTAMP_ADD - || selectNode.getKind() == TIMESTAMP_DIFF - || selectNode.getKind() == LIKE - || selectNode.getKind() == COALESCE - - ){ - SqlBasicCall sqlBasicCall = (SqlBasicCall) selectNode; - for(int i=0; i parseRightNode(SqlNode sqlNode, Set sideTableSet, Queue queueInfo, - SqlNode parentWhere, SqlNodeList selectList, SqlNodeList parentGroupByList, - String scope, Set joinTableNames) { - Tuple2 tabName = new Tuple2<>("", ""); - if(sqlNode.getKind() == IDENTIFIER){ - tabName.f0 = sqlNode.toString(); - }else{ - AliasInfo aliasInfo = (AliasInfo)sideSQLParser.parseSql(sqlNode, sideTableSet, queueInfo, parentWhere, selectList, parentGroupByList, scope, joinTableNames); - tabName.f0 = aliasInfo.getName(); - tabName.f1 = aliasInfo.getAlias(); - } - return tabName; - } - - private Tuple2 parseLeftNode(SqlNode sqlNode){ - Tuple2 tabName = new Tuple2<>("", ""); - if(sqlNode.getKind() == IDENTIFIER){ - tabName.f0 = sqlNode.toString(); - tabName.f1 = sqlNode.toString(); - }else if (sqlNode.getKind() == AS){ - SqlNode info = ((SqlBasicCall)sqlNode).getOperands()[0]; - SqlNode alias = ((SqlBasicCall) sqlNode).getOperands()[1]; - - tabName.f0 = info.toString(); - tabName.f1 = alias.toString(); - }else { - throw new RuntimeException(""); - } - - return tabName; - } - - public String buildCondition(List conditionList){ - if(CollectionUtils.isEmpty(conditionList)){ - return ""; - } - - return " where " + StringUtils.join(conditionList, " AND "); - } - - /** - * 构建抽取表的查询字段信息 - * 包括去除重复字段,名称相同的取别名 - * @param extractSelectField - * @param joinFieldSet - * @return - */ - public Set buildSelectNode(Set extractSelectField, Set joinFieldSet){ - if(CollectionUtils.isEmpty(extractSelectField)){ - throw new RuntimeException("no field is used"); - } - - Sets.SetView view = Sets.union(extractSelectField, joinFieldSet); - Set newFieldSet = Sets.newHashSet(); - //为相同的列取别名 - HashBiMap refFieldMap = HashBiMap.create(); - for(String field : view){ - String[] fieldInfo = StringUtils.split(field, '.'); - String aliasName = fieldInfo[1]; - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append(field); - if(refFieldMap.inverse().get(aliasName) != null){ - aliasName = ParseUtils.dealDuplicateFieldName(refFieldMap, aliasName); - stringBuilder.append(" as ") - .append(aliasName); - } - - refFieldMap.put(field, aliasName); - - newFieldSet.add(stringBuilder.toString()); - } - - return newFieldSet; - } - - private boolean checkIsSideTable(String tableName, Set sideTableList){ - if(sideTableList.contains(tableName)){ - return true; - } - return false; - } - - private SqlBasicCall buildAsSqlNode(String internalTableName, SqlNode newSource) { - SqlOperator operator = new SqlAsOperator(); - SqlParserPos sqlParserPos = new SqlParserPos(0, 0); - SqlIdentifier sqlIdentifierAlias = new SqlIdentifier(internalTableName, null, sqlParserPos); - SqlNode[] sqlNodes = new SqlNode[2]; - sqlNodes[0] = newSource; - sqlNodes[1] = sqlIdentifierAlias; - return new SqlBasicCall(operator, sqlNodes, sqlParserPos); - } - - /** - * 获取where中和指定表有关联的字段 - * @param fromTableNameSet - * @param parentWhere - * @param extractCondition - */ - private void extractWhereCondition(Set fromTableNameSet, SqlBasicCall parentWhere, Set extractCondition){ - - if(parentWhere == null){ - return; - } - - SqlKind kind = parentWhere.getKind(); - if(kind == AND){ - extractWhereCondition(fromTableNameSet, (SqlBasicCall) parentWhere.getOperands()[0], extractCondition); - extractWhereCondition(fromTableNameSet, (SqlBasicCall) parentWhere.getOperands()[1], extractCondition); - } else { - - Set fieldInfos = Sets.newHashSet(); - TableUtils.getConditionRefTable(parentWhere, fieldInfos); - fieldInfos.forEach(fieldInfo -> { - String[] splitInfo = StringUtils.split(fieldInfo, "."); - if(splitInfo.length == 2 && fromTableNameSet.contains(splitInfo[0])){ - extractCondition.add(fieldInfo); - } - }); - - } - - - } - - - /** - * 检查关联的where 条件中的判断是否可以下移到新构建的子查询 - * @param fromTableNameSet - * @param parentWhere - * @param extractCondition - * @return - */ - private boolean checkAndRemoveWhereCondition(Set fromTableNameSet, - SqlBasicCall parentWhere, - List extractCondition){ - if(parentWhere == null){ - return false; - } - - SqlKind kind = parentWhere.getKind(); - if(kind == AND){ - boolean removeLeft = checkAndRemoveWhereCondition(fromTableNameSet, (SqlBasicCall) parentWhere.getOperands()[0], extractCondition); - boolean removeRight = checkAndRemoveWhereCondition(fromTableNameSet, (SqlBasicCall) parentWhere.getOperands()[1], extractCondition); - //DO remove - if(removeLeft){ - extractCondition.add(removeWhereConditionNode(parentWhere, 0)); - } - - if(removeRight){ - extractCondition.add(removeWhereConditionNode(parentWhere, 1)); - } - - return false; - } else { - //条件表达式,如果该条件关联的表都是指定的表则移除 - Set fieldInfos = Sets.newHashSet(); - TableUtils.getConditionRefTable(parentWhere, fieldInfos); - Set conditionRefTableNameSet = Sets.newHashSet(); - - fieldInfos.forEach(fieldInfo -> { - String[] splitInfo = StringUtils.split(fieldInfo, "."); - if(splitInfo.length == 2){ - conditionRefTableNameSet.add(splitInfo[0]); - } - }); - - - if(fromTableNameSet.containsAll(conditionRefTableNameSet)){ - return true; - } - - return false; - } - } - - /** - * 抽取where 条件中指定的条件 - * @param parentWhere - * @param index - * @return - */ - public SqlBasicCall removeWhereConditionNode(SqlBasicCall parentWhere, int index){ - SqlBasicCall oldCondition = (SqlBasicCall) parentWhere.getOperands()[index]; - parentWhere.setOperand(index, buildEmptyCondition()); - return oldCondition; - } - - /** - * 构建 1=1的 where 条件 - * @return - */ - public SqlBasicCall buildEmptyCondition(){ - SqlBinaryOperator equalsOperators = SqlStdOperatorTable.EQUALS; - SqlNode[] operands = new SqlNode[2]; - operands[0] = SqlLiteral.createExactNumeric("1", SqlParserPos.ZERO); - operands[1] = SqlLiteral.createExactNumeric("1", SqlParserPos.ZERO); - - return new SqlBasicCall(equalsOperators, operands, SqlParserPos.ZERO); - } - - /** - * 替换join 条件中的表名称 - * @param node - * @param tableMap 表名的关联关系 - */ - private SqlIdentifier checkAndReplaceJoinCondition(SqlNode node, Map tableMap){ - - SqlKind joinKind = node.getKind(); - if(AGGREGATE.contains(joinKind) - || AVG_AGG_FUNCTIONS.contains(joinKind) - || COMPARISON.contains(joinKind) - || FUNCTION.contains(joinKind) - || COVAR_AVG_AGG_FUNCTIONS.contains(joinKind) - || BINARY_ARITHMETIC.contains(joinKind) - || BINARY_COMPARISON.contains(joinKind) - || joinKind == NOT_IN - || joinKind == OR - || joinKind == AND - || joinKind == TUMBLE - || joinKind == TUMBLE_START - || joinKind == TUMBLE_END - || joinKind == SESSION - || joinKind == SESSION_START - || joinKind == SESSION_END - || joinKind == HOP - || joinKind == HOP_START - || joinKind == HOP_END - || joinKind == BETWEEN - || joinKind == IS_NULL - || joinKind == IS_NOT_NULL - || joinKind == CONTAINS - || joinKind == TIMESTAMP_ADD - || joinKind == TIMESTAMP_DIFF - || joinKind == LIKE - || joinKind == COALESCE ){ - SqlBasicCall sqlBasicCall = (SqlBasicCall) node; - for(int i=0; i buildTmpTableFieldRefOriField(Set fieldSet, String newTableAliasName){ - Map refInfo = Maps.newConcurrentMap(); - for(String field : fieldSet){ - String[] fields; - if (StringUtils.contains(field, " AS ")) { - fields = StringUtils.splitByWholeSeparator(field, " AS "); - } else { - fields = StringUtils.splitByWholeSeparator(field, " as "); - } - fields = Stream - .of(fields) - .map(StringUtils::trimToNull) - .toArray(String[]::new); - String oldKey = field; - String[] oldFieldInfo = StringUtils.splitByWholeSeparator(fields[0], "."); - String oldFieldName = oldFieldInfo.length == 2 ? oldFieldInfo[1] : oldFieldInfo[0]; - String newKey = fields.length == 2 ? newTableAliasName + "." + fields[1] : - newTableAliasName + "." + oldFieldName; - refInfo.put(oldKey, newKey); - } - - return refInfo; - } - - -} diff --git a/core/src/main/java/com/dtstack/flink/sql/side/JoinScope.java b/core/src/main/java/com/dtstack/flink/sql/side/JoinScope.java index 7435ff8cd..c7a73e0d7 100644 --- a/core/src/main/java/com/dtstack/flink/sql/side/JoinScope.java +++ b/core/src/main/java/com/dtstack/flink/sql/side/JoinScope.java @@ -16,6 +16,7 @@ * limitations under the License. */ + package com.dtstack.flink.sql.side; @@ -28,15 +29,10 @@ import java.util.List; import java.util.Map; -import org.apache.flink.table.runtime.typeutils.BaseRowTypeInfo; -import org.apache.flink.table.types.logical.LogicalType; - - /** * Reason: * Date: 2018/7/20 * Company: www.dtstack.com - * * @author xuchao */ @@ -46,12 +42,12 @@ public class JoinScope { private Map aliasMap = Maps.newHashMap(); - public void addScope(ScopeChild scopeChild) { + public void addScope(ScopeChild scopeChild){ children.add(scopeChild); aliasMap.put(scopeChild.getAlias(), scopeChild); } - public ScopeChild getScope(String tableAlias) { + public ScopeChild getScope(String tableAlias){ return aliasMap.get(tableAlias); } @@ -59,37 +55,22 @@ public List getChildren() { return children; } - public TypeInformation getFieldType(String tableName, String fieldName) { + public TypeInformation getFieldType(String tableName, String fieldName){ ScopeChild scopeChild = aliasMap.get(tableName); - if (scopeChild == null) { + if(scopeChild == null){ throw new RuntimeException("can't find "); } RowTypeInfo rowTypeInfo = scopeChild.getRowTypeInfo(); int index = rowTypeInfo.getFieldIndex(fieldName); - if (index == -1) { + if(index == -1){ throw new RuntimeException("can't find field: " + fieldName); } return rowTypeInfo.getTypeAt(index); } - public LogicalType getLogicalType(String tableName, String fieldName) { - ScopeChild scopeChild = aliasMap.get(tableName); - if (scopeChild == null) { - throw new RuntimeException("can't find "); - } - - BaseRowTypeInfo rowTypeInfo = scopeChild.getBaseRowTypeInfo(); - int index = rowTypeInfo.getFieldIndex(fieldName); - if (index == -1) { - throw new RuntimeException("can't find field: " + fieldName); - } - - return rowTypeInfo.getLogicalTypes()[index]; - } - - public static class ScopeChild { + public static class ScopeChild{ private String alias; @@ -97,8 +78,6 @@ public static class ScopeChild { private RowTypeInfo rowTypeInfo; - private BaseRowTypeInfo baseRowTypeInfo; - public String getAlias() { return alias; } @@ -122,13 +101,5 @@ public RowTypeInfo getRowTypeInfo() { public void setRowTypeInfo(RowTypeInfo rowTypeInfo) { this.rowTypeInfo = rowTypeInfo; } - - public BaseRowTypeInfo getBaseRowTypeInfo() { - return baseRowTypeInfo; - } - - public void setBaseRowTypeInfo(BaseRowTypeInfo baseRowTypeInfo) { - this.baseRowTypeInfo = baseRowTypeInfo; - } } } diff --git a/core/src/main/java/com/dtstack/flink/sql/side/ParserJoinField.java b/core/src/main/java/com/dtstack/flink/sql/side/ParserJoinField.java index a1ec24c53..74d303c24 100644 --- a/core/src/main/java/com/dtstack/flink/sql/side/ParserJoinField.java +++ b/core/src/main/java/com/dtstack/flink/sql/side/ParserJoinField.java @@ -28,8 +28,6 @@ import org.apache.flink.api.common.typeinfo.TypeInformation; import org.apache.flink.api.java.typeutils.RowTypeInfo; import com.google.common.collect.Lists; -import org.apache.flink.table.runtime.typeutils.BaseRowTypeInfo; -import org.apache.flink.table.types.logical.LogicalType; import java.util.Iterator; import java.util.List; @@ -53,38 +51,37 @@ public class ParserJoinField { */ public static List getRowTypeInfo(SqlNode sqlNode, JoinScope scope, boolean getAll){ + if(sqlNode.getKind() != SqlKind.SELECT){ + throw new RuntimeException("------not select node--------\n" + sqlNode.toString()); + } + List fieldInfoList = Lists.newArrayList(); if(getAll){ return getAllField(scope); } - if(sqlNode.getKind() != SqlKind.SELECT){ - throw new RuntimeException("------not select node--------\n" + sqlNode.toString()); - } - SqlSelect sqlSelect = (SqlSelect)sqlNode; SqlNodeList sqlNodeList = sqlSelect.getSelectList(); for(SqlNode fieldNode : sqlNodeList.getList()){ SqlIdentifier identifier = (SqlIdentifier)fieldNode; if(!identifier.isStar()) { + System.out.println(identifier); String tableName = identifier.getComponent(0).getSimple(); String fieldName = identifier.getComponent(1).getSimple(); TypeInformation type = scope.getFieldType(tableName, fieldName); - LogicalType logicalType = scope.getLogicalType(tableName, fieldName); FieldInfo fieldInfo = new FieldInfo(); fieldInfo.setTable(tableName); fieldInfo.setFieldName(fieldName); fieldInfo.setTypeInformation(type); - fieldInfo.setLogicalType(logicalType); fieldInfoList.add(fieldInfo); } else { //处理 + System.out.println("----------"); int identifierSize = identifier.names.size(); switch(identifierSize) { case 1: fieldInfoList.addAll(getAllField(scope)); - break; default: SqlIdentifier tableIdentify = identifier.skipLast(1); JoinScope.ScopeChild scopeChild = scope.getScope(tableIdentify.getSimple()); @@ -93,22 +90,17 @@ public static List getRowTypeInfo(SqlNode sqlNode, JoinScope scope, b } RowTypeInfo field = scopeChild.getRowTypeInfo(); - BaseRowTypeInfo baseRowTypeInfo = scopeChild.getBaseRowTypeInfo(); String[] fieldNames = field.getFieldNames(); TypeInformation[] types = field.getFieldTypes(); - LogicalType[] logicalTypes = baseRowTypeInfo.getLogicalTypes(); for(int i=0; i< field.getTotalFields(); i++){ String fieldName = fieldNames[i]; TypeInformation type = types[i]; - LogicalType logicalType = logicalTypes[i]; FieldInfo fieldInfo = new FieldInfo(); fieldInfo.setTable(tableIdentify.getSimple()); fieldInfo.setFieldName(fieldName); fieldInfo.setTypeInformation(type); - fieldInfo.setLogicalType(logicalType); fieldInfoList.add(fieldInfo); } - break; } } } @@ -116,43 +108,27 @@ public static List getRowTypeInfo(SqlNode sqlNode, JoinScope scope, b return fieldInfoList; } - //TODO 丢弃多余的PROCTIME private static List getAllField(JoinScope scope){ Iterator prefixId = scope.getChildren().iterator(); List fieldInfoList = Lists.newArrayList(); while(true) { JoinScope.ScopeChild resolved; - BaseRowTypeInfo field; - BaseRowTypeInfo baseRowTypeInfo; + RowTypeInfo field; if(!prefixId.hasNext()) { return fieldInfoList; } resolved = (JoinScope.ScopeChild)prefixId.next(); - int fieldTypeLength = resolved.getBaseRowTypeInfo().getFieldTypes().length; - if(fieldTypeLength == 2 - && resolved.getRowTypeInfo().getFieldTypes()[1].getClass().equals(BaseRowTypeInfo.class)){ - field = (BaseRowTypeInfo) resolved.getBaseRowTypeInfo().getFieldTypes()[1]; - } else if(fieldTypeLength ==1 - && resolved.getRowTypeInfo().getFieldTypes()[0].getClass().equals(BaseRowTypeInfo.class)){ - field = (BaseRowTypeInfo) resolved.getBaseRowTypeInfo().getFieldTypes()[0]; - }else{ - field = resolved.getBaseRowTypeInfo(); - } - - baseRowTypeInfo = field; + field = resolved.getRowTypeInfo(); String[] fieldNames = field.getFieldNames(); TypeInformation[] types = field.getFieldTypes(); - LogicalType[] logicalTypes = baseRowTypeInfo.getLogicalTypes(); for(int i=0; i< field.getTotalFields(); i++){ String fieldName = fieldNames[i]; TypeInformation type = types[i]; - LogicalType logicalType = logicalTypes[i]; FieldInfo fieldInfo = new FieldInfo(); fieldInfo.setTable(resolved.getAlias()); fieldInfo.setFieldName(fieldName); fieldInfo.setTypeInformation(type); - fieldInfo.setLogicalType(logicalType); fieldInfoList.add(fieldInfo); } } diff --git a/core/src/main/java/com/dtstack/flink/sql/side/PredicateInfo.java b/core/src/main/java/com/dtstack/flink/sql/side/PredicateInfo.java deleted file mode 100644 index 62be2440e..000000000 --- a/core/src/main/java/com/dtstack/flink/sql/side/PredicateInfo.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side; - -import java.io.Serializable; - -/** - * Predicate base info - * - * Date: 2019/12/11 - * Company: www.dtstack.com - * @author maqi - */ -public class PredicateInfo implements Serializable { - - private String operatorName; - private String operatorKind; - private String ownerTable; - private String fieldName; - private String condition; - - public PredicateInfo(String operatorName, String operatorKind, String ownerTable, String fieldName, String condition) { - this.operatorName = operatorName; - this.operatorKind = operatorKind; - this.ownerTable = ownerTable; - this.fieldName = fieldName; - this.condition = condition; - } - - public String getOperatorName() { - return operatorName; - } - - public void setOperatorName(String operatorName) { - this.operatorName = operatorName; - } - - public String getOperatorKind() { - return operatorKind; - } - - public void setOperatorKind(String operatorKind) { - this.operatorKind = operatorKind; - } - - public String getOwnerTable() { - return ownerTable; - } - - public void setOwnerTable(String ownerTable) { - this.ownerTable = ownerTable; - } - - public String getFieldName() { - return fieldName; - } - - public void setFieldName(String fieldName) { - this.fieldName = fieldName; - } - - public String getCondition() { - return condition; - } - - public void setCondition(String condition) { - this.condition = condition; - } - - @Override - public String toString() { - return "PredicateInfo{" + - "operatorName='" + operatorName + '\'' + - ", operatorKind='" + operatorKind + '\'' + - ", ownerTable='" + ownerTable + '\'' + - ", fieldName='" + fieldName + '\'' + - ", condition='" + condition + '\'' + - '}'; - } - - public static Builder builder() { - return new Builder(); - } - - - public static class Builder { - - private String operatorName; - private String operatorKind; - private String ownerTable; - private String fieldName; - private String condition; - - public Builder setOperatorName(String operatorName) { - this.operatorName = operatorName; - return this; - } - - public Builder setOperatorKind(String operatorKind) { - this.operatorKind = operatorKind; - return this; - } - - public Builder setOwnerTable(String ownerTable) { - this.ownerTable = ownerTable; - return this; - } - - public Builder setFieldName(String fieldName) { - this.fieldName = fieldName; - return this; - } - - public Builder setCondition(String condition) { - this.condition = condition; - return this; - } - - public PredicateInfo build() { - return new PredicateInfo( - operatorName, operatorKind, ownerTable, fieldName, condition); - } - } - - -} diff --git a/core/src/main/java/com/dtstack/flink/sql/side/SideInfo.java b/core/src/main/java/com/dtstack/flink/sql/side/SideInfo.java new file mode 100644 index 000000000..df41e1663 --- /dev/null +++ b/core/src/main/java/com/dtstack/flink/sql/side/SideInfo.java @@ -0,0 +1,258 @@ +/* + * 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 com.dtstack.flink.sql.side; + +import com.dtstack.flink.sql.side.cache.AbsSideCache; +import org.apache.calcite.sql.JoinType; +import org.apache.calcite.sql.SqlBasicCall; +import org.apache.calcite.sql.SqlIdentifier; +import org.apache.calcite.sql.SqlKind; +import org.apache.calcite.sql.SqlNode; +import org.apache.flink.api.java.typeutils.RowTypeInfo; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; + +/** + * Reason: + * Date: 2018/9/18 + * Company: www.dtstack.com + * @author xuchao + */ + +public abstract class SideInfo implements Serializable{ + + protected RowTypeInfo rowTypeInfo; + + protected List outFieldInfoList; + + protected List equalFieldList = Lists.newArrayList(); + + protected List equalValIndex = Lists.newArrayList(); + + protected String sqlCondition = ""; + + protected String sideSelectFields = ""; + + protected JoinType joinType; + + //key:Returns the value of the position, value: the ref field index​in the input table + protected Map inFieldIndex = Maps.newHashMap(); + + //key:Returns the value of the position, value: the ref field index​in the side table + protected Map sideFieldIndex = Maps.newHashMap(); + + //key:Returns the value of the position, value: the ref field name​in the side table + protected Map sideFieldNameIndex = Maps.newHashMap(); + + protected SideTableInfo sideTableInfo; + + protected AbsSideCache sideCache; + + public SideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, + SideTableInfo sideTableInfo){ + this.rowTypeInfo = rowTypeInfo; + this.outFieldInfoList = outFieldInfoList; + this.joinType = joinInfo.getJoinType(); + this.sideTableInfo = sideTableInfo; + parseSelectFields(joinInfo); + buildEqualInfo(joinInfo, sideTableInfo); + } + + public void parseSelectFields(JoinInfo joinInfo){ + String sideTableName = joinInfo.getSideTableName(); + String nonSideTableName = joinInfo.getNonSideTable(); + List fields = Lists.newArrayList(); + + int sideIndex = 0; + for( int i=0; i getOutFieldInfoList() { + return outFieldInfoList; + } + + public void setOutFieldInfoList(List outFieldInfoList) { + this.outFieldInfoList = outFieldInfoList; + } + + public List getEqualFieldList() { + return equalFieldList; + } + + public void setEqualFieldList(List equalFieldList) { + this.equalFieldList = equalFieldList; + } + + public List getEqualValIndex() { + return equalValIndex; + } + + public void setEqualValIndex(List equalValIndex) { + this.equalValIndex = equalValIndex; + } + + public String getSqlCondition() { + return sqlCondition; + } + + public void setSqlCondition(String sqlCondition) { + this.sqlCondition = sqlCondition; + } + + public String getSideSelectFields() { + return sideSelectFields; + } + + public void setSideSelectFields(String sideSelectFields) { + this.sideSelectFields = sideSelectFields; + } + + public JoinType getJoinType() { + return joinType; + } + + public void setJoinType(JoinType joinType) { + this.joinType = joinType; + } + + public Map getInFieldIndex() { + return inFieldIndex; + } + + public void setInFieldIndex(Map inFieldIndex) { + this.inFieldIndex = inFieldIndex; + } + + public Map getSideFieldIndex() { + return sideFieldIndex; + } + + public void setSideFieldIndex(Map sideFieldIndex) { + this.sideFieldIndex = sideFieldIndex; + } + + public SideTableInfo getSideTableInfo() { + return sideTableInfo; + } + + public void setSideTableInfo(SideTableInfo sideTableInfo) { + this.sideTableInfo = sideTableInfo; + } + + public AbsSideCache getSideCache() { + return sideCache; + } + + public void setSideCache(AbsSideCache sideCache) { + this.sideCache = sideCache; + } + + public Map getSideFieldNameIndex() { + return sideFieldNameIndex; + } + + public void setSideFieldNameIndex(Map sideFieldNameIndex) { + this.sideFieldNameIndex = sideFieldNameIndex; + } +} diff --git a/core/src/main/java/com/dtstack/flink/sql/side/SidePredicatesParser.java b/core/src/main/java/com/dtstack/flink/sql/side/SidePredicatesParser.java deleted file mode 100644 index 4f66f8981..000000000 --- a/core/src/main/java/com/dtstack/flink/sql/side/SidePredicatesParser.java +++ /dev/null @@ -1,200 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side; - -import com.dtstack.flink.sql.parser.FlinkPlanner; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import org.apache.calcite.sql.SqlBasicCall; -import org.apache.calcite.sql.SqlCharStringLiteral; -import org.apache.calcite.sql.SqlIdentifier; -import org.apache.calcite.sql.SqlInsert; -import org.apache.calcite.sql.SqlJoin; -import org.apache.calcite.sql.SqlKind; -import org.apache.calcite.sql.SqlNode; -import org.apache.calcite.sql.SqlOperator; -import org.apache.calcite.sql.SqlSelect; -import org.apache.calcite.sql.parser.SqlParseException; -import org.apache.commons.lang3.StringUtils; - -import java.util.List; -import java.util.Map; - -import static org.apache.calcite.sql.SqlKind.IDENTIFIER; -import static org.apache.calcite.sql.SqlKind.LITERAL; -import static org.apache.calcite.sql.SqlKind.OR; - -/** - * - * 将同级谓词信息填充到维表 - * Date: 2019/12/11 - * Company: www.dtstack.com - * @author maqi - */ -public class SidePredicatesParser { - - private FlinkPlanner flinkPlanner = new FlinkPlanner(); - private static final String QUOTE = "'"; - - public void fillPredicatesForSideTable(String exeSql, Map sideTableMap) throws SqlParseException { - SqlNode sqlNode = flinkPlanner.getParser().parse(exeSql); - parseSql(sqlNode, sideTableMap, Maps.newHashMap()); - } - - /** - * 将谓词信息填充到维表属性 - * @param sqlNode - * @param sideTableMap - * @param tabMapping 谓词属性中别名对应的真实维表名称 - */ - private void parseSql(SqlNode sqlNode, Map sideTableMap, Map tabMapping) { - SqlKind sqlKind = sqlNode.getKind(); - switch (sqlKind) { - case INSERT: - SqlNode sqlSource = ((SqlInsert) sqlNode).getSource(); - parseSql(sqlSource, sideTableMap, tabMapping); - break; - case SELECT: - SqlNode fromNode = ((SqlSelect) sqlNode).getFrom(); - SqlNode whereNode = ((SqlSelect) sqlNode).getWhere(); - - if (fromNode.getKind() != IDENTIFIER) { - parseSql(fromNode, sideTableMap, tabMapping); - } - // 带or的不解析 - if (null != whereNode && whereNode.getKind() != OR) { - List predicateInfoList = Lists.newArrayList(); - extractPredicateInfo(whereNode, predicateInfoList); - fillToSideTableInfo(sideTableMap, tabMapping, predicateInfoList); - } - break; - case JOIN: - SqlNode leftNode = ((SqlJoin) sqlNode).getLeft(); - SqlNode rightNode = ((SqlJoin) sqlNode).getRight(); - parseSql(leftNode, sideTableMap, tabMapping); - parseSql(rightNode, sideTableMap, tabMapping); - break; - case AS: - SqlNode info = ((SqlBasicCall) sqlNode).getOperands()[0]; - SqlNode alias = ((SqlBasicCall) sqlNode).getOperands()[1]; - if (info.getKind() == IDENTIFIER) { - tabMapping.put(alias.toString(), info.toString()); - } else { - // 为子查询创建一个同级map - parseSql(info, sideTableMap, Maps.newHashMap()); - } - break; - case UNION: - SqlNode unionLeft = ((SqlBasicCall) sqlNode).getOperands()[0]; - SqlNode unionRight = ((SqlBasicCall) sqlNode).getOperands()[1]; - parseSql(unionLeft, sideTableMap, tabMapping); - parseSql(unionRight, sideTableMap, tabMapping); - break; - default: - break; - } - } - - private void fillToSideTableInfo(Map sideTableMap, Map tabMapping, List predicateInfoList) { - predicateInfoList.stream().filter(info -> sideTableMap.containsKey(tabMapping.getOrDefault(info.getOwnerTable(), info.getOwnerTable()))) - .map(info -> sideTableMap.get(tabMapping.getOrDefault(info.getOwnerTable(), info.getOwnerTable())).getFullPredicateInfoes().add(info)) - .count(); - } - - - private void extractPredicateInfo(SqlNode whereNode, List predicatesInfoList) { - SqlKind sqlKind = whereNode.getKind(); - if (sqlKind == SqlKind.AND && ((SqlBasicCall) whereNode).getOperandList().size() == 2) { - extractPredicateInfo(((SqlBasicCall) whereNode).getOperands()[0], predicatesInfoList); - extractPredicateInfo(((SqlBasicCall) whereNode).getOperands()[1], predicatesInfoList); - } else { - SqlOperator operator = ((SqlBasicCall) whereNode).getOperator(); - String operatorName = operator.getName(); - SqlKind operatorKind = operator.getKind(); - - if (operatorKind == SqlKind.IS_NOT_NULL || operatorKind == SqlKind.IS_NULL) { - fillPredicateInfoToList((SqlBasicCall) whereNode, predicatesInfoList, operatorName, operatorKind, 0, 0); - return; - } - - // 跳过函数 - if ((((SqlBasicCall) whereNode).getOperands()[0] instanceof SqlIdentifier) - && (((SqlBasicCall) whereNode).getOperands()[1].getKind() == SqlKind.LITERAL)) { - fillPredicateInfoToList((SqlBasicCall) whereNode, predicatesInfoList, operatorName, operatorKind, 0, 1); - } else if ((((SqlBasicCall) whereNode).getOperands()[1] instanceof SqlIdentifier) - && (((SqlBasicCall) whereNode).getOperands()[0].getKind() == LITERAL)) { - fillPredicateInfoToList((SqlBasicCall) whereNode, predicatesInfoList, operatorName, operatorKind, 1, 0); - } - } - } - - private void fillPredicateInfoToList( - SqlBasicCall whereNode, - List predicatesInfoList, - String operatorName, - SqlKind operatorKind, - int fieldIndex, - int conditionIndex) { - SqlNode sqlNode = whereNode.getOperands()[fieldIndex]; - if (sqlNode.getKind() == SqlKind.IDENTIFIER) { - SqlIdentifier fieldFullPath = (SqlIdentifier) sqlNode; - if (fieldFullPath.names.size() == 2) { - String ownerTable = fieldFullPath.names.get(0); - String fieldName = fieldFullPath.names.get(1); - - String condition; - SqlNode[] conditionNodes = whereNode.getOperands(); - SqlNode literal = conditionNodes[conditionIndex]; - if (operatorKind == SqlKind.BETWEEN) { - condition = literal.toString() + " AND " + conditionNodes[2].toString(); - } else { - if (literal instanceof SqlCharStringLiteral) { - condition = removeCoding((SqlCharStringLiteral) literal); - } else { - condition = literal.toString(); - } - } - - if (StringUtils.containsIgnoreCase(condition, SqlKind.CASE.toString())) { - return; - } - - PredicateInfo predicateInfo = - PredicateInfo.builder() - .setOperatorName(operatorName) - .setOperatorKind(operatorKind.toString()) - .setOwnerTable(ownerTable) - .setFieldName(fieldName) - .setCondition(condition) - .build(); - predicatesInfoList.add(predicateInfo); - } - } - } - - /** - * 去掉_UTF16前缀,只获取字符本身。要不然中文编码会有问题。例如 _UTF16'甲' 去掉后返回结果为 '甲'。 - * - * @param stringLiteral - * @return - */ - private String removeCoding(SqlCharStringLiteral stringLiteral) { - return QUOTE + stringLiteral.getNlsString().getValue() + QUOTE; - } -} diff --git a/core/src/main/java/com/dtstack/flink/sql/side/SideSQLParser.java b/core/src/main/java/com/dtstack/flink/sql/side/SideSQLParser.java index c5ef5263d..c881d6344 100644 --- a/core/src/main/java/com/dtstack/flink/sql/side/SideSQLParser.java +++ b/core/src/main/java/com/dtstack/flink/sql/side/SideSQLParser.java @@ -20,12 +20,10 @@ package com.dtstack.flink.sql.side; -import com.dtstack.flink.sql.exception.sqlparse.WithoutTableNameException; -import com.dtstack.flink.sql.parser.FlinkPlanner; -import com.dtstack.flink.sql.util.TableUtils; -import com.google.common.collect.Maps; -import com.google.common.collect.Queues; -import com.google.common.collect.Sets; +import com.dtstack.flink.sql.config.CalciteConfig; +import com.dtstack.flink.sql.util.ParseUtils; +import org.apache.calcite.sql.JoinType; +import org.apache.calcite.sql.SqlAsOperator; import org.apache.calcite.sql.SqlBasicCall; import org.apache.calcite.sql.SqlIdentifier; import org.apache.calcite.sql.SqlInsert; @@ -33,22 +31,29 @@ import org.apache.calcite.sql.SqlKind; import org.apache.calcite.sql.SqlNode; import org.apache.calcite.sql.SqlNodeList; +import org.apache.calcite.sql.SqlOperator; import org.apache.calcite.sql.SqlOrderBy; import org.apache.calcite.sql.SqlSelect; import org.apache.calcite.sql.SqlWith; import org.apache.calcite.sql.SqlWithItem; import org.apache.calcite.sql.parser.SqlParseException; +import org.apache.calcite.sql.parser.SqlParser; +import org.apache.calcite.sql.parser.SqlParserPos; +import org.apache.commons.collections.CollectionUtils; import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.table.api.Table; +import com.google.common.base.Strings; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Queues; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.List; import java.util.Map; import java.util.Queue; import java.util.Set; -import static org.apache.calcite.sql.SqlKind.IDENTIFIER; -import static org.apache.calcite.sql.SqlKind.LITERAL; +import static org.apache.calcite.sql.SqlKind.*; /** * Parsing sql, obtain execution information dimension table @@ -60,45 +65,25 @@ public class SideSQLParser { private static final Logger LOG = LoggerFactory.getLogger(SideSQLParser.class); - private Map localTableCache = Maps.newHashMap(); - - private FlinkPlanner flinkPlanner = new FlinkPlanner(); + private final char SPLIT = '_'; - public Queue getExeQueue(String exeSql, Set sideTableSet, String scope) throws SqlParseException { + private String tempSQL = "SELECT * FROM TMP"; - LOG.info("----------exec original Sql----------"); + public Queue getExeQueue(String exeSql, Set sideTableSet) throws SqlParseException { + System.out.println("---exeSql---"); + System.out.println(exeSql); + LOG.info("---exeSql---"); LOG.info(exeSql); Queue queueInfo = Queues.newLinkedBlockingQueue(); - SqlNode sqlNode = flinkPlanner.getParser().parse(exeSql); - - try { - parseSql(sqlNode, sideTableSet, queueInfo, null, null, null, scope, Sets.newHashSet()); - }catch (WithoutTableNameException e){ - throw new WithoutTableNameException(e.getMessage()+ "\n==sql==\n"+ exeSql); - } + SqlParser sqlParser = SqlParser.create(exeSql, CalciteConfig.MYSQL_LEX_CONFIG); + SqlNode sqlNode = sqlParser.parseStmt(); + parseSql(sqlNode, sideTableSet, queueInfo); queueInfo.offer(sqlNode); return queueInfo; } - - /** - * 解析 sql 根据维表 join关系重新组装新的sql - * @param sqlNode - * @param sideTableSet - * @param queueInfo - * @param parentWhere - * @param parentSelectList - * @return - */ - public Object parseSql(SqlNode sqlNode, - Set sideTableSet, - Queue queueInfo, - SqlNode parentWhere, - SqlNodeList parentSelectList, - SqlNodeList parentGroupByList, - String scope, - Set joinTableNames){ + private Object parseSql(SqlNode sqlNode, Set sideTableSet, Queue queueInfo){ SqlKind sqlKind = sqlNode.getKind(); switch (sqlKind){ case WITH: { @@ -106,25 +91,21 @@ public Object parseSql(SqlNode sqlNode, SqlNodeList sqlNodeList = sqlWith.withList; for (SqlNode withAsTable : sqlNodeList) { SqlWithItem sqlWithItem = (SqlWithItem) withAsTable; - parseSql(sqlWithItem.query, sideTableSet, queueInfo, parentWhere, parentSelectList, parentGroupByList, scope, joinTableNames); + parseSql(sqlWithItem.query, sideTableSet, queueInfo); queueInfo.add(sqlWithItem); } - parseSql(sqlWith.body, sideTableSet, queueInfo, parentWhere, parentSelectList, parentGroupByList, scope, joinTableNames); + parseSql(sqlWith.body, sideTableSet, queueInfo); break; } case INSERT: SqlNode sqlSource = ((SqlInsert)sqlNode).getSource(); - return parseSql(sqlSource, sideTableSet, queueInfo, parentWhere, parentSelectList, parentGroupByList, scope, joinTableNames); + return parseSql(sqlSource, sideTableSet, queueInfo); case SELECT: SqlNode sqlFrom = ((SqlSelect)sqlNode).getFrom(); - SqlNode sqlWhere = ((SqlSelect)sqlNode).getWhere(); - SqlNodeList selectList = ((SqlSelect)sqlNode).getSelectList(); - SqlNodeList groupByList = ((SqlSelect) sqlNode).getGroup(); - if(sqlFrom.getKind() != IDENTIFIER){ - Object result = parseSql(sqlFrom, sideTableSet, queueInfo, sqlWhere, selectList, groupByList, scope, joinTableNames); + Object result = parseSql(sqlFrom, sideTableSet, queueInfo); if(result instanceof JoinInfo){ - return TableUtils.dealSelectResultWithJoinInfo((JoinInfo) result, (SqlSelect) sqlNode, queueInfo); + dealSelectResultWithJoinInfo((JoinInfo)result, (SqlSelect) sqlNode, queueInfo); }else if(result instanceof AliasInfo){ String tableName = ((AliasInfo) result).getName(); if(sideTableSet.contains(tableName)){ @@ -139,21 +120,16 @@ public Object parseSql(SqlNode sqlNode, } break; case JOIN: - JoinNodeDealer joinNodeDealer = new JoinNodeDealer(this); - Set> joinFieldSet = Sets.newHashSet(); - Map tableRef = Maps.newHashMap(); - Map fieldRef = Maps.newHashMap(); - return joinNodeDealer.dealJoinNode((SqlJoin) sqlNode, sideTableSet, queueInfo, - parentWhere, parentSelectList, parentGroupByList, joinFieldSet, tableRef, fieldRef, scope, joinTableNames); + return dealJoinNode((SqlJoin) sqlNode, sideTableSet, queueInfo); case AS: SqlNode info = ((SqlBasicCall)sqlNode).getOperands()[0]; SqlNode alias = ((SqlBasicCall) sqlNode).getOperands()[1]; - String infoStr = ""; + String infoStr; if(info.getKind() == IDENTIFIER){ infoStr = info.toString(); - } else { - infoStr = parseSql(info, sideTableSet, queueInfo, parentWhere, parentSelectList, parentGroupByList, scope, joinTableNames).toString(); + }else{ + infoStr = parseSql(info, sideTableSet, queueInfo).toString(); } AliasInfo aliasInfo = new AliasInfo(); @@ -166,26 +142,275 @@ public Object parseSql(SqlNode sqlNode, SqlNode unionLeft = ((SqlBasicCall)sqlNode).getOperands()[0]; SqlNode unionRight = ((SqlBasicCall)sqlNode).getOperands()[1]; - parseSql(unionLeft, sideTableSet, queueInfo, parentWhere, parentSelectList, parentGroupByList, scope, joinTableNames); - parseSql(unionRight, sideTableSet, queueInfo, parentWhere, parentSelectList, parentGroupByList, scope, joinTableNames); + parseSql(unionLeft, sideTableSet, queueInfo); + + parseSql(unionRight, sideTableSet, queueInfo); + break; + case ORDER_BY: SqlOrderBy sqlOrderBy = (SqlOrderBy) sqlNode; - parseSql(sqlOrderBy.query, sideTableSet, queueInfo, parentWhere, parentSelectList, parentGroupByList, scope, joinTableNames); - - case LITERAL: - return LITERAL.toString(); - default: - break; + parseSql(sqlOrderBy.query, sideTableSet, queueInfo); } + return ""; } + private JoinInfo dealJoinNode(SqlJoin joinNode, Set sideTableSet, Queue queueInfo) { + SqlNode leftNode = joinNode.getLeft(); + SqlNode rightNode = joinNode.getRight(); + JoinType joinType = joinNode.getJoinType(); + String leftTbName = ""; + String leftTbAlias = ""; + String rightTableName = ""; + String rightTableAlias = ""; + Map midTableMapping = null ; + boolean leftIsMidTable = false; + // 右节点已经被解析 + boolean rightIsParse = false; + Tuple2 rightTableNameAndAlias = null; + + + if(leftNode.getKind() == IDENTIFIER){ + leftTbName = leftNode.toString(); + }else if(leftNode.getKind() == JOIN){ + JoinInfo leftNodeJoinInfo = (JoinInfo)parseSql(leftNode, sideTableSet, queueInfo);//解析多JOIN + + rightTableNameAndAlias = parseRightNode(rightNode, sideTableSet, queueInfo); + rightIsParse = true; + if (checkIsSideTable(rightTableNameAndAlias.f0, sideTableSet)) { + // select * from xxx + SqlNode sqlNode = buildSelectByLeftNode(leftNode); + // ( select * from xxx) as xxx_0 + SqlBasicCall newAsNode = buildAsNodeByJoinInfo(leftNodeJoinInfo, sqlNode); + leftNode = newAsNode; + joinNode.setLeft(leftNode); + + leftIsMidTable = true; + midTableMapping = saveTabMapping(leftNodeJoinInfo); + + AliasInfo aliasInfo = (AliasInfo) parseSql(newAsNode, sideTableSet, queueInfo); + leftTbName = aliasInfo.getName(); + leftTbAlias = aliasInfo.getAlias(); + } else { + leftTbName = leftNodeJoinInfo.getRightTableName(); + leftTbAlias = leftNodeJoinInfo.getRightTableAlias(); + } + + }else if(leftNode.getKind() == AS){ + AliasInfo aliasInfo = (AliasInfo) parseSql(leftNode, sideTableSet, queueInfo); + leftTbName = aliasInfo.getName(); + leftTbAlias = aliasInfo.getAlias(); + }else{ + throw new RuntimeException("---not deal---"); + } + + boolean leftIsSide = checkIsSideTable(leftTbName, sideTableSet); + if(leftIsSide){ + throw new RuntimeException("side-table must be at the right of join operator"); + } + + if (!rightIsParse) { + rightTableNameAndAlias = parseRightNode(rightNode, sideTableSet, queueInfo); + } + rightTableName = rightTableNameAndAlias.f0; + rightTableAlias = rightTableNameAndAlias.f1; + + boolean rightIsSide = checkIsSideTable(rightTableName, sideTableSet); + if(joinType == JoinType.RIGHT){ + throw new RuntimeException("side join not support join type of right[current support inner join and left join]"); + } + + if (leftIsMidTable) { + // 替换右边 on语句 中的字段别名 + SqlNode afterReplaceNameCondition = ParseUtils.replaceJoinConditionTabName(joinNode.getCondition(), midTableMapping); + joinNode.setOperand(5, afterReplaceNameCondition); + } + + JoinInfo tableInfo = new JoinInfo(); + tableInfo.setLeftTableName(leftTbName); + tableInfo.setRightTableName(rightTableName); + if (leftTbAlias.equals("")){ + tableInfo.setLeftTableAlias(leftTbName); + } else { + tableInfo.setLeftTableAlias(leftTbAlias); + } + if (leftTbAlias.equals("")){ + tableInfo.setRightTableAlias(rightTableName); + } else { + tableInfo.setRightTableAlias(rightTableAlias); + } + tableInfo.setLeftIsSideTable(leftIsSide); + tableInfo.setRightIsSideTable(rightIsSide); + tableInfo.setLeftNode(leftNode); + tableInfo.setRightNode(rightNode); + tableInfo.setJoinType(joinType); + tableInfo.setCondition(joinNode.getCondition()); + + tableInfo.setLeftIsMidTable(leftIsMidTable); + tableInfo.setLeftTabMapping(midTableMapping); + + return tableInfo; + } + + private Tuple2 parseRightNode(SqlNode sqlNode, Set sideTableSet, Queue queueInfo) { + Tuple2 tabName = new Tuple2<>("", ""); + if(sqlNode.getKind() == IDENTIFIER){ + tabName.f0 = sqlNode.toString(); + }else{ + AliasInfo aliasInfo = (AliasInfo)parseSql(sqlNode, sideTableSet, queueInfo); + tabName.f0 = aliasInfo.getName(); + tabName.f1 = aliasInfo.getAlias(); + } + return tabName; + } + + private Map saveTabMapping(JoinInfo leftNodeJoinInfo) { + Map midTableMapping = Maps.newHashMap();; + + String midTab = buidTableName(leftNodeJoinInfo.getLeftTableAlias(), SPLIT, leftNodeJoinInfo.getRightTableAlias()); + String finalMidTab = midTab + "_0"; + if(leftNodeJoinInfo.isLeftIsMidTable()) { + midTableMapping.putAll(leftNodeJoinInfo.getLeftTabMapping()); + } + fillLeftAllTable(leftNodeJoinInfo, midTableMapping, finalMidTab); + return midTableMapping; + } + private void fillLeftAllTable(JoinInfo leftNodeJoinInfo, Map midTableMapping, String finalMidTab) { + List tablesName = Lists.newArrayList(); + ParseUtils.parseLeftNodeTableName(leftNodeJoinInfo.getLeftNode(), tablesName); - public void setLocalTableCache(Map localTableCache) { - this.localTableCache = localTableCache; + tablesName.forEach(tab ->{ + midTableMapping.put(tab, finalMidTab); + }); + midTableMapping.put(leftNodeJoinInfo.getRightTableAlias(), finalMidTab); } + + private SqlNode buildSelectByLeftNode(SqlNode leftNode) { + SqlParser sqlParser = SqlParser.create(tempSQL, CalciteConfig.MYSQL_LEX_CONFIG); + SqlNode sqlNode = null; + try { + sqlNode = sqlParser.parseStmt(); + }catch (Exception e) { + LOG.error("tmp sql parse error..", e); + } + + ((SqlSelect) sqlNode).setFrom(leftNode); + return sqlNode; + } + + + private void dealSelectResultWithJoinInfo(JoinInfo joinInfo, SqlSelect sqlNode, Queue queueInfo){ + // 中间虚拟表进行表名称替换 + if (joinInfo.isLeftIsMidTable()){ + SqlNode whereNode = sqlNode.getWhere(); + SqlNodeList sqlGroup = sqlNode.getGroup(); + SqlNodeList sqlSelectList = sqlNode.getSelectList(); + List newSelectNodeList = Lists.newArrayList(); + + for( int i=0; i sideTableList){ + if(sideTableList.contains(tableName)){ + return true; + } + return false; + } } diff --git a/core/src/main/java/com/dtstack/flink/sql/side/SideSqlExec.java b/core/src/main/java/com/dtstack/flink/sql/side/SideSqlExec.java index 152b9defc..bfccd02f7 100644 --- a/core/src/main/java/com/dtstack/flink/sql/side/SideSqlExec.java +++ b/core/src/main/java/com/dtstack/flink/sql/side/SideSqlExec.java @@ -21,73 +21,51 @@ package com.dtstack.flink.sql.side; import com.dtstack.flink.sql.enums.ECacheType; -import com.dtstack.flink.sql.enums.EPluginLoadMode; import com.dtstack.flink.sql.exec.FlinkSQLExec; import com.dtstack.flink.sql.parser.CreateTmpTableParser; import com.dtstack.flink.sql.side.operator.SideAsyncOperator; import com.dtstack.flink.sql.side.operator.SideWithAllCacheOperator; import com.dtstack.flink.sql.util.ClassUtil; import com.dtstack.flink.sql.util.ParseUtils; -import com.dtstack.flink.sql.util.RowDataConvert; -import com.dtstack.flink.sql.util.TableUtils; -import com.google.common.base.Preconditions; -import com.google.common.collect.HashBasedTable; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; +import org.apache.calcite.sql.SqlAsOperator; import org.apache.calcite.sql.SqlBasicCall; +import org.apache.calcite.sql.SqlDataTypeSpec; import org.apache.calcite.sql.SqlIdentifier; +import org.apache.calcite.sql.SqlInsert; +import org.apache.calcite.sql.SqlJoin; import org.apache.calcite.sql.SqlKind; +import org.apache.calcite.sql.SqlLiteral; import org.apache.calcite.sql.SqlNode; +import org.apache.calcite.sql.SqlNodeList; +import org.apache.calcite.sql.SqlOperator; +import org.apache.calcite.sql.SqlOrderBy; import org.apache.calcite.sql.SqlSelect; import org.apache.calcite.sql.SqlWithItem; +import org.apache.calcite.sql.fun.SqlCase; import org.apache.calcite.sql.parser.SqlParseException; +import org.apache.calcite.sql.parser.SqlParserPos; import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.flink.api.common.typeinfo.BasicTypeInfo; -import org.apache.flink.api.common.typeinfo.LocalTimeTypeInfo; -import org.apache.flink.api.common.typeinfo.TypeHint; import org.apache.flink.api.common.typeinfo.TypeInformation; +import org.apache.flink.api.java.tuple.Tuple2; import org.apache.flink.api.java.typeutils.RowTypeInfo; +import com.google.common.collect.HashBasedTable; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; import org.apache.flink.streaming.api.datastream.DataStream; import org.apache.flink.table.api.Table; import org.apache.flink.table.api.java.StreamTableEnvironment; -import org.apache.flink.table.dataformat.BaseRow; -import org.apache.flink.table.planner.plan.QueryOperationConverter; -import org.apache.flink.table.runtime.typeutils.BaseRowTypeInfo; -import org.apache.flink.table.runtime.typeutils.BigDecimalTypeInfo; -import org.apache.flink.table.runtime.typeutils.LegacyLocalDateTimeTypeInfo; -import org.apache.flink.table.types.logical.DecimalType; -import org.apache.flink.table.types.logical.LegacyTypeInformationType; -import org.apache.flink.table.types.logical.LogicalType; -import org.apache.flink.table.types.logical.TimestampType; -import org.apache.flink.table.typeutils.TimeIndicatorTypeInfo; +import org.apache.flink.types.Row; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.sql.Timestamp; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Queue; -import java.util.Set; -import java.util.stream.Collectors; - -import static org.apache.calcite.sql.SqlKind.AS; -import static org.apache.calcite.sql.SqlKind.INSERT; -import static org.apache.calcite.sql.SqlKind.SELECT; -import static org.apache.calcite.sql.SqlKind.UNION; -import static org.apache.calcite.sql.SqlKind.WITH_ITEM; +import java.util.*; + +import static org.apache.calcite.sql.SqlKind.*; /** * Reason: * Date: 2018/7/24 * Company: www.dtstack.com - * * @author xuchao */ @@ -99,142 +77,137 @@ public class SideSqlExec { private String tmpFields = null; - private String pluginLoadMode = null; - - private SidePredicatesParser sidePredicatesParser = new SidePredicatesParser(); + private SideSQLParser sideSQLParser = new SideSQLParser(); private Map localTableCache = Maps.newHashMap(); - //维表重新注册之后的名字缓存 - private static Map dimTableNewTable = Maps.newHashMap(); + public void exec(String sql, Map sideTableMap, StreamTableEnvironment tableEnv, + Map tableCache) + throws Exception { - public void exec(String sql, - Map sideTableMap, - StreamTableEnvironment tableEnv, - Map tableCache, - CreateTmpTableParser.SqlParserResult createView, - String scope) throws Exception { - if (!pluginLoadMode.equalsIgnoreCase(EPluginLoadMode.LOCALTEST.name()) && localSqlPluginPath == null ) { + if(localSqlPluginPath == null){ throw new RuntimeException("need to set localSqlPluginPath"); } localTableCache.putAll(tableCache); - try { - sidePredicatesParser.fillPredicatesForSideTable(sql, sideTableMap); - } catch (Exception e) { - LOG.error("fill predicates for sideTable fail ", e); - } - - if (createView != null) { - LOG.warn("create view info\n"); - LOG.warn(createView.getExecSql()); - LOG.warn("-----------------"); - } - - SideSQLParser sideSQLParser = new SideSQLParser(); - sideSQLParser.setLocalTableCache(localTableCache); - Queue exeQueue = sideSQLParser.getExeQueue(sql, sideTableMap.keySet(), scope); + Queue exeQueue = sideSQLParser.getExeQueue(sql, sideTableMap.keySet()); Object pollObj = null; - // create view中是否包含维表 - boolean includeDimTable = false; - while ((pollObj = exeQueue.poll()) != null) { + //need clean + boolean preIsSideJoin = false; + List replaceInfoList = Lists.newArrayList(); - if (pollObj instanceof SqlNode) { - SqlNode pollSqlNode = (SqlNode) pollObj; + while((pollObj = exeQueue.poll()) != null){ + if(pollObj instanceof SqlNode){ + SqlNode pollSqlNode = (SqlNode) pollObj; - if (pollSqlNode.getKind() == INSERT) { - Collection newRegisterTableList = dimTableNewTable.keySet(); - FlinkSQLExec.sqlInsert(tableEnv, pollSqlNode, newRegisterTableList); - if (LOG.isInfoEnabled()) { - LOG.info("----------real exec sql-----------\n{}", pollSqlNode.toString()); + if(preIsSideJoin){ + preIsSideJoin = false; + List fieldNames = null; + for(FieldReplaceInfo replaceInfo : replaceInfoList){ + fieldNames = Lists.newArrayList(); + replaceFieldName(pollSqlNode, replaceInfo.getMappingTable(), replaceInfo.getTargetTableName(), replaceInfo.getTargetTableAlias()); + addAliasForFieldNode(pollSqlNode, fieldNames, replaceInfo.getMappingTable()); } + } - } else if (pollSqlNode.getKind() == AS) { - Collection newRegisterTableList = dimTableNewTable.keySet(); - dealAsSourceTable(tableEnv, pollSqlNode, tableCache, newRegisterTableList); - + if(pollSqlNode.getKind() == INSERT){ + System.out.println("----------real exec sql-----------" ); + System.out.println(pollSqlNode.toString()); + FlinkSQLExec.sqlUpdate(tableEnv, pollSqlNode.toString()); + if(LOG.isInfoEnabled()){ + LOG.info("exec sql: " + pollSqlNode.toString()); + } + }else if(pollSqlNode.getKind() == AS){ + AliasInfo aliasInfo = parseASNode(pollSqlNode); + Table table = tableEnv.sqlQuery(aliasInfo.getName()); + tableEnv.registerTable(aliasInfo.getAlias(), table); + localTableCache.put(aliasInfo.getAlias(), table); } else if (pollSqlNode.getKind() == WITH_ITEM) { SqlWithItem sqlWithItem = (SqlWithItem) pollSqlNode; - String tableAlias = sqlWithItem.name.toString(); - Collection newRegisterTableList = dimTableNewTable.keySet(); - Table table = FlinkSQLExec.sqlQuery(tableEnv, sqlWithItem.query, newRegisterTableList); - tableEnv.createTemporaryView(tableAlias, table); - - } else if (pollSqlNode.getKind() == SELECT || pollSqlNode.getKind() == UNION) { - Preconditions.checkState(createView != null, "select sql must included by create view"); - Collection newRegisterTableList = dimTableNewTable.keySet(); - Table table = FlinkSQLExec.sqlQuery(tableEnv, pollSqlNode, newRegisterTableList); - - if (createView.getFieldsInfoStr() == null) { - tableEnv.registerTable(createView.getTableName(), table); - } else { - if (checkFieldsInfo(createView, table)) { - table = table.as(tmpFields); - tableEnv.createTemporaryView(createView.getTableName(), table); - } else { - throw new RuntimeException("Fields mismatch"); - } - } - - localTableCache.put(createView.getTableName(), table); - if(includeDimTable){ - dimTableNewTable.put(createView.getTableName(), table); - } + String TableAlias = sqlWithItem.name.toString(); + Table table = tableEnv.sqlQuery(sqlWithItem.query.toString()); + tableEnv.registerTable(TableAlias, table); } - includeDimTable = false; - } else if (pollObj instanceof JoinInfo) { - includeDimTable = true; - LOG.info("----------exec join info----------\n{}", pollObj.toString()); - joinFun(pollObj, localTableCache, dimTableNewTable,sideTableMap, tableEnv); + + }else if (pollObj instanceof JoinInfo){ + preIsSideJoin = true; + joinFun(pollObj, localTableCache, sideTableMap, tableEnv, replaceInfoList); } } } - /** - * 解析出as查询的表和字段的关系 - * - * @param asSqlNode - * @param tableCache - * @return - */ - private FieldReplaceInfo parseAsQuery(SqlBasicCall asSqlNode, Map tableCache) { - SqlNode info = asSqlNode.getOperands()[0]; - SqlNode alias = asSqlNode.getOperands()[1]; + private void addAliasForFieldNode(SqlNode pollSqlNode, List fieldList, HashBasedTable mappingTable) { + SqlKind sqlKind = pollSqlNode.getKind(); + switch (sqlKind) { + case INSERT: + SqlNode source = ((SqlInsert) pollSqlNode).getSource(); + addAliasForFieldNode(source, fieldList, mappingTable); + break; - SqlKind infoKind = info.getKind(); - if (infoKind != SELECT) { - return null; - } + case AS: + addAliasForFieldNode(((SqlBasicCall) pollSqlNode).getOperands()[0], fieldList, mappingTable); + break; - List extractFieldList = TableUtils.parserSelectField((SqlSelect) info, tableCache); + case SELECT: - HashBasedTable mappingTable = HashBasedTable.create(); - for (FieldInfo fieldInfo : extractFieldList) { - String tableName = fieldInfo.getTable(); - String fieldName = fieldInfo.getFieldName(); - String mappingFieldName = ParseUtils.dealDuplicateFieldName(mappingTable, fieldName); - mappingTable.put(tableName, fieldName, mappingFieldName); - } + SqlNodeList selectList = ((SqlSelect) pollSqlNode).getSelectList(); - FieldReplaceInfo replaceInfo = new FieldReplaceInfo(); - replaceInfo.setMappingTable(mappingTable); - replaceInfo.setTargetTableName(alias.toString()); - replaceInfo.setTargetTableAlias(alias.toString()); - return replaceInfo; + selectList.getList().forEach(node -> { + if (node.getKind() == IDENTIFIER) { + SqlIdentifier sqlIdentifier = (SqlIdentifier) node; + if (sqlIdentifier.names.size() == 1) { + return; + } + // save real field + String fieldName = sqlIdentifier.names.get(1); + if (!fieldName.endsWith("0") || fieldName.endsWith("0") && mappingTable.columnMap().containsKey(fieldName)) { + fieldList.add(fieldName); + } + + } + }); + + for (int i = 0; i < selectList.getList().size(); i++) { + SqlNode node = selectList.get(i); + if (node.getKind() == IDENTIFIER) { + SqlIdentifier sqlIdentifier = (SqlIdentifier) node; + if (sqlIdentifier.names.size() == 1) { + return; + } + + String name = sqlIdentifier.names.get(1); + // avoid real field pv0 convert pv + if (name.endsWith("0") && !fieldList.contains(name) && !fieldList.contains(name.substring(0, name.length() - 1))) { + SqlOperator operator = new SqlAsOperator(); + SqlParserPos sqlParserPos = new SqlParserPos(0, 0); + + SqlIdentifier sqlIdentifierAlias = new SqlIdentifier(name.substring(0, name.length() - 1), null, sqlParserPos); + SqlNode[] sqlNodes = new SqlNode[2]; + sqlNodes[0] = sqlIdentifier; + sqlNodes[1] = sqlIdentifierAlias; + SqlBasicCall sqlBasicCall = new SqlBasicCall(operator, sqlNodes, sqlParserPos); + + selectList.set(i, sqlBasicCall); + } + + } + } + break; + } } public AliasInfo parseASNode(SqlNode sqlNode) throws SqlParseException { SqlKind sqlKind = sqlNode.getKind(); - if (sqlKind != AS) { + if(sqlKind != AS){ throw new RuntimeException(sqlNode + " is not 'as' operator"); } - SqlNode info = ((SqlBasicCall) sqlNode).getOperands()[0]; + SqlNode info = ((SqlBasicCall)sqlNode).getOperands()[0]; SqlNode alias = ((SqlBasicCall) sqlNode).getOperands()[1]; AliasInfo aliasInfo = new AliasInfo(); @@ -244,182 +217,408 @@ public AliasInfo parseASNode(SqlNode sqlNode) throws SqlParseException { return aliasInfo; } - public BaseRowTypeInfo buildOutRowTypeInfo(List sideJoinFieldInfo, - HashBasedTable mappingTable) { - // TypeInformation[] sideOutTypes = new TypeInformation[sideJoinFieldInfo.size()]; - LogicalType[] sideOutTypes = new LogicalType[sideJoinFieldInfo.size()]; + public RowTypeInfo buildOutRowTypeInfo(List sideJoinFieldInfo, HashBasedTable mappingTable){ + TypeInformation[] sideOutTypes = new TypeInformation[sideJoinFieldInfo.size()]; String[] sideOutNames = new String[sideJoinFieldInfo.size()]; - for (int i = 0; i < sideJoinFieldInfo.size(); i++) { + for(int i=0; i mappingTable, String targetTableName, String tableAlias) { + SqlKind sqlKind = sqlNode.getKind(); + switch (sqlKind) { + case INSERT: + SqlNode sqlSource = ((SqlInsert) sqlNode).getSource(); + replaceFieldName(sqlSource, mappingTable, targetTableName, tableAlias); + break; + case AS: + SqlNode asNode = ((SqlBasicCall) sqlNode).getOperands()[0]; + replaceFieldName(asNode, mappingTable, targetTableName, tableAlias); + break; + case SELECT: + SqlSelect sqlSelect = (SqlSelect) filterNodeWithTargetName(sqlNode, targetTableName); + if(sqlSelect == null){ + return; + } - /** - * 对时间类型进行类型转换 - * - * @param leftTypeInfo - * @return - */ - private RowTypeInfo buildLeftTableOutType(RowTypeInfo leftTypeInfo) { - TypeInformation[] sideOutTypes = new TypeInformation[leftTypeInfo.getFieldNames().length]; - TypeInformation[] fieldTypes = leftTypeInfo.getFieldTypes(); - for (int i = 0; i < sideOutTypes.length; i++) { - sideOutTypes[i] = convertTimeAttributeType(fieldTypes[i]); + SqlNode sqlSource1 = sqlSelect.getFrom(); + if(sqlSource1.getKind() == AS){ + String tableName = ((SqlBasicCall)sqlSource1).getOperands()[0].toString(); + if(tableName.equalsIgnoreCase(targetTableName)){ + SqlNodeList sqlSelectList = sqlSelect.getSelectList(); + SqlNode whereNode = sqlSelect.getWhere(); + SqlNodeList sqlGroup = sqlSelect.getGroup(); + + //TODO 暂时不处理having + SqlNode sqlHaving = sqlSelect.getHaving(); + + List newSelectNodeList = Lists.newArrayList(); + for( int i=0; i replaceNodeList = replaceSelectStarFieldName(selectNode, mappingTable, tableAlias); + newSelectNodeList.addAll(replaceNodeList); + continue; + } + + SqlNode replaceNode = replaceSelectFieldName(selectNode, mappingTable, tableAlias); + if(replaceNode == null){ + continue; + } + + //sqlSelectList.set(i, replaceNode); + newSelectNodeList.add(replaceNode); + } + + SqlNodeList newSelectList = new SqlNodeList(newSelectNodeList, sqlSelectList.getParserPosition()); + sqlSelect.setSelectList(newSelectList); + + //where + if(whereNode != null){ + SqlNode[] sqlNodeList = ((SqlBasicCall)whereNode).getOperands(); + for(int i =0; i mappingTable, String tableAlias){ + if(groupNode.getKind() == IDENTIFIER){ + SqlIdentifier sqlIdentifier = (SqlIdentifier) groupNode; + if(sqlIdentifier.names.size() == 1){ + return sqlIdentifier; + } + String mappingFieldName = mappingTable.get(sqlIdentifier.getComponent(0).getSimple(), sqlIdentifier.getComponent(1).getSimple()); - public void setLocalSqlPluginPath(String localSqlPluginPath) { - this.localSqlPluginPath = localSqlPluginPath; + if(mappingFieldName == null){ + throw new RuntimeException("can't find mapping fieldName:" + sqlIdentifier.toString() ); + } + sqlIdentifier = sqlIdentifier.setName(0, tableAlias); + return sqlIdentifier.setName(1, mappingFieldName); + }else if(groupNode instanceof SqlBasicCall){ + SqlBasicCall sqlBasicCall = (SqlBasicCall) groupNode; + for(int i=0; i localTableCache, String tableAlias, String tableName) { + private Table getTableFromCache(Map localTableCache, String tableAlias, String tableName){ Table table = localTableCache.get(tableAlias); - if (table == null) { + if(table == null){ table = localTableCache.get(tableName); } - if (table == null) { - throw new RuntimeException("not register table " + tableAlias); + if(table == null){ + throw new RuntimeException("not register table " + tableName); } return table; } + private List replaceSelectStarFieldName(SqlNode selectNode, HashBasedTable mappingTable, String tableAlias){ + SqlIdentifier sqlIdentifier = (SqlIdentifier) selectNode; + List sqlNodes = Lists.newArrayList(); + if(sqlIdentifier.isStar()){//处理 [* or table.*] + int identifierSize = sqlIdentifier.names.size(); + Collection columns = null; + if(identifierSize == 1){ + columns = mappingTable.values(); + }else{ + columns = mappingTable.row(sqlIdentifier.names.get(0)).values(); + } - /** - * Analyzing conditions are very join the dimension tables include all equivalent conditions (i.e., dimension table is the primary key definition - * - * @return - */ - private boolean checkJoinCondition(SqlNode conditionNode, String sideTableAlias, AbstractSideTableInfo sideTableInfo) { - List conditionFields = getConditionFields(conditionNode, sideTableAlias, sideTableInfo); - return CollectionUtils.isEqualCollection(conditionFields, convertPrimaryAlias(sideTableInfo)); - } + for(String colAlias : columns){ + SqlParserPos sqlParserPos = new SqlParserPos(0, 0); + List columnInfo = Lists.newArrayList(); + columnInfo.add(tableAlias); + columnInfo.add(colAlias); + SqlIdentifier sqlIdentifierAlias = new SqlIdentifier(columnInfo, sqlParserPos); + sqlNodes.add(sqlIdentifierAlias); + } - private List convertPrimaryAlias(AbstractSideTableInfo sideTableInfo) { - List res = Lists.newArrayList(); - sideTableInfo.getPrimaryKeys().forEach(field -> { - res.add(sideTableInfo.getPhysicalFields().getOrDefault(field, field)); - }); - return res; + return sqlNodes; + }else{ + throw new RuntimeException("is not a star select field." + selectNode); + } } - /** - * check whether all table fields exist in join condition. - * @param conditionNode - * @param joinScope - */ - public void checkConditionFieldsInTable(SqlNode conditionNode, JoinScope joinScope, AbstractSideTableInfo sideTableInfo) { - List sqlNodeList = Lists.newArrayList(); - ParseUtils.parseAnd(conditionNode, sqlNodeList); - for (SqlNode sqlNode : sqlNodeList) { - if (!SqlKind.COMPARISON.contains(sqlNode.getKind())) { - throw new RuntimeException("It is not comparison operator."); + private SqlNode replaceSelectFieldName(SqlNode selectNode, HashBasedTable mappingTable, String tableAlias) { + if (selectNode.getKind() == AS) { + SqlNode leftNode = ((SqlBasicCall) selectNode).getOperands()[0]; + SqlNode replaceNode = replaceSelectFieldName(leftNode, mappingTable, tableAlias); + if (replaceNode != null) { + ((SqlBasicCall) selectNode).getOperands()[0] = replaceNode; + } + + return selectNode; + }else if(selectNode.getKind() == IDENTIFIER){ + SqlIdentifier sqlIdentifier = (SqlIdentifier) selectNode; + + if(sqlIdentifier.names.size() == 1){ + return selectNode; + } + + String mappingFieldName = mappingTable.get(sqlIdentifier.getComponent(0).getSimple(), sqlIdentifier.getComponent(1).getSimple()); + if(mappingFieldName == null){ + throw new RuntimeException("can't find mapping fieldName:" + selectNode.toString() ); } - SqlNode leftNode = ((SqlBasicCall) sqlNode).getOperands()[0]; - SqlNode rightNode = ((SqlBasicCall) sqlNode).getOperands()[1]; + sqlIdentifier = sqlIdentifier.setName(0, tableAlias); + sqlIdentifier = sqlIdentifier.setName(1, mappingFieldName); + return sqlIdentifier; + }else if(selectNode.getKind() == LITERAL || selectNode.getKind() == LITERAL_CHAIN){//字面含义 + return selectNode; + }else if( AGGREGATE.contains(selectNode.getKind()) + || AVG_AGG_FUNCTIONS.contains(selectNode.getKind()) + || COMPARISON.contains(selectNode.getKind()) + || selectNode.getKind() == OTHER_FUNCTION + || selectNode.getKind() == DIVIDE + || selectNode.getKind() == CAST + || selectNode.getKind() == TRIM + || selectNode.getKind() == TIMES + || selectNode.getKind() == PLUS + || selectNode.getKind() == NOT_IN + || selectNode.getKind() == OR + || selectNode.getKind() == AND + || selectNode.getKind() == MINUS + || selectNode.getKind() == TUMBLE + || selectNode.getKind() == TUMBLE_START + || selectNode.getKind() == TUMBLE_END + || selectNode.getKind() == SESSION + || selectNode.getKind() == SESSION_START + || selectNode.getKind() == SESSION_END + || selectNode.getKind() == HOP + || selectNode.getKind() == HOP_START + || selectNode.getKind() == HOP_END + || selectNode.getKind() == BETWEEN + || selectNode.getKind() == IS_NULL + || selectNode.getKind() == IS_NOT_NULL + || selectNode.getKind() == CONTAINS + || selectNode.getKind() == TIMESTAMP_ADD + || selectNode.getKind() == TIMESTAMP_DIFF + + ){ + SqlBasicCall sqlBasicCall = (SqlBasicCall) selectNode; + for(int i=0; i allFieldNames = new ArrayList( - Arrays.asList(fieldNames) - ); - // HBase、Redis这种NoSQL Primary Key不在字段列表中,所以要加进去。 - if (sideTableInfo != null) { - List pks = sideTableInfo.getPrimaryKeys(); - if (pks != null) { - pks.stream() - .filter(pk -> !allFieldNames.contains(pk)) - .forEach(pk -> allFieldNames.add(pk)); - } + private boolean checkJoinCondition(SqlNode conditionNode, String sideTableAlias, SideTableInfo sideTableInfo) { + List conditionFields = getConditionFields(conditionNode, sideTableAlias, sideTableInfo); + if(CollectionUtils.isEqualCollection(conditionFields, convertPrimaryAlias(sideTableInfo))){ + return true; } + return false; + } - boolean hasField = allFieldNames.contains(fieldName); - String fieldErrorMsg = "Table [%s] has not [%s] field. Error join condition is [%s]. If you find it is exist. Please check AS statement."; - Preconditions.checkState( - hasField, - fieldErrorMsg, - tableName, - fieldName, - conditionNode.toString() - ); + private List convertPrimaryAlias(SideTableInfo sideTableInfo) { + List res = Lists.newArrayList(); + sideTableInfo.getPrimaryKeys().forEach(field -> { + res.add(sideTableInfo.getPhysicalFields().getOrDefault(field, field)); + }); + return res; } - public List getConditionFields(SqlNode conditionNode, String specifyTableName, AbstractSideTableInfo sideTableInfo) { + public List getConditionFields(SqlNode conditionNode, String specifyTableName, SideTableInfo sideTableInfo){ List sqlNodeList = Lists.newArrayList(); ParseUtils.parseAnd(conditionNode, sqlNodeList); List conditionFields = Lists.newArrayList(); - for (SqlNode sqlNode : sqlNodeList) { + for(SqlNode sqlNode : sqlNodeList){ if (!SqlKind.COMPARISON.contains(sqlNode.getKind())) { throw new RuntimeException("not compare operator."); } - SqlIdentifier left = (SqlIdentifier) ((SqlBasicCall) sqlNode).getOperands()[0]; - SqlIdentifier right = (SqlIdentifier) ((SqlBasicCall) sqlNode).getOperands()[1]; + SqlIdentifier left = (SqlIdentifier)((SqlBasicCall)sqlNode).getOperands()[0]; + SqlIdentifier right = (SqlIdentifier)((SqlBasicCall)sqlNode).getOperands()[1]; String leftTableName = left.getComponent(0).getSimple(); String rightTableName = right.getComponent(0).getSimple(); String tableCol = ""; - if (leftTableName.equalsIgnoreCase(specifyTableName)) { + if(leftTableName.equalsIgnoreCase(specifyTableName)){ tableCol = left.getComponent(1).getSimple(); - } else if (rightTableName.equalsIgnoreCase(specifyTableName)) { + }else if(rightTableName.equalsIgnoreCase(specifyTableName)){ tableCol = right.getComponent(1).getSimple(); - } else { + }else{ throw new RuntimeException(String.format("side table:%s join condition is wrong", specifyTableName)); } tableCol = sideTableInfo.getPhysicalFields().getOrDefault(tableCol, tableCol); @@ -429,45 +628,74 @@ public List getConditionFields(SqlNode conditionNode, String specifyTabl return conditionFields; } - protected void dealAsSourceTable(StreamTableEnvironment tableEnv, - SqlNode pollSqlNode, - Map tableCache, - Collection newRegisterTableList) throws SqlParseException { + public void registerTmpTable(CreateTmpTableParser.SqlParserResult result, + Map sideTableMap, StreamTableEnvironment tableEnv, + Map tableCache) + throws Exception { - AliasInfo aliasInfo = parseASNode(pollSqlNode); - if (localTableCache.containsKey(aliasInfo.getName())) { - return; + if(localSqlPluginPath == null){ + throw new RuntimeException("need to set localSqlPluginPath"); } - boolean isGroupByTimeWindow = TableUtils.checkIsDimTableGroupBy(pollSqlNode, newRegisterTableList); - if(isGroupByTimeWindow){ - QueryOperationConverter.setProducesUpdates(true); - } - Table table = tableEnv.sqlQuery(aliasInfo.getName()); - QueryOperationConverter.setProducesUpdates(false); + localTableCache.putAll(tableCache); + Queue exeQueue = sideSQLParser.getExeQueue(result.getExecSql(), sideTableMap.keySet()); + Object pollObj = null; - tableEnv.registerTable(aliasInfo.getAlias(), table); - localTableCache.put(aliasInfo.getAlias(), table); + //need clean + boolean preIsSideJoin = false; + List replaceInfoList = Lists.newArrayList(); - LOG.info("Register Table {} by {}", aliasInfo.getAlias(), aliasInfo.getName()); + while((pollObj = exeQueue.poll()) != null){ - FieldReplaceInfo fieldReplaceInfo = parseAsQuery((SqlBasicCall) pollSqlNode, tableCache); - if (fieldReplaceInfo == null) { - return; - } + if(pollObj instanceof SqlNode){ + SqlNode pollSqlNode = (SqlNode) pollObj; + + if(preIsSideJoin){ + preIsSideJoin = false; + List fieldNames = null; + for (FieldReplaceInfo replaceInfo : replaceInfoList) { + fieldNames = Lists.newArrayList(); + replaceFieldName(pollSqlNode, replaceInfo.getMappingTable(), replaceInfo.getTargetTableName(), replaceInfo.getTargetTableAlias()); + addAliasForFieldNode(pollSqlNode, fieldNames, replaceInfo.getMappingTable()); + } + } + + if(pollSqlNode.getKind() == INSERT){ + tableEnv.sqlUpdate(pollSqlNode.toString()); + }else if(pollSqlNode.getKind() == AS){ + AliasInfo aliasInfo = parseASNode(pollSqlNode); + Table table = tableEnv.sqlQuery(aliasInfo.getName()); + tableEnv.registerTable(aliasInfo.getAlias(), table); + if(LOG.isInfoEnabled()){ + LOG.info("Register Table {} by {}", aliasInfo.getAlias(), aliasInfo.getName()); + } + localTableCache.put(aliasInfo.getAlias(), table); + } else if (pollSqlNode.getKind() == SELECT){ + Table table = tableEnv.sqlQuery(pollObj.toString()); + if (result.getFieldsInfoStr() == null){ + tableEnv.registerTable(result.getTableName(), table); + } else { + if (checkFieldsInfo(result, table)){ + table = table.as(tmpFields); + tableEnv.registerTable(result.getTableName(), table); + } else { + throw new RuntimeException("Fields mismatch"); + } + } + localTableCache.put(result.getTableName(), table); - //as 的源表 - Set fromTableNameSet = Sets.newHashSet(); - SqlNode fromNode = ((SqlBasicCall) pollSqlNode).getOperands()[0]; - TableUtils.getFromTableInfo(fromNode, fromTableNameSet); + } + }else if (pollObj instanceof JoinInfo){ + preIsSideJoin = true; + joinFun(pollObj, localTableCache, sideTableMap, tableEnv, replaceInfoList); + } + } } - private void joinFun(Object pollObj, - Map localTableCache, - Map dimTableNewTable, - Map sideTableMap, - StreamTableEnvironment tableEnv) throws Exception { + private void joinFun(Object pollObj, Map localTableCache, + Map sideTableMap, StreamTableEnvironment tableEnv, + List replaceInfoList) throws Exception{ JoinInfo joinInfo = (JoinInfo) pollObj; JoinScope joinScope = new JoinScope(); @@ -476,101 +704,63 @@ private void joinFun(Object pollObj, leftScopeChild.setTableName(joinInfo.getLeftTableName()); Table leftTable = getTableFromCache(localTableCache, joinInfo.getLeftTableAlias(), joinInfo.getLeftTableName()); - - RowTypeInfo leftTypeInfo = new RowTypeInfo(leftTable.getSchema().getFieldTypes(), leftTable.getSchema().getFieldNames()); - - int length = leftTable.getSchema().getFieldDataTypes().length; - LogicalType[] logicalTypes = new LogicalType[length]; - for (int i = 0; i < length; i++) { - logicalTypes[i] = leftTable.getSchema().getFieldDataTypes()[i].getLogicalType(); - if (logicalTypes[i] instanceof LegacyTypeInformationType && - ((LegacyTypeInformationType) logicalTypes[i]).getTypeInformation().getClass().equals(BigDecimalTypeInfo.class)) { - logicalTypes[i] = new DecimalType(38, 18); - } - - if (logicalTypes[i] instanceof LegacyTypeInformationType && - (((LegacyTypeInformationType) logicalTypes[i]).getTypeInformation().getClass().equals(LegacyLocalDateTimeTypeInfo.class))) { - logicalTypes[i] = new TimestampType(TimestampType.MAX_PRECISION); - } - } - - BaseRowTypeInfo leftBaseTypeInfo = new BaseRowTypeInfo(logicalTypes, leftTable.getSchema().getFieldNames()); - + RowTypeInfo leftTypeInfo = new RowTypeInfo(leftTable.getSchema().getTypes(), leftTable.getSchema().getColumnNames()); leftScopeChild.setRowTypeInfo(leftTypeInfo); - leftScopeChild.setBaseRowTypeInfo(leftBaseTypeInfo); JoinScope.ScopeChild rightScopeChild = new JoinScope.ScopeChild(); rightScopeChild.setAlias(joinInfo.getRightTableAlias()); rightScopeChild.setTableName(joinInfo.getRightTableName()); - AbstractSideTableInfo sideTableInfo = sideTableMap.get(joinInfo.getRightTableName()); - if (sideTableInfo == null) { + SideTableInfo sideTableInfo = sideTableMap.get(joinInfo.getRightTableName()); + if(sideTableInfo == null){ sideTableInfo = sideTableMap.get(joinInfo.getRightTableAlias()); } - extractActualSidePredicateInfos(joinInfo, sideTableInfo); - - if (sideTableInfo == null) { + if(sideTableInfo == null){ throw new RuntimeException("can't not find side table:" + joinInfo.getRightTableName()); } + if(!checkJoinCondition(joinInfo.getCondition(), joinInfo.getRightTableAlias(), sideTableInfo)){ + throw new RuntimeException("ON condition must contain all equal fields!!!"); + } + rightScopeChild.setRowTypeInfo(sideTableInfo.getRowTypeInfo()); - rightScopeChild.setBaseRowTypeInfo(sideTableInfo.getBaseRowTypeInfo()); joinScope.addScope(leftScopeChild); joinScope.addScope(rightScopeChild); - HashBasedTable mappingTable = ((JoinInfo) pollObj).getTableFieldRef(); - // 检查JOIN等式字段是否在原表中 - checkConditionFieldsInTable(joinInfo.getCondition(), joinScope, sideTableInfo); - //获取两个表的所有字段 List sideJoinFieldInfo = ParserJoinField.getRowTypeInfo(joinInfo.getSelectNode(), joinScope, true); - //通过join的查询字段信息过滤出需要的字段信息 - sideJoinFieldInfo.removeIf(tmpFieldInfo -> mappingTable.get(tmpFieldInfo.getTable(), tmpFieldInfo.getFieldName()) == null); String leftTableAlias = joinInfo.getLeftTableAlias(); Table targetTable = localTableCache.get(leftTableAlias); - if (targetTable == null) { + if(targetTable == null){ targetTable = localTableCache.get(joinInfo.getLeftTableName()); } - TypeInformation[] fieldDataTypes = targetTable.getSchema().getFieldTypes(); - for (int i = 0; i < fieldDataTypes.length; i++) { - if (fieldDataTypes[i].getClass().equals(BigDecimalTypeInfo.class)) { - fieldDataTypes[i] = BasicTypeInfo.BIG_DEC_TYPE_INFO; - } - - if (fieldDataTypes[i].getClass().equals(LegacyLocalDateTimeTypeInfo.class)) { - fieldDataTypes[i] = LocalTimeTypeInfo.LOCAL_DATE_TIME; - } - - if (fieldDataTypes[i].getClass().equals(TimeIndicatorTypeInfo.class)) { - fieldDataTypes[i] = TypeInformation.of(new TypeHint() {}); - } - } - - RowTypeInfo typeInfo = new RowTypeInfo(fieldDataTypes, targetTable.getSchema().getFieldNames()); + RowTypeInfo typeInfo = new RowTypeInfo(targetTable.getSchema().getTypes(), targetTable.getSchema().getColumnNames()); - DataStream adaptStream = tableEnv.toRetractStream(targetTable, typeInfo) - .map(f -> RowDataConvert.convertToBaseRow(f)); + DataStream adaptStream = tableEnv.toRetractStream(targetTable, org.apache.flink.types.Row.class) + .map((Tuple2 f0) -> { return f0.f1; }) + .returns(Row.class); //join side table before keyby ===> Reducing the size of each dimension table cache of async - if (sideTableInfo.isPartitionedJoin()) { - // TODO need change - // adaptStream = adaptStream.keyBy(new TupleKeySelector(leftBaseTypeInfo)); + if(sideTableInfo.isPartitionedJoin()){ + List leftJoinColList = getConditionFields(joinInfo.getCondition(), joinInfo.getLeftTableAlias(), sideTableInfo); + String[] leftJoinColArr = new String[leftJoinColList.size()]; + leftJoinColArr = leftJoinColList.toArray(leftJoinColArr); + adaptStream = adaptStream.keyBy(leftJoinColArr); } - DataStream dsOut = null; + DataStream dsOut = null; if(ECacheType.ALL.name().equalsIgnoreCase(sideTableInfo.getCacheType())){ - dsOut = SideWithAllCacheOperator.getSideJoinDataStream(adaptStream, sideTableInfo.getType(), localSqlPluginPath, typeInfo, joinInfo, sideJoinFieldInfo, sideTableInfo, pluginLoadMode); + dsOut = SideWithAllCacheOperator.getSideJoinDataStream(adaptStream, sideTableInfo.getType(), localSqlPluginPath, typeInfo, joinInfo, sideJoinFieldInfo, sideTableInfo); }else{ - dsOut = SideAsyncOperator.getSideJoinDataStream(adaptStream, sideTableInfo.getType(), localSqlPluginPath, typeInfo, joinInfo, sideJoinFieldInfo, sideTableInfo, pluginLoadMode); + dsOut = SideAsyncOperator.getSideJoinDataStream(adaptStream, sideTableInfo.getType(), localSqlPluginPath, typeInfo, joinInfo, sideJoinFieldInfo, sideTableInfo); } - BaseRowTypeInfo sideOutTypeInfo = buildOutRowTypeInfo(sideJoinFieldInfo, mappingTable); - + HashBasedTable mappingTable = HashBasedTable.create(); + RowTypeInfo sideOutTypeInfo = buildOutRowTypeInfo(sideJoinFieldInfo, mappingTable); dsOut.getTransformation().setOutputType(sideOutTypeInfo); - String targetTableName = joinInfo.getNewTableName(); String targetTableAlias = joinInfo.getNewTableAlias(); @@ -579,51 +769,32 @@ private void joinFun(Object pollObj, replaceInfo.setTargetTableName(targetTableName); replaceInfo.setTargetTableAlias(targetTableAlias); - boolean tableExists = false; - for (String table : tableEnv.listTables()) { - if (table.equals(targetTableName)) { - tableExists = true; - break; - } - } + replaceInfoList.add(replaceInfo); - if (!tableExists) { - Table joinTable = tableEnv.fromDataStream(dsOut); - tableEnv.createTemporaryView(targetTableName, joinTable); - localTableCache.put(joinInfo.getNewTableName(), joinTable); - dimTableNewTable.put(joinInfo.getNewTableName(), joinTable); + if (!tableEnv.isRegistered(joinInfo.getNewTableName())){ + tableEnv.registerDataStream(joinInfo.getNewTableName(), dsOut, String.join(",", sideOutTypeInfo.getFieldNames())); } } - /** - * 抽取维表本次真正使用的谓词集合 - * @param joinInfo 维表join信息 - * @param sideTableInfo 维表实体信息 - */ - private void extractActualSidePredicateInfos(JoinInfo joinInfo, AbstractSideTableInfo sideTableInfo) { - sideTableInfo.setPredicateInfoes(sideTableInfo.getFullPredicateInfoes() - .stream() - .filter(e -> e.getOwnerTable().equals(joinInfo.getRightTableAlias())) - .collect(Collectors.toList())); - } - private boolean checkFieldsInfo(CreateTmpTableParser.SqlParserResult result, Table table) { List fieldNames = new LinkedList<>(); String fieldsInfo = result.getFieldsInfoStr(); - String[] fields = StringUtils.split(fieldsInfo, ","); + String[] fields = fieldsInfo.split(","); for (int i = 0; i < fields.length; i++) { String[] filed = fields[i].split("\\s"); - if (filed.length < 2 || fields.length != table.getSchema().getFieldCount()) { + if (filed.length < 2 || fields.length != table.getSchema().getColumnNames().length){ return false; } else { String[] filedNameArr = new String[filed.length - 1]; System.arraycopy(filed, 0, filedNameArr, 0, filed.length - 1); String fieldName = String.join(" ", filedNameArr); fieldNames.add(fieldName); - String fieldType = filed[filed.length - 1].trim(); + String fieldType = filed[filed.length - 1 ].trim(); Class fieldClass = ClassUtil.stringConvertClass(fieldType); Class tableField = table.getSchema().getFieldType(i).get().getTypeClass(); - if (fieldClass != tableField) { + if (fieldClass == tableField){ + continue; + } else { return false; } } @@ -632,8 +803,4 @@ private boolean checkFieldsInfo(CreateTmpTableParser.SqlParserResult result, Tab return true; } - public static Map getDimTableNewTable(){ - return dimTableNewTable; - } - } diff --git a/core/src/main/java/com/dtstack/flink/sql/side/SideTableInfo.java b/core/src/main/java/com/dtstack/flink/sql/side/SideTableInfo.java new file mode 100644 index 000000000..e21389ea7 --- /dev/null +++ b/core/src/main/java/com/dtstack/flink/sql/side/SideTableInfo.java @@ -0,0 +1,134 @@ +/* + * 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 com.dtstack.flink.sql.side; + +import com.dtstack.flink.sql.table.TableInfo; +import org.apache.flink.api.common.typeinfo.TypeInformation; +import org.apache.flink.api.java.typeutils.RowTypeInfo; + +import java.io.Serializable; + +/** + * Reason: + * Date: 2018/7/25 + * Company: www.dtstack.com + * @author xuchao + */ + +public abstract class SideTableInfo extends TableInfo implements Serializable { + + public static final String TARGET_SUFFIX = "Side"; + + public static final String CACHE_KEY = "cache"; + + public static final String CACHE_SIZE_KEY = "cacheSize"; + + public static final String CACHE_TTLMS_KEY = "cacheTTLMs"; + + public static final String PARTITIONED_JOIN_KEY = "partitionedJoin"; + + public static final String CACHE_MODE_KEY = "cacheMode"; + + public static final String ASYNC_CAP_KEY = "asyncCapacity"; + + public static final String ASYNC_TIMEOUT_KEY = "asyncTimeout"; + + private String cacheType = "none";//None or LRU or ALL + + private int cacheSize = 10000; + + private long cacheTimeout = 60 * 1000;// + + private int asyncCapacity=100; + + private int asyncTimeout=10000; + + private boolean partitionedJoin = false; + + private String cacheMode="ordered"; + + public RowTypeInfo getRowTypeInfo(){ + Class[] fieldClass = getFieldClasses(); + TypeInformation[] types = new TypeInformation[fieldClass.length]; + String[] fieldNames = getFields(); + for(int i=0; i { Class sideParser = cl.loadClass(className); - if (!AbstractSideTableParser.class.isAssignableFrom(sideParser)) { + if (!AbsSideTableParser.class.isAssignableFrom(sideParser)) { throw new RuntimeException("class " + sideParser.getName() + " not subClass of AbsSideTableParser"); } - return sideParser.asSubclass(AbstractTableParser.class).newInstance(); + return sideParser.asSubclass(AbsTableParser.class).newInstance(); }); } } diff --git a/core/src/main/java/com/dtstack/flink/sql/side/TupleKeySelector.java b/core/src/main/java/com/dtstack/flink/sql/side/TupleKeySelector.java deleted file mode 100644 index dd7f617ac..000000000 --- a/core/src/main/java/com/dtstack/flink/sql/side/TupleKeySelector.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side; - -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.functions.KeySelector; -import org.apache.flink.api.java.typeutils.ResultTypeQueryable; -import org.apache.flink.table.dataformat.BaseRow; -import org.apache.flink.table.dataformat.GenericRow; - -/** - * Date: 2020/3/25 - * Company: www.dtstack.com - * @author maqi - */ -public class TupleKeySelector implements ResultTypeQueryable, KeySelector { - - private TypeInformation returnType; - - public TupleKeySelector(TypeInformation returnType) { - this.returnType = returnType; - } - - @Override - public BaseRow getKey(BaseRow value) throws Exception { - return GenericRow.copyReference((GenericRow)value); - } - - @Override - public TypeInformation getProducedType() { - return returnType; - } -} diff --git a/core/src/main/java/com/dtstack/flink/sql/side/cache/AbstractSideCache.java b/core/src/main/java/com/dtstack/flink/sql/side/cache/AbsSideCache.java similarity index 84% rename from core/src/main/java/com/dtstack/flink/sql/side/cache/AbstractSideCache.java rename to core/src/main/java/com/dtstack/flink/sql/side/cache/AbsSideCache.java index 58832c583..757f91600 100644 --- a/core/src/main/java/com/dtstack/flink/sql/side/cache/AbstractSideCache.java +++ b/core/src/main/java/com/dtstack/flink/sql/side/cache/AbsSideCache.java @@ -20,7 +20,7 @@ package com.dtstack.flink.sql.side.cache; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; +import com.dtstack.flink.sql.side.SideTableInfo; /** * Reason: @@ -30,11 +30,11 @@ * @author xuchao */ -public abstract class AbstractSideCache { +public abstract class AbsSideCache { - protected AbstractSideTableInfo sideTableInfo; + protected SideTableInfo sideTableInfo; - public AbstractSideCache(AbstractSideTableInfo sideTableInfo){ + public AbsSideCache(SideTableInfo sideTableInfo){ this.sideTableInfo = sideTableInfo; } diff --git a/core/src/main/java/com/dtstack/flink/sql/side/cache/LRUSideCache.java b/core/src/main/java/com/dtstack/flink/sql/side/cache/LRUSideCache.java index 2664efd34..700e13bb2 100644 --- a/core/src/main/java/com/dtstack/flink/sql/side/cache/LRUSideCache.java +++ b/core/src/main/java/com/dtstack/flink/sql/side/cache/LRUSideCache.java @@ -20,7 +20,7 @@ package com.dtstack.flink.sql.side.cache; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; +import com.dtstack.flink.sql.side.SideTableInfo; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; @@ -33,11 +33,11 @@ * @author xuchao */ -public class LRUSideCache extends AbstractSideCache { +public class LRUSideCache extends AbsSideCache{ protected transient Cache cache; - public LRUSideCache(AbstractSideTableInfo sideTableInfo) { + public LRUSideCache(SideTableInfo sideTableInfo) { super(sideTableInfo); } diff --git a/core/src/main/java/com/dtstack/flink/sql/side/operator/SideAsyncOperator.java b/core/src/main/java/com/dtstack/flink/sql/side/operator/SideAsyncOperator.java index b1f9264e5..290804200 100644 --- a/core/src/main/java/com/dtstack/flink/sql/side/operator/SideAsyncOperator.java +++ b/core/src/main/java/com/dtstack/flink/sql/side/operator/SideAsyncOperator.java @@ -20,15 +20,14 @@ package com.dtstack.flink.sql.side.operator; import com.dtstack.flink.sql.classloader.ClassLoaderManager; -import com.dtstack.flink.sql.side.BaseAsyncReqRow; +import com.dtstack.flink.sql.side.AsyncReqRow; import com.dtstack.flink.sql.side.FieldInfo; import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; +import com.dtstack.flink.sql.side.SideTableInfo; import com.dtstack.flink.sql.util.PluginUtil; import org.apache.flink.api.java.typeutils.RowTypeInfo; import org.apache.flink.streaming.api.datastream.AsyncDataStream; import org.apache.flink.streaming.api.datastream.DataStream; -import org.apache.flink.table.dataformat.BaseRow; import java.util.List; import java.util.concurrent.TimeUnit; @@ -50,27 +49,27 @@ public class SideAsyncOperator { private static final String ORDERED = "ordered"; - private static BaseAsyncReqRow loadAsyncReq(String sideType, String sqlRootDir, RowTypeInfo rowTypeInfo, JoinInfo joinInfo, - List outFieldInfoList, AbstractSideTableInfo sideTableInfo, String pluginLoadMode) throws Exception { + private static AsyncReqRow loadAsyncReq(String sideType, String sqlRootDir, RowTypeInfo rowTypeInfo, + JoinInfo joinInfo, List outFieldInfoList, SideTableInfo sideTableInfo) throws Exception { String pathOfType = String.format(PATH_FORMAT, sideType); - String pluginJarPath = PluginUtil.getJarFileDirPath(pathOfType, sqlRootDir, pluginLoadMode); + String pluginJarPath = PluginUtil.getJarFileDirPath(pathOfType, sqlRootDir); String className = PluginUtil.getSqlSideClassName(sideType, "side", OPERATOR_TYPE); return ClassLoaderManager.newInstance(pluginJarPath, (cl) -> - cl.loadClass(className).asSubclass(BaseAsyncReqRow.class) - .getConstructor(RowTypeInfo.class, JoinInfo.class, List.class, AbstractSideTableInfo.class) + cl.loadClass(className).asSubclass(AsyncReqRow.class) + .getConstructor(RowTypeInfo.class, JoinInfo.class, List.class, SideTableInfo.class) .newInstance(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo)); } - public static DataStream getSideJoinDataStream(DataStream inputStream, String sideType, String sqlRootDir, RowTypeInfo rowTypeInfo, JoinInfo joinInfo, - List outFieldInfoList, AbstractSideTableInfo sideTableInfo, String pluginLoadMode) throws Exception { - BaseAsyncReqRow asyncDbReq = loadAsyncReq(sideType, sqlRootDir, rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo, pluginLoadMode); + public static DataStream getSideJoinDataStream(DataStream inputStream, String sideType, String sqlRootDir, RowTypeInfo rowTypeInfo, JoinInfo joinInfo, + List outFieldInfoList, SideTableInfo sideTableInfo) throws Exception { + AsyncReqRow asyncDbReq = loadAsyncReq(sideType, sqlRootDir, rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); //TODO How much should be set for the degree of parallelism? Timeout? capacity settings? if (ORDERED.equals(sideTableInfo.getCacheMode())){ - return AsyncDataStream.orderedWait(inputStream, asyncDbReq, -1, TimeUnit.MILLISECONDS, sideTableInfo.getAsyncCapacity()) + return AsyncDataStream.orderedWait(inputStream, asyncDbReq, sideTableInfo.getAsyncTimeout(), TimeUnit.MILLISECONDS, sideTableInfo.getAsyncCapacity()) .setParallelism(sideTableInfo.getParallelism()); }else { - return AsyncDataStream.unorderedWait(inputStream, asyncDbReq, -1, TimeUnit.MILLISECONDS, sideTableInfo.getAsyncCapacity()) + return AsyncDataStream.unorderedWait(inputStream, asyncDbReq, sideTableInfo.getAsyncTimeout(), TimeUnit.MILLISECONDS, sideTableInfo.getAsyncCapacity()) .setParallelism(sideTableInfo.getParallelism()); } diff --git a/core/src/main/java/com/dtstack/flink/sql/side/operator/SideWithAllCacheOperator.java b/core/src/main/java/com/dtstack/flink/sql/side/operator/SideWithAllCacheOperator.java index 94901d8f9..5aa810b0f 100644 --- a/core/src/main/java/com/dtstack/flink/sql/side/operator/SideWithAllCacheOperator.java +++ b/core/src/main/java/com/dtstack/flink/sql/side/operator/SideWithAllCacheOperator.java @@ -20,10 +20,10 @@ package com.dtstack.flink.sql.side.operator; import com.dtstack.flink.sql.classloader.ClassLoaderManager; -import com.dtstack.flink.sql.side.BaseAllReqRow; +import com.dtstack.flink.sql.side.AllReqRow; import com.dtstack.flink.sql.side.FieldInfo; import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; +import com.dtstack.flink.sql.side.SideTableInfo; import com.dtstack.flink.sql.util.PluginUtil; import org.apache.flink.api.java.typeutils.RowTypeInfo; import org.apache.flink.streaming.api.datastream.DataStream; @@ -44,22 +44,22 @@ public class SideWithAllCacheOperator { private static final String OPERATOR_TYPE = "All"; - private static BaseAllReqRow loadFlatMap(String sideType, String sqlRootDir, RowTypeInfo rowTypeInfo, - JoinInfo joinInfo, List outFieldInfoList, - AbstractSideTableInfo sideTableInfo, String pluginLoadMode) throws Exception { + private static AllReqRow loadFlatMap(String sideType, String sqlRootDir, RowTypeInfo rowTypeInfo, + JoinInfo joinInfo, List outFieldInfoList, + SideTableInfo sideTableInfo) throws Exception { String pathOfType = String.format(PATH_FORMAT, sideType); - String pluginJarPath = PluginUtil.getJarFileDirPath(pathOfType, sqlRootDir, pluginLoadMode); + String pluginJarPath = PluginUtil.getJarFileDirPath(pathOfType, sqlRootDir); String className = PluginUtil.getSqlSideClassName(sideType, "side", OPERATOR_TYPE); - return ClassLoaderManager.newInstance(pluginJarPath, (cl) -> cl.loadClass(className).asSubclass(BaseAllReqRow.class) - .getConstructor(RowTypeInfo.class, JoinInfo.class, List.class, AbstractSideTableInfo.class) + return ClassLoaderManager.newInstance(pluginJarPath, (cl) -> cl.loadClass(className).asSubclass(AllReqRow.class) + .getConstructor(RowTypeInfo.class, JoinInfo.class, List.class, SideTableInfo.class) .newInstance(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo)); } public static DataStream getSideJoinDataStream(DataStream inputStream, String sideType, String sqlRootDir, RowTypeInfo rowTypeInfo, JoinInfo joinInfo, - List outFieldInfoList, AbstractSideTableInfo sideTableInfo, String pluginLoadMode) throws Exception { - BaseAllReqRow allReqRow = loadFlatMap(sideType, sqlRootDir, rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo, pluginLoadMode); - return inputStream.flatMap(allReqRow).setParallelism(sideTableInfo.getParallelism()); + List outFieldInfoList, SideTableInfo sideTableInfo) throws Exception { + AllReqRow allReqRow = loadFlatMap(sideType, sqlRootDir, rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); + return inputStream.flatMap(allReqRow); } } diff --git a/core/src/main/java/com/dtstack/flink/sql/sink/IStreamSinkGener.java b/core/src/main/java/com/dtstack/flink/sql/sink/IStreamSinkGener.java index e29421369..3cfd48f1b 100644 --- a/core/src/main/java/com/dtstack/flink/sql/sink/IStreamSinkGener.java +++ b/core/src/main/java/com/dtstack/flink/sql/sink/IStreamSinkGener.java @@ -20,7 +20,7 @@ package com.dtstack.flink.sql.sink; -import com.dtstack.flink.sql.table.AbstractTargetTableInfo; +import com.dtstack.flink.sql.table.TargetTableInfo; /** * Reason: @@ -30,5 +30,5 @@ */ public interface IStreamSinkGener { - T genStreamSink(AbstractTargetTableInfo targetTableInfo); + T genStreamSink(TargetTableInfo targetTableInfo); } diff --git a/core/src/main/java/com/dtstack/flink/sql/outputformat/AbstractDtRichOutputFormat.java b/core/src/main/java/com/dtstack/flink/sql/sink/MetricOutputFormat.java similarity index 74% rename from core/src/main/java/com/dtstack/flink/sql/outputformat/AbstractDtRichOutputFormat.java rename to core/src/main/java/com/dtstack/flink/sql/sink/MetricOutputFormat.java index fbcc86bbd..f56f531e0 100644 --- a/core/src/main/java/com/dtstack/flink/sql/outputformat/AbstractDtRichOutputFormat.java +++ b/core/src/main/java/com/dtstack/flink/sql/sink/MetricOutputFormat.java @@ -15,31 +15,31 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.dtstack.flink.sql.outputformat; +package com.dtstack.flink.sql.sink; import com.dtstack.flink.sql.metric.MetricConstant; +import org.apache.flink.api.java.tuple.Tuple2; + import org.apache.flink.api.common.io.RichOutputFormat; import org.apache.flink.metrics.Counter; import org.apache.flink.metrics.Meter; import org.apache.flink.metrics.MeterView; /** - * extend RichOutputFormat with metric 'dtNumRecordsOut', 'dtNumDirtyRecordsOut', 'dtNumRecordsOutRate' * Created by sishu.yss on 2018/11/28. */ -public abstract class AbstractDtRichOutputFormat extends RichOutputFormat{ +public abstract class MetricOutputFormat extends RichOutputFormat{ + + protected transient Counter outRecords; - public transient Counter outRecords; - public transient Counter outDirtyRecords; - public transient Meter outRecordsRate; + protected transient Counter outDirtyRecords; - protected static int ROW_PRINT_FREQUENCY = 1000; - protected static int DIRTY_PRINT_FREQUENCY = 1000; + protected transient Meter outRecordsRate; - public void initMetric() { + public void initMetric() { outRecords = getRuntimeContext().getMetricGroup().counter(MetricConstant.DT_NUM_RECORDS_OUT); outDirtyRecords = getRuntimeContext().getMetricGroup().counter(MetricConstant.DT_NUM_DIRTY_RECORDS_OUT); outRecordsRate = getRuntimeContext().getMetricGroup().meter(MetricConstant.DT_NUM_RECORDS_OUT_RATE, new MeterView(outRecords, 20)); - } + } } diff --git a/core/src/main/java/com/dtstack/flink/sql/sink/StreamSinkFactory.java b/core/src/main/java/com/dtstack/flink/sql/sink/StreamSinkFactory.java index 4c268630c..53460081d 100644 --- a/core/src/main/java/com/dtstack/flink/sql/sink/StreamSinkFactory.java +++ b/core/src/main/java/com/dtstack/flink/sql/sink/StreamSinkFactory.java @@ -21,8 +21,8 @@ package com.dtstack.flink.sql.sink; import com.dtstack.flink.sql.classloader.ClassLoaderManager; -import com.dtstack.flink.sql.table.AbstractTableParser; -import com.dtstack.flink.sql.table.AbstractTargetTableInfo; +import com.dtstack.flink.sql.table.AbsTableParser; +import com.dtstack.flink.sql.table.TargetTableInfo; import com.dtstack.flink.sql.util.DtStringUtil; import com.dtstack.flink.sql.util.PluginUtil; import org.apache.flink.table.sinks.TableSink; @@ -40,23 +40,23 @@ public class StreamSinkFactory { private static final String DIR_NAME_FORMAT = "%ssink"; - public static AbstractTableParser getSqlParser(String pluginType, String sqlRootDir, String pluginLoadMode) throws Exception { - String pluginJarPath = PluginUtil.getJarFileDirPath(String.format(DIR_NAME_FORMAT, pluginType), sqlRootDir, pluginLoadMode); + public static AbsTableParser getSqlParser(String pluginType, String sqlRootDir) throws Exception { + String pluginJarPath = PluginUtil.getJarFileDirPath(String.format(DIR_NAME_FORMAT, pluginType), sqlRootDir); String typeNoVersion = DtStringUtil.getPluginTypeWithoutVersion(pluginType); String className = PluginUtil.getSqlParserClassName(typeNoVersion, CURR_TYPE); return ClassLoaderManager.newInstance(pluginJarPath, (cl) -> { Class targetParser = cl.loadClass(className); - if(!AbstractTableParser.class.isAssignableFrom(targetParser)){ + if(!AbsTableParser.class.isAssignableFrom(targetParser)){ throw new RuntimeException("class " + targetParser.getName() + " not subClass of AbsTableParser"); } - return targetParser.asSubclass(AbstractTableParser.class).newInstance(); + return targetParser.asSubclass(AbsTableParser.class).newInstance(); }); } - public static TableSink getTableSink(AbstractTargetTableInfo targetTableInfo, String localSqlRootDir, String pluginLoadMode) throws Exception { + public static TableSink getTableSink(TargetTableInfo targetTableInfo, String localSqlRootDir) throws Exception { String pluginType = targetTableInfo.getType(); - String pluginJarDirPath = PluginUtil.getJarFileDirPath(String.format(DIR_NAME_FORMAT, pluginType), localSqlRootDir, pluginLoadMode); + String pluginJarDirPath = PluginUtil.getJarFileDirPath(String.format(DIR_NAME_FORMAT, pluginType), localSqlRootDir); String typeNoVersion = DtStringUtil.getPluginTypeWithoutVersion(pluginType); String className = PluginUtil.getGenerClassName(typeNoVersion, CURR_TYPE); diff --git a/core/src/main/java/com/dtstack/flink/sql/source/AbsDeserialization.java b/core/src/main/java/com/dtstack/flink/sql/source/AbsDeserialization.java new file mode 100644 index 000000000..d8b2e4d7e --- /dev/null +++ b/core/src/main/java/com/dtstack/flink/sql/source/AbsDeserialization.java @@ -0,0 +1,78 @@ +/* + * 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 com.dtstack.flink.sql.source; + +import com.dtstack.flink.sql.metric.MetricConstant; +import org.apache.flink.api.common.functions.RuntimeContext; +import org.apache.flink.api.common.serialization.AbstractDeserializationSchema; +import org.apache.flink.metrics.Counter; +import org.apache.flink.metrics.Meter; +import org.apache.flink.metrics.MeterView; + +/** + * add metric for source, customer Deserialization which want add metric need to extends this abs class + * Date: 2018/10/19 + * Company: www.dtstack.com + * + * @author xuchao + */ + +public abstract class AbsDeserialization extends AbstractDeserializationSchema { + + private static final long serialVersionUID = 2176278128811784415L; + + private transient RuntimeContext runtimeContext; + + protected transient Counter dirtyDataCounter; + + //tps ransactions Per Second + protected transient Counter numInRecord; + + protected transient Meter numInRate; + + //rps Record Per Second: deserialize data and out record num + protected transient Counter numInResolveRecord; + + protected transient Meter numInResolveRate; + + protected transient Counter numInBytes; + + protected transient Meter numInBytesRate; + + public RuntimeContext getRuntimeContext() { + return runtimeContext; + } + + public void setRuntimeContext(RuntimeContext runtimeContext) { + this.runtimeContext = runtimeContext; + } + + public void initMetric(){ + dirtyDataCounter = runtimeContext.getMetricGroup().counter(MetricConstant.DT_DIRTY_DATA_COUNTER); + + numInRecord = runtimeContext.getMetricGroup().counter(MetricConstant.DT_NUM_RECORDS_IN_COUNTER); + numInRate = runtimeContext.getMetricGroup().meter( MetricConstant.DT_NUM_RECORDS_IN_RATE, new MeterView(numInRecord, 20)); + + numInBytes = runtimeContext.getMetricGroup().counter(MetricConstant.DT_NUM_BYTES_IN_COUNTER); + numInBytesRate = runtimeContext.getMetricGroup().meter(MetricConstant.DT_NUM_BYTES_IN_RATE , new MeterView(numInBytes, 20)); + + numInResolveRecord = runtimeContext.getMetricGroup().counter(MetricConstant.DT_NUM_RECORDS_RESOVED_IN_COUNTER); + numInResolveRate = runtimeContext.getMetricGroup().meter(MetricConstant.DT_NUM_RECORDS_RESOVED_IN_RATE, new MeterView(numInResolveRecord, 20)); + } +} diff --git a/core/src/main/java/com/dtstack/flink/sql/source/IStreamSourceGener.java b/core/src/main/java/com/dtstack/flink/sql/source/IStreamSourceGener.java index fde5a235d..b8b8f6edc 100644 --- a/core/src/main/java/com/dtstack/flink/sql/source/IStreamSourceGener.java +++ b/core/src/main/java/com/dtstack/flink/sql/source/IStreamSourceGener.java @@ -20,7 +20,7 @@ package com.dtstack.flink.sql.source; -import com.dtstack.flink.sql.table.AbstractSourceTableInfo; +import com.dtstack.flink.sql.table.SourceTableInfo; import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; import org.apache.flink.table.api.java.StreamTableEnvironment; @@ -38,6 +38,6 @@ public interface IStreamSourceGener { * @param tableEnv * @return */ - T genStreamSource(AbstractSourceTableInfo sourceTableInfo, StreamExecutionEnvironment env, StreamTableEnvironment tableEnv); + T genStreamSource(SourceTableInfo sourceTableInfo, StreamExecutionEnvironment env, StreamTableEnvironment tableEnv); } diff --git a/core/src/main/java/com/dtstack/flink/sql/source/StreamSourceFactory.java b/core/src/main/java/com/dtstack/flink/sql/source/StreamSourceFactory.java index 1f1c77483..1057fb0ed 100644 --- a/core/src/main/java/com/dtstack/flink/sql/source/StreamSourceFactory.java +++ b/core/src/main/java/com/dtstack/flink/sql/source/StreamSourceFactory.java @@ -22,8 +22,8 @@ import com.dtstack.flink.sql.classloader.ClassLoaderManager; -import com.dtstack.flink.sql.table.AbstractSourceParser; -import com.dtstack.flink.sql.table.AbstractSourceTableInfo; +import com.dtstack.flink.sql.table.AbsSourceParser; +import com.dtstack.flink.sql.table.SourceTableInfo; import com.dtstack.flink.sql.util.DtStringUtil; import com.dtstack.flink.sql.util.PluginUtil; import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; @@ -43,17 +43,17 @@ public class StreamSourceFactory { private static final String DIR_NAME_FORMAT = "%ssource"; - public static AbstractSourceParser getSqlParser(String pluginType, String sqlRootDir, String pluginLoadMode) throws Exception { + public static AbsSourceParser getSqlParser(String pluginType, String sqlRootDir) throws Exception { - String pluginJarPath = PluginUtil.getJarFileDirPath(String.format(DIR_NAME_FORMAT, pluginType), sqlRootDir, pluginLoadMode); + String pluginJarPath = PluginUtil.getJarFileDirPath(String.format(DIR_NAME_FORMAT, pluginType), sqlRootDir); String typeNoVersion = DtStringUtil.getPluginTypeWithoutVersion(pluginType); String className = PluginUtil.getSqlParserClassName(typeNoVersion, CURR_TYPE); return ClassLoaderManager.newInstance(pluginJarPath, (cl) -> { Class sourceParser = cl.loadClass(className); - if(!AbstractSourceParser.class.isAssignableFrom(sourceParser)){ + if(!AbsSourceParser.class.isAssignableFrom(sourceParser)){ throw new RuntimeException("class " + sourceParser.getName() + " not subClass of AbsSourceParser"); } - return sourceParser.asSubclass(AbstractSourceParser.class).newInstance(); + return sourceParser.asSubclass(AbsSourceParser.class).newInstance(); }); } @@ -62,12 +62,12 @@ public static AbstractSourceParser getSqlParser(String pluginType, String sqlRoo * @param sourceTableInfo * @return */ - public static Table getStreamSource(AbstractSourceTableInfo sourceTableInfo, StreamExecutionEnvironment env, - StreamTableEnvironment tableEnv, String sqlRootDir, String pluginLoadMode) throws Exception { + public static Table getStreamSource(SourceTableInfo sourceTableInfo, StreamExecutionEnvironment env, + StreamTableEnvironment tableEnv, String sqlRootDir) throws Exception { String sourceTypeStr = sourceTableInfo.getType(); String typeNoVersion = DtStringUtil.getPluginTypeWithoutVersion(sourceTypeStr); - String pluginJarPath = PluginUtil.getJarFileDirPath(String.format(DIR_NAME_FORMAT, sourceTypeStr), sqlRootDir, pluginLoadMode); + String pluginJarPath = PluginUtil.getJarFileDirPath(String.format(DIR_NAME_FORMAT, sourceTypeStr), sqlRootDir); String className = PluginUtil.getGenerClassName(typeNoVersion, CURR_TYPE); return ClassLoaderManager.newInstance(pluginJarPath, (cl) -> { diff --git a/core/src/main/java/com/dtstack/flink/sql/table/AbstractSideTableParser.java b/core/src/main/java/com/dtstack/flink/sql/table/AbsSideTableParser.java similarity index 53% rename from core/src/main/java/com/dtstack/flink/sql/table/AbstractSideTableParser.java rename to core/src/main/java/com/dtstack/flink/sql/table/AbsSideTableParser.java index 52ab084bd..3c4199c8c 100644 --- a/core/src/main/java/com/dtstack/flink/sql/table/AbstractSideTableParser.java +++ b/core/src/main/java/com/dtstack/flink/sql/table/AbsSideTableParser.java @@ -21,10 +21,8 @@ package com.dtstack.flink.sql.table; import com.dtstack.flink.sql.enums.ECacheType; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; +import com.dtstack.flink.sql.side.SideTableInfo; import com.dtstack.flink.sql.util.MathUtil; -import org.apache.flink.util.Preconditions; - import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -36,24 +34,25 @@ * @author xuchao */ -public abstract class AbstractSideTableParser extends AbstractTableParser { +public abstract class AbsSideTableParser extends AbsTableParser { private final static String SIDE_SIGN_KEY = "sideSignKey"; private final static Pattern SIDE_TABLE_SIGN = Pattern.compile("(?i)^PERIOD\\s+FOR\\s+SYSTEM_TIME$"); - public AbstractSideTableParser() { - addParserHandler(SIDE_SIGN_KEY, SIDE_TABLE_SIGN, this::dealSideSign); + static { + keyPatternMap.put(SIDE_SIGN_KEY, SIDE_TABLE_SIGN); + keyHandlerMap.put(SIDE_SIGN_KEY, AbsSideTableParser::dealSideSign); } - private void dealSideSign(Matcher matcher, AbstractTableInfo tableInfo){ + private static void dealSideSign(Matcher matcher, TableInfo tableInfo){ //FIXME SIDE_TABLE_SIGN current just used as a sign for side table; and do nothing } //Analytical create table attributes ==> Get information cache - protected void parseCacheProp(AbstractSideTableInfo sideTableInfo, Map props){ - if(props.containsKey(AbstractSideTableInfo.CACHE_KEY.toLowerCase())){ - String cacheType = MathUtil.getString(props.get(AbstractSideTableInfo.CACHE_KEY.toLowerCase())); + protected void parseCacheProp(SideTableInfo sideTableInfo, Map props){ + if(props.containsKey(SideTableInfo.CACHE_KEY.toLowerCase())){ + String cacheType = MathUtil.getString(props.get(SideTableInfo.CACHE_KEY.toLowerCase())); if(cacheType == null){ return; } @@ -63,74 +62,53 @@ protected void parseCacheProp(AbstractSideTableInfo sideTableInfo, Map 0."); } sideTableInfo.setCacheSize(cacheSize); } - if(props.containsKey(AbstractSideTableInfo.CACHE_TTLMS_KEY.toLowerCase())){ - Long cacheTTLMS = MathUtil.getLongVal(props.get(AbstractSideTableInfo.CACHE_TTLMS_KEY.toLowerCase())); + if(props.containsKey(SideTableInfo.CACHE_TTLMS_KEY.toLowerCase())){ + Long cacheTTLMS = MathUtil.getLongVal(props.get(SideTableInfo.CACHE_TTLMS_KEY.toLowerCase())); if(cacheTTLMS < 1000){ throw new RuntimeException("cache time out need > 1000 ms."); } sideTableInfo.setCacheTimeout(cacheTTLMS); } - if(props.containsKey(AbstractSideTableInfo.PARTITIONED_JOIN_KEY.toLowerCase())){ - Boolean partitionedJoinKey = MathUtil.getBoolean(props.get(AbstractSideTableInfo.PARTITIONED_JOIN_KEY.toLowerCase())); + if(props.containsKey(SideTableInfo.PARTITIONED_JOIN_KEY.toLowerCase())){ + Boolean partitionedJoinKey = MathUtil.getBoolean(props.get(SideTableInfo.PARTITIONED_JOIN_KEY.toLowerCase())); if(partitionedJoinKey){ sideTableInfo.setPartitionedJoin(true); } } - if(props.containsKey(AbstractSideTableInfo.CACHE_MODE_KEY.toLowerCase())){ - String cachemode = MathUtil.getString(props.get(AbstractSideTableInfo.CACHE_MODE_KEY.toLowerCase())); + if(props.containsKey(SideTableInfo.CACHE_MODE_KEY.toLowerCase())){ + String cachemode = MathUtil.getString(props.get(SideTableInfo.CACHE_MODE_KEY.toLowerCase())); - if(!"ordered".equalsIgnoreCase(cachemode) && !"unordered".equalsIgnoreCase(cachemode)){ + if(!cachemode.equalsIgnoreCase("ordered") && !cachemode.equalsIgnoreCase("unordered")){ throw new RuntimeException("cachemode must ordered or unordered!"); } sideTableInfo.setCacheMode(cachemode.toLowerCase()); } - if(props.containsKey(AbstractSideTableInfo.ASYNC_CAP_KEY.toLowerCase())){ - Integer asyncCap = MathUtil.getIntegerVal(props.get(AbstractSideTableInfo.ASYNC_CAP_KEY.toLowerCase())); + if(props.containsKey(SideTableInfo.ASYNC_CAP_KEY.toLowerCase())){ + Integer asyncCap = MathUtil.getIntegerVal(props.get(SideTableInfo.ASYNC_CAP_KEY.toLowerCase())); if(asyncCap < 0){ throw new RuntimeException("asyncCapacity size need > 0."); } sideTableInfo.setAsyncCapacity(asyncCap); } - if(props.containsKey(AbstractSideTableInfo.ASYNC_TIMEOUT_KEY.toLowerCase())){ - Integer asyncTimeout = MathUtil.getIntegerVal(props.get(AbstractSideTableInfo.ASYNC_TIMEOUT_KEY.toLowerCase())); + if(props.containsKey(SideTableInfo.ASYNC_TIMEOUT_KEY.toLowerCase())){ + Integer asyncTimeout = MathUtil.getIntegerVal(props.get(SideTableInfo.ASYNC_TIMEOUT_KEY.toLowerCase())); if (asyncTimeout<0){ throw new RuntimeException("asyncTimeout size need > 0."); } sideTableInfo.setAsyncTimeout(asyncTimeout); } - - if(props.containsKey(AbstractSideTableInfo.ASYNC_FAIL_MAX_NUM_KEY.toLowerCase())){ - Long asyncFailMaxNum = MathUtil.getLongVal(props.get(AbstractSideTableInfo.ASYNC_FAIL_MAX_NUM_KEY.toLowerCase())); - if (asyncFailMaxNum<0){ - throw new RuntimeException("asyncFailMaxNum need > 0."); - } - sideTableInfo.setAsyncFailMaxNum(asyncFailMaxNum); - } - - if(props.containsKey(AbstractSideTableInfo.CONNECT_RETRY_MAX_NUM_KEY.toLowerCase())){ - Integer connectRetryMaxNum = MathUtil.getIntegerVal(props.get(AbstractSideTableInfo.CONNECT_RETRY_MAX_NUM_KEY.toLowerCase())); - if (connectRetryMaxNum > 0){ - sideTableInfo.setConnectRetryMaxNum(connectRetryMaxNum); - } - } - - if (props.containsKey(AbstractSideTableInfo.ASYNC_REQ_POOL_KEY.toLowerCase())) { - Integer asyncPoolSize = MathUtil.getIntegerVal(props.get(AbstractSideTableInfo.ASYNC_REQ_POOL_KEY.toLowerCase())); - Preconditions.checkArgument(asyncPoolSize > 0 && asyncPoolSize <= 20, "asyncPoolSize size limit (0,20]"); - sideTableInfo.setAsyncPoolSize(asyncPoolSize); - } } } } diff --git a/core/src/main/java/com/dtstack/flink/sql/table/AbstractSourceParser.java b/core/src/main/java/com/dtstack/flink/sql/table/AbsSourceParser.java similarity index 70% rename from core/src/main/java/com/dtstack/flink/sql/table/AbstractSourceParser.java rename to core/src/main/java/com/dtstack/flink/sql/table/AbsSourceParser.java index 308f5859f..82000b386 100644 --- a/core/src/main/java/com/dtstack/flink/sql/table/AbstractSourceParser.java +++ b/core/src/main/java/com/dtstack/flink/sql/table/AbsSourceParser.java @@ -20,6 +20,7 @@ package com.dtstack.flink.sql.table; +import com.dtstack.flink.sql.util.ClassUtil; import com.dtstack.flink.sql.util.MathUtil; import java.util.regex.Matcher; @@ -33,7 +34,7 @@ * @author xuchao */ -public abstract class AbstractSourceParser extends AbstractTableParser { +public abstract class AbsSourceParser extends AbsTableParser { private static final String VIRTUAL_KEY = "virtualFieldKey"; private static final String WATERMARK_KEY = "waterMarkKey"; @@ -43,21 +44,25 @@ public abstract class AbstractSourceParser extends AbstractTableParser { private static Pattern waterMarkKeyPattern = Pattern.compile("(?i)^\\s*WATERMARK\\s+FOR\\s+(\\S+)\\s+AS\\s+withOffset\\(\\s*(\\S+)\\s*,\\s*(\\d+)\\s*\\)$"); private static Pattern notNullKeyPattern = Pattern.compile("(?i)^(\\w+)\\s+(\\w+)\\s+NOT\\s+NULL?$"); - public AbstractSourceParser() { - addParserHandler(VIRTUAL_KEY, virtualFieldKeyPattern, this::dealVirtualField); - addParserHandler(WATERMARK_KEY, waterMarkKeyPattern, this::dealWaterMark); - addParserHandler(NOTNULL_KEY, notNullKeyPattern, this::dealNotNull); + static { + keyPatternMap.put(VIRTUAL_KEY, virtualFieldKeyPattern); + keyPatternMap.put(WATERMARK_KEY, waterMarkKeyPattern); + keyPatternMap.put(NOTNULL_KEY, notNullKeyPattern); + + keyHandlerMap.put(VIRTUAL_KEY, AbsSourceParser::dealVirtualField); + keyHandlerMap.put(WATERMARK_KEY, AbsSourceParser::dealWaterMark); + keyHandlerMap.put(NOTNULL_KEY, AbsSourceParser::dealNotNull); } - protected void dealVirtualField(Matcher matcher, AbstractTableInfo tableInfo){ - AbstractSourceTableInfo sourceTableInfo = (AbstractSourceTableInfo) tableInfo; + static void dealVirtualField(Matcher matcher, TableInfo tableInfo){ + SourceTableInfo sourceTableInfo = (SourceTableInfo) tableInfo; String fieldName = matcher.group(2); String expression = matcher.group(1); sourceTableInfo.addVirtualField(fieldName, expression); } - protected void dealWaterMark(Matcher matcher, AbstractTableInfo tableInfo){ - AbstractSourceTableInfo sourceTableInfo = (AbstractSourceTableInfo) tableInfo; + static void dealWaterMark(Matcher matcher, TableInfo tableInfo){ + SourceTableInfo sourceTableInfo = (SourceTableInfo) tableInfo; String eventTimeField = matcher.group(1); //FIXME Temporarily resolve the second parameter row_time_field Integer offset = MathUtil.getIntegerVal(matcher.group(3)); @@ -65,11 +70,11 @@ protected void dealWaterMark(Matcher matcher, AbstractTableInfo tableInfo){ sourceTableInfo.setMaxOutOrderness(offset); } - protected void dealNotNull(Matcher matcher, AbstractTableInfo tableInfo) { + static void dealNotNull(Matcher matcher, TableInfo tableInfo) { String fieldName = matcher.group(1); String fieldType = matcher.group(2); - Class fieldClass= dbTypeConvertToJavaType(fieldType); - AbstractTableInfo.FieldExtraInfo fieldExtraInfo = new AbstractTableInfo.FieldExtraInfo(); + Class fieldClass= ClassUtil.stringConvertClass(fieldType); + TableInfo.FieldExtraInfo fieldExtraInfo = new TableInfo.FieldExtraInfo(); fieldExtraInfo.setNotNull(true); tableInfo.addPhysicalMappings(fieldName, fieldName); @@ -78,5 +83,4 @@ protected void dealNotNull(Matcher matcher, AbstractTableInfo tableInfo) { tableInfo.addFieldType(fieldType); tableInfo.addFieldExtraInfo(fieldExtraInfo); } - } diff --git a/core/src/main/java/com/dtstack/flink/sql/table/AbsTableParser.java b/core/src/main/java/com/dtstack/flink/sql/table/AbsTableParser.java new file mode 100644 index 000000000..aa0639c8a --- /dev/null +++ b/core/src/main/java/com/dtstack/flink/sql/table/AbsTableParser.java @@ -0,0 +1,124 @@ +/* + * 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 com.dtstack.flink.sql.table; + +import com.dtstack.flink.sql.util.ClassUtil; +import com.dtstack.flink.sql.util.DtStringUtil; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; + +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Reason: + * Date: 2018/7/4 + * Company: www.dtstack.com + * @author xuchao + */ + +public abstract class AbsTableParser { + + private static final String PRIMARY_KEY = "primaryKey"; + + private static Pattern primaryKeyPattern = Pattern.compile("(?i)PRIMARY\\s+KEY\\s*\\((.*)\\)"); + + public static Map keyPatternMap = Maps.newHashMap(); + + public static Map keyHandlerMap = Maps.newHashMap(); + + static { + keyPatternMap.put(PRIMARY_KEY, primaryKeyPattern); + keyHandlerMap.put(PRIMARY_KEY, AbsTableParser::dealPrimaryKey); + } + + protected boolean fieldNameNeedsUpperCase() { + return true; + } + + public abstract TableInfo getTableInfo(String tableName, String fieldsInfo, Map props) throws Exception; + + public boolean dealKeyPattern(String fieldRow, TableInfo tableInfo){ + for(Map.Entry keyPattern : keyPatternMap.entrySet()){ + Pattern pattern = keyPattern.getValue(); + String key = keyPattern.getKey(); + Matcher matcher = pattern.matcher(fieldRow); + if(matcher.find()){ + ITableFieldDealHandler handler = keyHandlerMap.get(key); + if(handler == null){ + throw new RuntimeException("parse field [" + fieldRow + "] error."); + } + + handler.dealPrimaryKey(matcher, tableInfo); + return true; + } + } + + return false; + } + + public void parseFieldsInfo(String fieldsInfo, TableInfo tableInfo){ + + List fieldRows = DtStringUtil.splitIgnoreQuota(fieldsInfo, ','); + for(String fieldRow : fieldRows){ + fieldRow = fieldRow.trim(); + + String[] filedInfoArr = fieldRow.split("\\s+"); + if(filedInfoArr.length < 2 ){ + throw new RuntimeException(String.format("table [%s] field [%s] format error.", tableInfo.getName(), fieldRow)); + } + + boolean isMatcherKey = dealKeyPattern(fieldRow, tableInfo); + if(isMatcherKey){ + continue; + } + + //Compatible situation may arise in space in the fieldName + String[] filedNameArr = new String[filedInfoArr.length - 1]; + System.arraycopy(filedInfoArr, 0, filedNameArr, 0, filedInfoArr.length - 1); + String fieldName = String.join(" ", filedNameArr); + String fieldType = filedInfoArr[filedInfoArr.length - 1 ].trim(); + Class fieldClass = dbTypeConvertToJavaType(fieldType); + + tableInfo.addPhysicalMappings(filedInfoArr[0],filedInfoArr[0]); + tableInfo.addField(fieldName); + tableInfo.addFieldClass(fieldClass); + tableInfo.addFieldType(fieldType); + tableInfo.addFieldExtraInfo(null); + } + + tableInfo.finish(); + } + + public static void dealPrimaryKey(Matcher matcher, TableInfo tableInfo){ + String primaryFields = matcher.group(1).trim(); + String[] splitArry = primaryFields.split(","); + List primaryKes = Lists.newArrayList(splitArry); + tableInfo.setPrimaryKeys(primaryKes); + } + + public Class dbTypeConvertToJavaType(String fieldType) { + return ClassUtil.stringConvertClass(fieldType); + } + +} diff --git a/core/src/main/java/com/dtstack/flink/sql/table/AbstractTableParser.java b/core/src/main/java/com/dtstack/flink/sql/table/AbstractTableParser.java deleted file mode 100644 index aa8dc69fd..000000000 --- a/core/src/main/java/com/dtstack/flink/sql/table/AbstractTableParser.java +++ /dev/null @@ -1,214 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.table; - -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.util.ClassUtil; -import com.dtstack.flink.sql.util.DtStringUtil; -import com.google.common.base.Preconditions; -import com.google.common.collect.Maps; -import org.apache.commons.lang3.StringUtils; -import org.apache.flink.api.java.tuple.Tuple2; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; - -/** - * Reason: - * Date: 2018/7/4 - * Company: www.dtstack.com - * - * @author xuchao - */ - -public abstract class AbstractTableParser { - - private static final Logger LOG = LoggerFactory.getLogger(AbstractTableParser.class); - - private static final String PRIMARY_KEY = "primaryKey"; - private static final String NEST_JSON_FIELD_KEY = "nestFieldKey"; - private static final String CHAR_TYPE_NO_LENGTH = "CHAR"; - - private static final Pattern primaryKeyPattern = Pattern.compile("(?i)(^\\s*)PRIMARY\\s+KEY\\s*\\((.*)\\)"); - private static final Pattern nestJsonFieldKeyPattern = Pattern.compile("(?i)((@*\\S+\\.)*\\S+)\\s+(.+?)\\s+AS\\s+(\\w+)(\\s+NOT\\s+NULL)?$"); - private static final Pattern physicalFieldFunPattern = Pattern.compile("\\w+\\((\\w+)\\)$"); - private static final Pattern charTypePattern = Pattern.compile("(?i)CHAR\\((\\d*)\\)$"); - private static final Pattern typePattern = Pattern.compile("(\\S+)\\s+(\\w+.*)"); - - - private Map patternMap = Maps.newHashMap(); - - private Map handlerMap = Maps.newHashMap(); - - public AbstractTableParser() { - addParserHandler(PRIMARY_KEY, primaryKeyPattern, this::dealPrimaryKey); - addParserHandler(NEST_JSON_FIELD_KEY, nestJsonFieldKeyPattern, this::dealNestField); - } - - protected boolean fieldNameNeedsUpperCase() { - return true; - } - - public abstract AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) throws Exception; - - public boolean dealKeyPattern(String fieldRow, AbstractTableInfo tableInfo) { - for (Map.Entry keyPattern : patternMap.entrySet()) { - Pattern pattern = keyPattern.getValue(); - String key = keyPattern.getKey(); - Matcher matcher = pattern.matcher(fieldRow); - if (matcher.find()) { - ITableFieldDealHandler handler = handlerMap.get(key); - if (handler == null) { - throw new RuntimeException("parse field [" + fieldRow + "] error."); - } - - handler.dealPrimaryKey(matcher, tableInfo); - return true; - } - } - - return false; - } - - public void parseFieldsInfo(String fieldsInfo, AbstractTableInfo tableInfo) { - - List fieldRows = DtStringUtil.splitField(fieldsInfo); - - for (int i = 0; i < fieldRows.size(); i++) { - String fieldRow = fieldRows.get(i).trim(); - - if (StringUtils.isBlank(fieldRow)) { - throw new RuntimeException(String.format("Empty field appears in position [%s] in table [%s]", - i + 1, tableInfo.getName())); - } - - boolean isMatcherKey = dealKeyPattern(fieldRow, tableInfo); - if (isMatcherKey) { - continue; - } - - handleKeyNotHaveAlias(fieldRow, tableInfo); - } - - /* - * check whether filed list contains pks and then add pks into field list. - * because some no-sql database is not primary key. eg :redis、hbase etc... - */ - if (tableInfo instanceof AbstractSideTableInfo) { - tableInfo.getPrimaryKeys().stream() - .filter(pk -> (!tableInfo.getFieldList().contains(pk))) - .forEach(pk -> { - try { - handleKeyNotHaveAlias(String.format("%s varchar", pk.trim()), tableInfo); - } catch (Exception e) { - LOG.error(String.format("Add primary key to field list failed. Reason: %s", e.getMessage())); - } - }); - } - - tableInfo.finish(); - } - - private void handleKeyNotHaveAlias(String fieldRow, AbstractTableInfo tableInfo) { - Tuple2 t = extractType(fieldRow, tableInfo.getName()); - String fieldName = t.f0; - String fieldType = t.f1; - - Class fieldClass; - AbstractTableInfo.FieldExtraInfo fieldExtraInfo = null; - - Matcher matcher = charTypePattern.matcher(fieldType); - if (matcher.find()) { - fieldClass = dbTypeConvertToJavaType(CHAR_TYPE_NO_LENGTH); - fieldExtraInfo = new AbstractTableInfo.FieldExtraInfo(); - fieldExtraInfo.setLength(Integer.parseInt(matcher.group(1))); - } else { - fieldClass = dbTypeConvertToJavaType(fieldType); - } - - tableInfo.addPhysicalMappings(fieldName, fieldName); - tableInfo.addField(fieldName); - tableInfo.addFieldClass(fieldClass); - tableInfo.addFieldType(fieldType); - tableInfo.addFieldExtraInfo(fieldExtraInfo); - } - - private Tuple2 extractType(String fieldRow, String tableName) { - Matcher matcher = typePattern.matcher(fieldRow); - if (matcher.matches()) { - String fieldName = matcher.group(1); - String fieldType = matcher.group(2); - return Tuple2.of(fieldName, fieldType); - } else { - String errorMsg = String.format("table [%s] field [%s] format error.", tableName, fieldRow); - throw new RuntimeException(errorMsg); - } - } - - public void dealPrimaryKey(Matcher matcher, AbstractTableInfo tableInfo) { - String primaryFields = matcher.group(2).trim(); - List primaryKeys = Arrays - .stream(primaryFields.split(",")) - .map(String::trim) - .collect(Collectors.toList()); - tableInfo.setPrimaryKeys(primaryKeys); - } - - /** - * add parser for alias field - * - * @param matcher - * @param tableInfo - */ - protected void dealNestField(Matcher matcher, AbstractTableInfo tableInfo) { - String physicalField = matcher.group(1); - Preconditions.checkArgument(!physicalFieldFunPattern.matcher(physicalField).find(), - "No need to add data types when using functions, The correct way is : strLen(name) as nameSize, "); - - String fieldType = matcher.group(3); - String mappingField = matcher.group(4); - Class fieldClass = dbTypeConvertToJavaType(fieldType); - boolean notNull = matcher.group(5) != null; - AbstractTableInfo.FieldExtraInfo fieldExtraInfo = new AbstractTableInfo.FieldExtraInfo(); - fieldExtraInfo.setNotNull(notNull); - - tableInfo.addPhysicalMappings(mappingField, physicalField); - tableInfo.addField(mappingField); - tableInfo.addFieldClass(fieldClass); - tableInfo.addFieldType(fieldType); - tableInfo.addFieldExtraInfo(fieldExtraInfo); - } - - public Class dbTypeConvertToJavaType(String fieldType) { - return ClassUtil.stringConvertClass(fieldType); - } - - protected void addParserHandler(String parserName, Pattern pattern, ITableFieldDealHandler handler) { - patternMap.put(parserName, pattern); - handlerMap.put(parserName, handler); - } - -} diff --git a/core/src/main/java/com/dtstack/flink/sql/table/ITableFieldDealHandler.java b/core/src/main/java/com/dtstack/flink/sql/table/ITableFieldDealHandler.java index fab634cdc..db804ea34 100644 --- a/core/src/main/java/com/dtstack/flink/sql/table/ITableFieldDealHandler.java +++ b/core/src/main/java/com/dtstack/flink/sql/table/ITableFieldDealHandler.java @@ -30,5 +30,5 @@ */ public interface ITableFieldDealHandler { - void dealPrimaryKey(Matcher matcher, AbstractTableInfo tableInfo); + void dealPrimaryKey(Matcher matcher, TableInfo tableInfo); } diff --git a/core/src/main/java/com/dtstack/flink/sql/table/AbstractSourceTableInfo.java b/core/src/main/java/com/dtstack/flink/sql/table/SourceTableInfo.java similarity index 94% rename from core/src/main/java/com/dtstack/flink/sql/table/AbstractSourceTableInfo.java rename to core/src/main/java/com/dtstack/flink/sql/table/SourceTableInfo.java index 559e233d9..9a41fa0a1 100644 --- a/core/src/main/java/com/dtstack/flink/sql/table/AbstractSourceTableInfo.java +++ b/core/src/main/java/com/dtstack/flink/sql/table/SourceTableInfo.java @@ -16,7 +16,7 @@ * limitations under the License. */ - + package com.dtstack.flink.sql.table; @@ -36,13 +36,13 @@ * @author xuchao */ -public abstract class AbstractSourceTableInfo extends AbstractTableInfo { +public abstract class SourceTableInfo extends TableInfo { public static final String SOURCE_SUFFIX = "Source"; - public static final String TIME_ZONE_KEY = "timezone"; + public static final String TIME_ZONE_KEY="timezone"; - private String timeZone = TimeZone.getDefault().getID(); + private String timeZone=TimeZone.getDefault().getID(); private String eventTimeField; diff --git a/core/src/main/java/com/dtstack/flink/sql/table/AbstractTableInfo.java b/core/src/main/java/com/dtstack/flink/sql/table/TableInfo.java similarity index 58% rename from core/src/main/java/com/dtstack/flink/sql/table/AbstractTableInfo.java rename to core/src/main/java/com/dtstack/flink/sql/table/TableInfo.java index f6cc9cd5d..a2454b893 100644 --- a/core/src/main/java/com/dtstack/flink/sql/table/AbstractTableInfo.java +++ b/core/src/main/java/com/dtstack/flink/sql/table/TableInfo.java @@ -16,71 +16,57 @@ * limitations under the License. */ + + package com.dtstack.flink.sql.table; -import com.dtstack.flink.sql.dirtyManager.manager.DirtyKeys; -import com.dtstack.flink.sql.outputformat.AbstractDtRichOutputFormat; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import java.io.Serializable; import java.util.List; import java.util.Map; -import java.util.Objects; /** * Reason: * Date: 2018/6/22 * Company: www.dtstack.com - * * @author xuchao */ -public abstract class AbstractTableInfo implements Serializable { +public abstract class TableInfo implements Serializable { public static final String PARALLELISM_KEY = "parallelism"; - public static final String ERROR_LIMIT = "errorLimit"; - public static final Boolean DEFAULT_FALSE = false; - public static final Boolean DEFAULT_TRUE = true; - public static final Object DEFAULT_NULL = null; - private final List fieldList = Lists.newArrayList(); - private final List fieldTypeList = Lists.newArrayList(); - private final List fieldClassList = Lists.newArrayList(); - private final List fieldExtraInfoList = Lists.newArrayList(); + private String name; + private String type; + private String[] fields; + private String[] fieldTypes; + private Class[] fieldClasses; - /** - * key:别名, value: realField - */ - private Map physicalFields = Maps.newLinkedHashMap(); - private List primaryKeys; - private Integer parallelism = -1; - private Map checkProperties; + private final List fieldList = Lists.newArrayList(); - /** - * 构建脏数据插件的相关信息 - */ - private Map dirtyProperties; + /**key:别名, value: realField */ + private Map physicalFields = Maps.newHashMap(); - /** - * error data limit. Task will failed once {@link AbstractDtRichOutputFormat#outDirtyRecords} - * count over limit. Default 1000L; - */ - private Long errorLimit = Long.MAX_VALUE; + private final List fieldTypeList = Lists.newArrayList(); + + private final List fieldClassList = Lists.newArrayList(); + + private final List fieldExtraInfoList = Lists.newArrayList(); + + private List primaryKeys; + + private Integer parallelism = 1; public String[] getFieldTypes() { return fieldTypes; } - public void setFieldTypes(String[] fieldTypes) { - this.fieldTypes = fieldTypes; - } - public abstract boolean check(); public String getType() { @@ -95,23 +81,11 @@ public String[] getFields() { return fields; } - public void setFields(String[] fields) { - this.fields = fields; - } - public Class[] getFieldClasses() { return fieldClasses; } - public void setFieldClasses(Class[] fieldClasses) { - this.fieldClasses = fieldClasses; - } - public List getPrimaryKeys() { - if (this instanceof AbstractSideTableInfo && - Objects.isNull(primaryKeys)) { - throw new IllegalArgumentException("Side table must contain [primary key]!"); - } return primaryKeys; } @@ -132,37 +106,45 @@ public Integer getParallelism() { } public void setParallelism(Integer parallelism) { - if (parallelism == null) { + if(parallelism == null){ return; } - if (parallelism <= 0) { + if(parallelism <= 0){ throw new RuntimeException("Abnormal parameter settings: parallelism > 0"); } this.parallelism = parallelism; } - public void addField(String fieldName) { - if (fieldList.contains(fieldName)) { - throw new RuntimeException("redundancy field name " + fieldName + " in table " + getName()); - } - + public void addField(String fieldName){ fieldList.add(fieldName); } - public void addPhysicalMappings(String aliasName, String physicalFieldName) { + public void addPhysicalMappings(String aliasName, String physicalFieldName){ physicalFields.put(aliasName, physicalFieldName); } - public void addFieldClass(Class fieldClass) { + public void addFieldClass(Class fieldClass){ fieldClassList.add(fieldClass); } - public void addFieldType(String fieldType) { + public void addFieldType(String fieldType){ fieldTypeList.add(fieldType); } + public void setFields(String[] fields) { + this.fields = fields; + } + + public void setFieldTypes(String[] fieldTypes) { + this.fieldTypes = fieldTypes; + } + + public void setFieldClasses(Class[] fieldClasses) { + this.fieldClasses = fieldClasses; + } + public void addFieldExtraInfo(FieldExtraInfo extraInfo) { fieldExtraInfoList.add(extraInfo); } @@ -183,52 +165,23 @@ public Map getPhysicalFields() { return physicalFields; } - public void setPhysicalFields(Map physicalFields) { - this.physicalFields = physicalFields; - } - public List getFieldExtraInfoList() { return fieldExtraInfoList; } - public Map getCheckProperties() { - return checkProperties; - } - - public void setCheckProperties() { - this.checkProperties = buildCheckProperties(); - } - - public Map buildCheckProperties() { - return Maps.newHashMap(); - } - - public Map getDirtyProperties() { - dirtyProperties.put(DirtyKeys.TABLE_NAME, this.name); - return dirtyProperties; - } - - public void setDirtyProperties(Map dirtyProperties) { - this.dirtyProperties = dirtyProperties; - } - - public Long getErrorLimit() { - return errorLimit; - } - - public void setErrorLimit(Long errorLimit) { - this.errorLimit = errorLimit; + public void setPhysicalFields(Map physicalFields) { + this.physicalFields = physicalFields; } - public void finish() { - this.fields = fieldList.toArray(new String[0]); - this.fieldClasses = fieldClassList.toArray(new Class[0]); - this.fieldTypes = fieldTypeList.toArray(new String[0]); + public void finish(){ + this.fields = fieldList.toArray(new String[fieldList.size()]); + this.fieldClasses = fieldClassList.toArray(new Class[fieldClassList.size()]); + this.fieldTypes = fieldTypeList.toArray(new String[fieldTypeList.size()]); } /** * field extra info,used to store `not null` `default 0`..., - *

+ * * now, only support not null */ public static class FieldExtraInfo implements Serializable { @@ -237,18 +190,6 @@ public static class FieldExtraInfo implements Serializable { * default false:allow field is null */ boolean notNull = false; - /** - * field length,eg.char(4) - */ - int length; - - public int getLength() { - return length; - } - - public void setLength(int length) { - this.length = length; - } public boolean getNotNull() { return notNull; @@ -257,13 +198,5 @@ public boolean getNotNull() { public void setNotNull(boolean notNull) { this.notNull = notNull; } - - @Override - public String toString() { - return "FieldExtraInfo{" + - "notNull=" + notNull + - ", length=" + length + - '}'; - } } } diff --git a/core/src/main/java/com/dtstack/flink/sql/table/AbstractTableInfoParser.java b/core/src/main/java/com/dtstack/flink/sql/table/TableInfoParser.java similarity index 66% rename from core/src/main/java/com/dtstack/flink/sql/table/AbstractTableInfoParser.java rename to core/src/main/java/com/dtstack/flink/sql/table/TableInfoParser.java index 41d0d230e..ae98d90ae 100644 --- a/core/src/main/java/com/dtstack/flink/sql/table/AbstractTableInfoParser.java +++ b/core/src/main/java/com/dtstack/flink/sql/table/TableInfoParser.java @@ -16,20 +16,19 @@ * limitations under the License. */ - + package com.dtstack.flink.sql.table; import com.dtstack.flink.sql.enums.ETableType; import com.dtstack.flink.sql.parser.CreateTableParser; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; +import com.dtstack.flink.sql.side.SideTableInfo; import com.dtstack.flink.sql.side.StreamSideFactory; import com.dtstack.flink.sql.sink.StreamSinkFactory; import com.dtstack.flink.sql.source.StreamSourceFactory; import com.dtstack.flink.sql.util.MathUtil; import com.google.common.base.Strings; import com.google.common.collect.Maps; -import org.apache.commons.lang3.StringUtils; import java.util.Map; import java.util.regex.Matcher; @@ -42,7 +41,7 @@ * @author xuchao */ -public class AbstractTableInfoParser { +public class TableInfoParser { private final static String TYPE_KEY = "type"; @@ -50,79 +49,75 @@ public class AbstractTableInfoParser { private final static Pattern SIDE_PATTERN = Pattern.compile(SIDE_TABLE_SIGN); - private Map sourceTableInfoMap = Maps.newConcurrentMap(); - - private Map targetTableInfoMap = Maps.newConcurrentMap(); + private Map sourceTableInfoMap = Maps.newConcurrentMap(); - private Map sideTableInfoMap = Maps.newConcurrentMap(); - - /** - * judge dim table of PERIOD FOR SYSTEM_TIME - * - * @param tableField - * @return - */ - private static boolean checkIsSideTable(String tableField) { - String[] fieldInfos = StringUtils.split(tableField, ","); - for (String field : fieldInfos) { - Matcher matcher = SIDE_PATTERN.matcher(field.trim()); - if (matcher.find()) { - return true; - } - } + private Map targetTableInfoMap = Maps.newConcurrentMap(); - return false; - } + private Map sideTableInfoMap = Maps.newConcurrentMap(); //Parsing loaded plugin - public AbstractTableInfo parseWithTableType( - int tableType - , CreateTableParser.SqlParserResult parserResult - , String localPluginRoot - , String pluginLoadMode - ) throws Exception { - AbstractTableParser absTableParser = null; + public TableInfo parseWithTableType(int tableType, CreateTableParser.SqlParserResult parserResult, + String localPluginRoot) throws Exception { + AbsTableParser absTableParser = null; Map props = parserResult.getPropMap(); String type = MathUtil.getString(props.get(TYPE_KEY)); - if (Strings.isNullOrEmpty(type)) { + if(Strings.isNullOrEmpty(type)){ throw new RuntimeException("create table statement requires property of type"); } - if (tableType == ETableType.SOURCE.getType()) { + if(tableType == ETableType.SOURCE.getType()){ boolean isSideTable = checkIsSideTable(parserResult.getFieldsInfoStr()); - if (!isSideTable) { + if(!isSideTable){ absTableParser = sourceTableInfoMap.get(type); - if (absTableParser == null) { - absTableParser = StreamSourceFactory.getSqlParser(type, localPluginRoot, pluginLoadMode); + if(absTableParser == null){ + absTableParser = StreamSourceFactory.getSqlParser(type, localPluginRoot); sourceTableInfoMap.put(type, absTableParser); } - } else { + }else{ absTableParser = sideTableInfoMap.get(type); - if (absTableParser == null) { - String cacheType = MathUtil.getString(props.get(AbstractSideTableInfo.CACHE_KEY)); - absTableParser = StreamSideFactory.getSqlParser(type, localPluginRoot, cacheType, pluginLoadMode); - sideTableInfoMap.put(type + cacheType, absTableParser); + if(absTableParser == null){ + String cacheType = MathUtil.getString(props.get(SideTableInfo.CACHE_KEY)); + absTableParser = StreamSideFactory.getSqlParser(type, localPluginRoot, cacheType); + sideTableInfoMap.put(type, absTableParser); } } - } else if (tableType == ETableType.SINK.getType()) { + }else if(tableType == ETableType.SINK.getType()){ absTableParser = targetTableInfoMap.get(type); - if (absTableParser == null) { - absTableParser = StreamSinkFactory.getSqlParser(type, localPluginRoot, pluginLoadMode); + if(absTableParser == null){ + absTableParser = StreamSinkFactory.getSqlParser(type, localPluginRoot); targetTableInfoMap.put(type, absTableParser); } } - if (absTableParser == null) { + if(absTableParser == null){ throw new RuntimeException(String.format("not support %s type of table", type)); } Map prop = Maps.newHashMap(); //Shield case - parserResult.getPropMap().forEach((key, val) -> prop.put(key.toLowerCase(), val)); + parserResult.getPropMap().forEach((key,val) -> prop.put(key.toLowerCase(), val)); + return absTableParser.getTableInfo(parserResult.getTableName(), parserResult.getFieldsInfoStr(), prop); } + + /** + * judge dim table of PERIOD FOR SYSTEM_TIME + * @param tableField + * @return + */ + private static boolean checkIsSideTable(String tableField){ + String[] fieldInfos = tableField.split(","); + for(String field : fieldInfos){ + Matcher matcher = SIDE_PATTERN.matcher(field.trim()); + if(matcher.find()){ + return true; + } + } + + return false; + } } diff --git a/core/src/main/java/com/dtstack/flink/sql/table/AbstractTargetTableInfo.java b/core/src/main/java/com/dtstack/flink/sql/table/TargetTableInfo.java similarity index 73% rename from core/src/main/java/com/dtstack/flink/sql/table/AbstractTargetTableInfo.java rename to core/src/main/java/com/dtstack/flink/sql/table/TargetTableInfo.java index 48de59227..70b625b5c 100644 --- a/core/src/main/java/com/dtstack/flink/sql/table/AbstractTargetTableInfo.java +++ b/core/src/main/java/com/dtstack/flink/sql/table/TargetTableInfo.java @@ -20,8 +20,6 @@ package com.dtstack.flink.sql.table; -import com.dtstack.flink.sql.format.FormatType; - /** * Reason: * Date: 2018/6/25 @@ -29,17 +27,13 @@ * @author xuchao */ -public abstract class AbstractTargetTableInfo extends AbstractTableInfo { - - public static final String FAST_CHECK = "fastCheck"; +public abstract class TargetTableInfo extends TableInfo { public static final String TARGET_SUFFIX = "Sink"; public static final String SINK_DATA_TYPE = "sinkdatatype"; - private String sinkDataType = FormatType.JSON.name(); - - private boolean fastCheck; + private String sinkDataType = "json"; public String getSinkDataType() { return sinkDataType; @@ -48,13 +42,4 @@ public String getSinkDataType() { public void setSinkDataType(String sinkDataType) { this.sinkDataType = sinkDataType; } - - public boolean getFastCheck() { - return fastCheck; - } - - public void setFastCheck(boolean fastCheck) { - this.fastCheck = fastCheck; - } - } diff --git a/core/src/main/java/com/dtstack/flink/sql/util/AuthUtil.java b/core/src/main/java/com/dtstack/flink/sql/util/AuthUtil.java deleted file mode 100644 index 646a11b66..000000000 --- a/core/src/main/java/com/dtstack/flink/sql/util/AuthUtil.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.util; - -import org.apache.commons.io.FileUtils; - -import java.io.File; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -/** - * Utility methods for helping with security tasks. - * Date: 2019/12/28 - * Company: www.dtstack.com - * @author maqi - */ -public class AuthUtil { - - public static String creatJaasFile(String prefix, String suffix, JAASConfig jaasConfig) throws IOException { - File krbConf = new File(System.getProperty("user.dir")); - File temp = File.createTempFile(prefix, suffix, krbConf); - temp.deleteOnExit(); - FileUtils.writeStringToFile(temp, jaasConfig.toString()); - return temp.getAbsolutePath(); - } - - - public static class JAASConfig { - private String entryName; - private String loginModule; - private String loginModuleFlag; - private Map loginModuleOptions; - - public JAASConfig(String entryName, String loginModule, String loginModuleFlag, Map loginModuleOptions) { - this.entryName = entryName; - this.loginModule = loginModule; - this.loginModuleFlag = loginModuleFlag; - this.loginModuleOptions = loginModuleOptions; - } - - public static Builder builder() { - return new Builder(); - } - - @Override - public String toString() { - StringBuilder stringBuilder = new StringBuilder(entryName).append(" {\n\t") - .append(loginModule).append(" ").append(loginModuleFlag).append("\n\t"); - String[] keys = loginModuleOptions.keySet().toArray(new String[loginModuleOptions.size()]); - for (int i = 0; i < keys.length; i++) { - stringBuilder.append(keys[i]).append("=").append(loginModuleOptions.get(keys[i])); - if (i != keys.length - 1) { - stringBuilder.append("\n\t"); - } else { - stringBuilder.append(";\n"); - } - - } - stringBuilder.append("\n").append("};"); - return stringBuilder.toString(); - } - - public static class Builder { - private String entryName; - private String loginModule; - private String loginModuleFlag; - private Map loginModuleOptions; - - public Builder setEntryName(String entryName) { - this.entryName = entryName; - return this; - } - - public Builder setLoginModule(String loginModule) { - this.loginModule = loginModule; - return this; - } - - public Builder setLoginModuleFlag(String loginModuleFlag) { - this.loginModuleFlag = loginModuleFlag; - return this; - } - - public Builder setLoginModuleOptions(Map loginModuleOptions) { - this.loginModuleOptions = loginModuleOptions; - return this; - } - - public JAASConfig build() { - return new JAASConfig( - entryName, loginModule, loginModuleFlag, loginModuleOptions); - } - } - } -} diff --git a/core/src/main/java/com/dtstack/flink/sql/util/ClassUtil.java b/core/src/main/java/com/dtstack/flink/sql/util/ClassUtil.java index 3ad26fc01..feebbe3f1 100644 --- a/core/src/main/java/com/dtstack/flink/sql/util/ClassUtil.java +++ b/core/src/main/java/com/dtstack/flink/sql/util/ClassUtil.java @@ -20,15 +20,10 @@ package com.dtstack.flink.sql.util; -import java.lang.reflect.Array; import java.math.BigDecimal; -import java.sql.Clob; import java.sql.Date; -import java.sql.NClob; import java.sql.Time; import java.sql.Timestamp; -import java.util.HashMap; -import java.util.Map; /** * Reason: TODO ADD REASON(可选) @@ -39,18 +34,7 @@ public class ClassUtil { public static Class stringConvertClass(String str) { - - // 这部分主要是告诉Class转TypeInfomation的方法,字段是Array类型 - String lowerStr = str.toLowerCase().trim(); - if (lowerStr.startsWith("array")) { - return Array.newInstance(Integer.class, 0).getClass(); - } - if (lowerStr.startsWith("map")) { - Map m = new HashMap(); - return m.getClass(); - } - - switch (lowerStr) { + switch (str.toLowerCase()) { case "boolean": case "bit": return Boolean.class; @@ -77,7 +61,6 @@ public static Class stringConvertClass(String str) { case "varchar": case "char": case "text": - case "string": return String.class; case "real": @@ -103,12 +86,7 @@ public static Class stringConvertClass(String str) { case "decimal": case "decimalunsigned": return BigDecimal.class; - case "clob": - return Clob.class; - case "nclob": - return NClob.class; - default: - break; + } throw new RuntimeException("不支持 " + str + " 类型"); diff --git a/core/src/main/java/com/dtstack/flink/sql/util/DataTypeUtils.java b/core/src/main/java/com/dtstack/flink/sql/util/DataTypeUtils.java deleted file mode 100644 index bb15b9c45..000000000 --- a/core/src/main/java/com/dtstack/flink/sql/util/DataTypeUtils.java +++ /dev/null @@ -1,208 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.util; - -import com.google.common.base.Preconditions; -import com.google.common.collect.Lists; -import org.apache.commons.lang3.StringUtils; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.shaded.guava18.com.google.common.base.Splitter; -import org.apache.flink.table.api.Types; - -import java.util.ArrayList; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import static org.apache.commons.lang3.StringUtils.split; - -/** - * @program: flink.sql - * @author: wuren - * @create: 2020/07/09 - **/ -public class DataTypeUtils { - - private final static Pattern COMPOSITE_TYPE_PATTERN = Pattern.compile("(.+?)<(.+)>"); - private final static String ARRAY = "ARRAY"; - private final static String MAP = "MAP"; - private final static String ROW = "ROW"; - private final static char FIELD_DELIMITER = ','; - private final static char TYPE_DELIMITER = ' '; - - private DataTypeUtils() {} - - /** - * 目前ARRAY里只支持ROW和其他基本类型 - * @param arrayTypeString - * @return - */ - public static TypeInformation convertToArray(String arrayTypeString) { - Matcher matcher = matchCompositeType(arrayTypeString); - final String errorMsg = arrayTypeString + "convert to array type error!"; - Preconditions.checkState(matcher.find(), errorMsg); - - String normalizedType = normalizeType(matcher.group(1)); - Preconditions.checkState(ARRAY.equals(normalizedType), errorMsg); - - String elementTypeString = matcher.group(2); - TypeInformation elementType; - String normalizedElementType = normalizeType(elementTypeString); - if (normalizedElementType.startsWith(ROW)) { - elementType = convertToRow(elementTypeString); - } else { - elementType = convertToAtomicType(elementTypeString); - } - - return Types.OBJECT_ARRAY(elementType); - } - - /** - * 目前Map里只支持基本类型 - * @param mapTypeString - * @return - */ - public static TypeInformation convertToMap(String mapTypeString) { - Matcher matcher = matchCompositeType(mapTypeString); - final String errorMsg = mapTypeString + "convert to map type error!"; - Preconditions.checkState(matcher.find(), errorMsg); - - String normalizedType = normalizeType(matcher.group(1)); - Preconditions.checkState(MAP.equals(normalizedType), errorMsg); - - String kvTypeString = matcher.group(2); - String[] kvTypeStringList = StringUtils.split(kvTypeString, ","); - final String mapTypeErrorMsg = "There can only be key and value two types in map declaration."; - Preconditions.checkState(kvTypeStringList.length == 2, mapTypeErrorMsg); - String keyTypeString = normalizeType(kvTypeStringList[0]); - String valueTypeString = normalizeType(kvTypeStringList[1]); - TypeInformation keyType = convertToAtomicType(keyTypeString); - TypeInformation valueType = convertToAtomicType(valueTypeString); - return Types.MAP(keyType, valueType); - } - - /** - * 目前ROW里只支持基本类型 - * @param rowTypeString - */ - public static RowTypeInfo convertToRow(String rowTypeString) { - Matcher matcher = matchCompositeType(rowTypeString); - final String errorMsg = rowTypeString + "convert to row type error!"; - Preconditions.checkState(matcher.find(), errorMsg); - - String normalizedType = normalizeType(matcher.group(1)); - Preconditions.checkState(ROW.equals(normalizedType), errorMsg); - - String elementTypeStr = matcher.group(2); - Iterable fieldInfoStrs = splitCompositeTypeField(elementTypeStr); - Tuple2 info = genFieldInfo(fieldInfoStrs); - return new RowTypeInfo(info.f0, info.f1); - } - - - private static Tuple2 genFieldInfo(Iterable fieldInfoStrs) { - ArrayList types = Lists.newArrayList(); - ArrayList fieldNames = Lists.newArrayList(); - - for (String fieldStr : fieldInfoStrs) { - Iterable splitedInfo = splitTypeInfo(fieldStr); - ArrayList info = Lists.newArrayList(splitedInfo.iterator()); - Preconditions.checkState(info.size() == 2, "field info must be name with type"); - - fieldNames.add(info.get(0)); - TypeInformation fieldType = convertToAtomicType(info.get(1)); - types.add(fieldType); - } - - TypeInformation[] typeArray = types.toArray(new TypeInformation[types.size()]); - String[] fieldNameArray = fieldNames.toArray(new String[fieldNames.size()]); - return Tuple2.of(typeArray, fieldNameArray); - } - - /** - * 转换基本类型,所有类型参考Flink官方文档,一共12个基本类型。 - * @param string - * @return - */ - public static TypeInformation convertToAtomicType(String string) { - switch (normalizeType(string)) { - case "VARCHAR": - case "STRING": - return Types.STRING(); - case "BOOLEAN": - return Types.BOOLEAN(); - case "TINYINT": - return Types.BYTE(); - case "SMALLINT": - return Types.SHORT(); - case "INT": - case "INTEGER": - return Types.INT(); - case "BIGINT": - return Types.LONG(); - case "FLOAT": - case "REAL": - return Types.FLOAT(); - case "DOUBLE": - return Types.DOUBLE(); - case "DECIMAL": - case "DEC": - case "NUMERIC": - return Types.DECIMAL(); - case "DATE": - return Types.SQL_DATE(); - case "TIME": - return Types.SQL_TIME(); - case "TIMESTAMP": - return Types.SQL_TIMESTAMP(); - default: - throw new RuntimeException("type " + string + "not supported, please refer to the flink doc!"); - } - } - - private static Iterable splitTypeInfo(String string) { - return Splitter - .on(TYPE_DELIMITER) - .trimResults() - .omitEmptyStrings() - .split(string); - } - - private static Iterable splitCompositeTypeField(String string) { - return Splitter - .on(FIELD_DELIMITER) - .trimResults() - .split(string); - } - - private static String replaceBlank(String s) { - return s.replaceAll("\\s", " ").trim(); - } - - private static Matcher matchCompositeType(String s) { - return COMPOSITE_TYPE_PATTERN.matcher( - replaceBlank(s) - ); - } - - private static String normalizeType(String s) { - return s.toUpperCase().trim(); - } -} diff --git a/core/src/main/java/com/dtstack/flink/sql/util/DateUtil.java b/core/src/main/java/com/dtstack/flink/sql/util/DateUtil.java index 428125ad8..5bfa2f203 100644 --- a/core/src/main/java/com/dtstack/flink/sql/util/DateUtil.java +++ b/core/src/main/java/com/dtstack/flink/sql/util/DateUtil.java @@ -16,36 +16,22 @@ * limitations under the License. */ - + package com.dtstack.flink.sql.util; import java.sql.Timestamp; import java.text.ParseException; import java.text.SimpleDateFormat; - -import java.time.Instant; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.ZoneId; -import java.time.ZoneOffset; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeParseException; - import java.util.Calendar; import java.util.Date; import java.util.Locale; import java.util.SimpleTimeZone; -import java.util.TimeZone; -import java.util.regex.Pattern; - -import static java.time.format.DateTimeFormatter.ISO_INSTANT; /** * - * 日期工具 + * Reason: TODO ADD REASON(可选) * Date: 2017年03月10日 下午1:16:37 * Company: www.dtstack.com * @author sishu.yss @@ -53,16 +39,13 @@ */ public class DateUtil { - static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); - static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd"); - static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm:ss"); - - private static final Pattern DATETIME = Pattern.compile("^\\d{4}-(?:0[0-9]|1[0-2])-[0-9]{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{3,9})?Z$"); - private static final Pattern DATE = Pattern.compile("^\\d{4}-(?:0[0-9]|1[0-2])-[0-9]{2}$"); - private static final Pattern TIME = Pattern.compile("^\\d{2}:\\d{2}:\\d{2}(\\.\\d{3,9})?Z$"); - private static final int MILLIS_PER_SECOND = 1000; - - + static final String timeZone = "GMT+8"; + static final String datetimeFormat = "yyyy-MM-dd HH:mm:ss"; + static final String dateFormat = "yyyy-MM-dd"; + static final String timeFormat = "HH:mm:ss"; + static final SimpleDateFormat datetimeFormatter = new SimpleDateFormat(datetimeFormat); + static final SimpleDateFormat dateFormatter = new SimpleDateFormat(dateFormat); + static final SimpleDateFormat timeFormatter = new SimpleDateFormat(timeFormat); public static java.sql.Date columnToDate(Object column) { if(column instanceof String) { @@ -87,44 +70,23 @@ public static Date stringToDate(String strDate) { return null; } try { - return localDateTimetoDate(LocalDateTime.parse(strDate, DATE_TIME_FORMATTER)); - } catch (DateTimeParseException ignored) { + return datetimeFormatter.parse(strDate); + } catch (ParseException ignored) { } try { - return localDateTimetoDate(LocalDate.parse(strDate, DATE_FORMATTER).atStartOfDay()); - } catch (DateTimeParseException ignored) { + return dateFormatter.parse(strDate); + } catch (ParseException ignored) { } try { - return localDateTimetoDate(LocalDateTime.of(LocalDate.now(), LocalTime.parse(strDate, TIME_FORMATTER))); - } catch (DateTimeParseException ignored) { + return timeFormatter.parse(strDate); + } catch (ParseException ignored) { } throw new RuntimeException("can't parse date"); } - public static Date localDateTimetoDate(LocalDateTime localDateTime){ - return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant()); - } - - public static LocalDateTime dateToLocalDateTime(Date date){ - date = transformSqlDateToUtilDate(date); - return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime(); - } - - /** - * 将java.sql.Date 转化为 java.util.Date - * @param date 不知道是java.sql.Date 还是 java.util.Date - * @return 最后返回 java.util.Date - */ - public static Date transformSqlDateToUtilDate(Date date) { - if (date instanceof java.sql.Date) { - date = new Date(date.getTime()); - } - return date; - } - /** * * @@ -137,13 +99,13 @@ public static long getTodayStart(long day) { if (("" + day).length() > 10) { cal.setTime(new Date(day)); } else { - cal.setTime(new Date(day * 1000L)); + cal.setTime(new Date(day * 1000)); } cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); - firstDay = cal.getTimeInMillis() / 1000L; + firstDay = cal.getTimeInMillis() / 1000; return firstDay; } @@ -154,13 +116,13 @@ public static long getTodayStart(long day) { * @return */ public static long getTodayStart(long day,String scope) { - if("MS".equals(scope)){ - return getTodayStart(day)*1000L; - }else if("S".equals(scope)){ - return getTodayStart(day); - }else{ - return getTodayStart(day); - } + if(scope.equals("MS")){ + return getTodayStart(day)*1000; + }else if(scope.equals("S")){ + return getTodayStart(day); + }else{ + return getTodayStart(day); + } } /** @@ -175,13 +137,13 @@ public static long getNextDayStart(long day) { if (("" + day).length() > 10) { cal.setTime(new Date(day)); } else { - cal.setTime(new Date(day * 1000L)); + cal.setTime(new Date(day * 1000)); } cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); - nextDay = (cal.getTimeInMillis() + daySpanMill) / 1000L; + nextDay = (cal.getTimeInMillis() + daySpanMill) / 1000; return nextDay; } @@ -192,15 +154,15 @@ public static long getNextDayStart(long day) { * @return */ public static long getNextDayStart(long day,String scope) { - if("MS".equals(scope)){ - return getNextDayStart(day)*1000L; - }else if("S".equals(scope)){ - return getNextDayStart(day); - }else{ - return getNextDayStart(day); - } + if(scope.equals("MS")){ + return getNextDayStart(day)*1000; + }else if(scope.equals("S")){ + return getNextDayStart(day); + }else{ + return getNextDayStart(day); + } } - + /** * @@ -210,13 +172,13 @@ public static long getNextDayStart(long day,String scope) { public static long getMonthFirst(long day) { long firstDay = 0L; Calendar cal = Calendar.getInstance(); - cal.setTime(new Date(day * 1000L)); + cal.setTime(new Date(day * 1000)); cal.set(Calendar.DAY_OF_MONTH, 1); cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); - firstDay = cal.getTimeInMillis() / 1000L; + firstDay = cal.getTimeInMillis() / 1000; return firstDay; } @@ -248,7 +210,7 @@ public static int getYear(long day) { public static long getWeekFirst(long day) { long firstDay = 0L; Calendar cal = Calendar.getInstance(); - cal.setTime(new Date(day * 1000L)); + cal.setTime(new Date(day * 1000)); cal.setFirstDayOfWeek(Calendar.MONDAY); cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); cal.set(Calendar.HOUR_OF_DAY, 0); @@ -261,13 +223,13 @@ public static long getWeekFirst(long day) { /** * 根据某个日期时间戳秒值,获取所在周在一年中是第几周. - * + * * @param day * @return */ public static int getWeekOfYear(long day) { Calendar cal = Calendar.getInstance(); - cal.setTime(new Date(day * 1000L)); + cal.setTime(new Date(day * 1000)); return cal.get(Calendar.WEEK_OF_YEAR); } @@ -281,17 +243,17 @@ public static int getWeekOfYear(long day) { */ public static String getYesterdayByString(String day, String inFormat, String outFormat){ try { - SimpleDateFormat sdf = new SimpleDateFormat(inFormat); - Date date = sdf.parse(day); - Calendar calendar = Calendar.getInstance(); - calendar.setTime(date); - int calendarDay = calendar.get(Calendar.DATE); - calendar.set(Calendar.DATE, calendarDay - 1); - String dayBefore = new SimpleDateFormat(outFormat).format(calendar.getTime()); - return dayBefore; - } catch (ParseException e) { - return null; - } + SimpleDateFormat sdf = new SimpleDateFormat(inFormat); + Date date = sdf.parse(day); + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + int calendarDay = calendar.get(Calendar.DATE); + calendar.set(Calendar.DATE, calendarDay - 1); + String dayBefore = new SimpleDateFormat(outFormat).format(calendar.getTime()); + return dayBefore; + } catch (ParseException e) { + return null; + } } /** @@ -312,7 +274,7 @@ public static String getTomorrowByString(String day, String inFormat, String out String dayBefore = new SimpleDateFormat(outFormat).format(calendar.getTime()); return dayBefore; } - + /** * * @param date @@ -344,7 +306,7 @@ public static String get30DaysBeforeByString(String day, String inFormat, String calendar.set(Calendar.DATE, calendarDay - 30); return new SimpleDateFormat(outFormat).format(calendar.getTime()); } - + /** * * @param day @@ -354,14 +316,14 @@ public static String get30DaysBeforeByString(String day, String inFormat, String * @throws ParseException */ public static String get30DaysLaterByString(String day, String inFormat, String outFormat) throws ParseException { - SimpleDateFormat sdf = new SimpleDateFormat(inFormat); - Date date = sdf.parse(day); - Calendar calendar = Calendar.getInstance(); - calendar.setTime(date); - int calendarDay = calendar.get(Calendar.DATE); - calendar.set(Calendar.DATE, calendarDay + 30); - String dayBefore = new SimpleDateFormat(outFormat).format(calendar.getTime()); - return dayBefore; + SimpleDateFormat sdf = new SimpleDateFormat(inFormat); + Date date = sdf.parse(day); + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + int calendarDay = calendar.get(Calendar.DATE); + calendar.set(Calendar.DATE, calendarDay + 30); + String dayBefore = new SimpleDateFormat(outFormat).format(calendar.getTime()); + return dayBefore; } @@ -373,7 +335,7 @@ public static String get30DaysLaterByString(String day, String inFormat, String * @return String * @throws ParseException */ - public static String getDateStrToFormat(String day, String inFormat, String outFormat) throws ParseException { + public static String getDateStrTOFormat(String day, String inFormat, String outFormat) throws ParseException { SimpleDateFormat sdf = new SimpleDateFormat(inFormat); Date date = sdf.parse(day); Calendar calendar = Calendar.getInstance(); @@ -381,13 +343,13 @@ public static String getDateStrToFormat(String day, String inFormat, String outF String dayBefore = new SimpleDateFormat(outFormat).format(calendar.getTime()); return dayBefore; } - - public static long getDateMillToFormat(String day, String inFormat) throws ParseException { + + public static long getDateMillTOFormat(String day, String inFormat) throws ParseException { SimpleDateFormat sdf = new SimpleDateFormat(inFormat); Date date = sdf.parse(day); Calendar calendar = Calendar.getInstance(); calendar.setTime(date); - return calendar.getTimeInMillis()/1000L; + return calendar.getTimeInMillis()/1000; } /** @@ -407,7 +369,7 @@ public static long getFirstDay4Month(int year, int month) { cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); - firstDay = cal.getTimeInMillis() / 1000L; + firstDay = cal.getTimeInMillis() / 1000; return firstDay; } @@ -429,7 +391,7 @@ public static long getLastDay4Month(int year, int month) { cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); - lastDay = cal.getTimeInMillis() / 1000L; + lastDay = cal.getTimeInMillis() / 1000; return lastDay; } @@ -468,7 +430,7 @@ public static long getMillByOneDay() { cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); - return cal.getTimeInMillis() / 1000L; + return cal.getTimeInMillis() / 1000; } /** @@ -482,7 +444,7 @@ public static long getMillByYesDay() { cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); - return cal.getTimeInMillis() / 1000L; + return cal.getTimeInMillis() / 1000; } /** @@ -496,81 +458,81 @@ public static long getMillByLastWeekDay() { cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); - return cal.getTimeInMillis() / 1000L; + return cal.getTimeInMillis() / 1000; } - - /** - * @return long - */ + + /** + * @return long + */ public static long getMillByDay(int severalDays,String condition) { - int dateT=0; + int dateT=0; Calendar cal = Calendar.getInstance(); - if(condition==null){ - return getMillToDay(cal,dateT); - } - if("-".equals(condition)){ - dateT = (cal.get(Calendar.DATE) - severalDays); - return getMillToDay(cal,dateT); - } - if("+".equals(condition)){ - dateT = (cal.get(Calendar.DATE) + severalDays); - return getMillToDay(cal,dateT); - } - return getMillToDay(cal,dateT); - } - + if(condition==null){ + return getMillToDay(cal,dateT); + } + if(condition.equals("-")){ + dateT = (cal.get(Calendar.DATE) - severalDays); + return getMillToDay(cal,dateT); + } + if(condition.equals("+")){ + dateT = (cal.get(Calendar.DATE) + severalDays); + return getMillToDay(cal,dateT); + } + return getMillToDay(cal,dateT); + } + /** * @return long */ public static long getStampByDay(int severalDays,String condition) { - int dateT=0; - Calendar cal = Calendar.getInstance(); - if(condition==null){ - return getStampToDay(cal,dateT); - } - if("-".equals(condition)){ - dateT = (cal.get(Calendar.DATE) - severalDays); - return getStampToDay(cal,dateT); - } - if("+".equals(condition)){ - dateT = (cal.get(Calendar.DATE) + severalDays); - return getStampToDay(cal,dateT); - } - return getStampToDay(cal,dateT); + int dateT=0; + Calendar cal = Calendar.getInstance(); + if(condition==null){ + return getStampToDay(cal,dateT); + } + if(condition.equals("-")){ + dateT = (cal.get(Calendar.DATE) - severalDays); + return getStampToDay(cal,dateT); + } + if(condition.equals("+")){ + dateT = (cal.get(Calendar.DATE) + severalDays); + return getStampToDay(cal,dateT); + } + return getStampToDay(cal,dateT); } /** * @return long */ public static long getMillByDay(){ - return getMillByDay(0,null); + return getMillByDay(0,null); } - + /** * @param cal Calendar - * @param dateT Integer + * @param dateT Integer * @return long */ public static long getMillToDay(Calendar cal,int dateT){ - if(dateT!=0){ - cal.set(Calendar.DATE, dateT); - } - cal.set(Calendar.HOUR_OF_DAY, 0); - cal.set(Calendar.MINUTE, 0); - cal.set(Calendar.SECOND, 0); - cal.set(Calendar.MILLISECOND, 0); - return cal.getTimeInMillis()/1000L; - } - + if(dateT!=0){ + cal.set(Calendar.DATE, dateT); + } + cal.set(Calendar.HOUR_OF_DAY, 0); + cal.set(Calendar.MINUTE, 0); + cal.set(Calendar.SECOND, 0); + cal.set(Calendar.MILLISECOND, 0); + return cal.getTimeInMillis()/1000; + } + /** * @param cal Calendar - * @param dateT Integer + * @param dateT Integer * @return long */ public static long getStampToDay(Calendar cal,int dateT){ - if(dateT!=0){ - cal.set(Calendar.DATE, dateT); - } - return cal.getTimeInMillis(); + if(dateT!=0){ + cal.set(Calendar.DATE, dateT); + } + return cal.getTimeInMillis(); } public static String getToday() { @@ -587,12 +549,12 @@ public static String getDate(long day, String format) { if (("" + day).length() > 10) { cal.setTime(new Date(day)); } else { - cal.setTime(new Date(day * 1000L)); + cal.setTime(new Date(day * 1000)); } SimpleDateFormat sf = new SimpleDateFormat(format); return sf.format(cal.getTime()); } - + /** * * @param date @@ -602,21 +564,21 @@ public static String getDate(Date date, String format) { SimpleDateFormat sf = new SimpleDateFormat(format); return sf.format(date); } - - + + /** * * @param day * @param format * @return long - * @throws ParseException + * @throws ParseException */ public static long stringToLong(String day, String format) throws ParseException { - SimpleDateFormat dateFormat = new SimpleDateFormat(format); - long date = dateFormat.parse(day).getTime(); - return date; + SimpleDateFormat dateFormat = new SimpleDateFormat(format); + long Date = dateFormat.parse(day).getTime(); + return Date; } - + /** * @param day * @param format @@ -624,30 +586,30 @@ public static long stringToLong(String day, String format) throws ParseException * @throws ParseException */ public static Date stringToDate(String day, String format) { - try { - SimpleDateFormat dateFormat = new SimpleDateFormat(format); - Date date = dateFormat.parse(day); - return date; - } catch (ParseException e) { - return new Date(); - } + try { + SimpleDateFormat dateFormat = new SimpleDateFormat(format); + Date Date = dateFormat.parse(day); + return Date; + } catch (ParseException e) { + return new Date(); + } } - - + + /** * long型时间戳转为String型 - * + * * @param day 秒 * @return 格式化后的日期 - * @throws ParseException + * @throws ParseException */ public static String longToString(long day, String format) throws ParseException { - if (("" + day).length() <= 10){ - day=day*1000L; + if (("" + day).length() <= 10){ + day=day*1000; } - SimpleDateFormat dateFormat = new SimpleDateFormat(format); - String date = dateFormat.format(day); - return date; + SimpleDateFormat dateFormat = new SimpleDateFormat(format); + String Date = dateFormat.format(day); + return Date; } /** @@ -658,7 +620,7 @@ public static String longToString(long day, String format) throws ParseException */ public static int getMinusDate(int day, int minusDay) { Calendar cal = Calendar.getInstance(); - cal.setTime(new Date(day * 1000L)); + cal.setTime(new Date(day * 1000)); cal.set(Calendar.DATE, cal.get(Calendar.DATE) - minusDay); cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); @@ -677,39 +639,39 @@ public static long getMillByNow() { return cal.getTimeInMillis(); } - public static int getWeeksBetweenTwoDates(long startDay, long endDay) { - int week = getWeekOfYear(endDay) - getWeekOfYear(startDay) + 1; - if(week<1){ - week = getWeekOfYear(endDay) + getMaxWeekOfYear(startDay) - getWeekOfYear(startDay) + 1; - } - return week; - } + public static int getWeeksBetweenTwoDates(long startDay, long endDay) { + int week = getWeekOfYear(endDay) - getWeekOfYear(startDay) + 1; + if(week<1){ + week = getWeekOfYear(endDay) + getMaxWeekOfYear(startDay) - getWeekOfYear(startDay) + 1; + } + return week; + } - public static int getMaxWeekOfYear(long startDay) { - Calendar cal = Calendar.getInstance(); - cal.setTime(new Date(startDay * 1000L)); + public static int getMaxWeekOfYear(long startDay) { + Calendar cal = Calendar.getInstance(); + cal.setTime(new Date(startDay * 1000)); return cal.getMaximum(Calendar.WEEK_OF_YEAR); - } - - public static int getMonthsBetweenTwoDates(long startDay, long endDay) { - int month = DateUtil.getMonth(endDay) - DateUtil.getMonth(startDay) + 1; - if(month<1){ - month = getMonth(endDay) + 12 - getMonth(startDay) +1; - } - return month; - } - - public static Date parseDate(String dateStr, String pattern){ - SimpleDateFormat sdf = new SimpleDateFormat(); - sdf.applyPattern(pattern); - try { - return sdf.parse(dateStr); - } catch (ParseException e) { - return null; - } - } - - /** + } + + public static int getMonthsBetweenTwoDates(long startDay, long endDay) { + int month = DateUtil.getMonth(endDay) - DateUtil.getMonth(startDay) + 1; + if(month<1){ + month = getMonth(endDay) + 12 - getMonth(startDay) +1; + } + return month; + } + + public static Date parseDate(String dateStr, String pattern){ + SimpleDateFormat sdf = new SimpleDateFormat(); + sdf.applyPattern(pattern); + try { + return sdf.parse(dateStr); + } catch (ParseException e) { + return null; + } + } + + /** * * @param time Long 时间 * @return long @@ -720,14 +682,14 @@ public static long getMinuteStart(long time) { if (("" + time).length() > 10) { cal.setTime(new Date(time)); } else { - cal.setTime(new Date(time * 1000L)); + cal.setTime(new Date(time * 1000)); } cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); firstDay = cal.getTimeInMillis() / 1000; return firstDay; } - + /** * @param time Long * @return long @@ -743,7 +705,7 @@ public static long getHourStart(long time) { cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); cal.set(Calendar.MINUTE, 0); - firstDay = cal.getTimeInMillis() / 1000L; + firstDay = cal.getTimeInMillis() / 1000; return firstDay; } @@ -756,24 +718,24 @@ public static Date getDateByLong(long time){ date.setTime(time); return date; } - + public static Date parseDate(String dateStr, String pattern, Locale locale){ - SimpleDateFormat df = new SimpleDateFormat( - pattern, locale); - - df.setTimeZone(new SimpleTimeZone(0, "GMT")); - try { - return df.parse(dateStr); - } catch (ParseException e) { - return null; - } - } - + SimpleDateFormat df = new SimpleDateFormat( + pattern, locale); + + df.setTimeZone(new SimpleTimeZone(0, "GMT")); + try { + return df.parse(dateStr); + } catch (ParseException e) { + return null; + } + } + public static String getDate(Date date, String format, Locale locale) { - SimpleDateFormat df = new SimpleDateFormat( - format, locale); - df.setTimeZone(new SimpleTimeZone(0, "GMT")); + SimpleDateFormat df = new SimpleDateFormat( + format, locale); + df.setTimeZone(new SimpleTimeZone(0, "GMT")); return df.format(date); } @@ -781,8 +743,7 @@ public static java.sql.Timestamp columnToTimestamp(Object column) { if (column == null) { return null; } else if(column instanceof String) { - Date date = stringToDate((String) column); - return null == date ? null : new java.sql.Timestamp(date.getTime()); + return new java.sql.Timestamp(stringToDate((String)column).getTime()); } else if (column instanceof Integer) { Integer rawData = (Integer) column; return new java.sql.Timestamp(rawData.longValue()); @@ -802,49 +763,11 @@ public static java.sql.Timestamp columnToTimestamp(Object column) { } public static String dateToString(Date date) { - LocalDateTime localDateTime = dateToLocalDateTime(date); - return localDateTime.format(DATE_FORMATTER); + return dateFormatter.format(date); } public static String timestampToString(Date date) { - LocalDateTime localDateTime = dateToLocalDateTime(date); - return localDateTime.format(DATE_TIME_FORMATTER); + return datetimeFormatter.format(date); } - public static Timestamp getTimestampFromStr(String timeStr) { - if (DATETIME.matcher(timeStr).matches()) { - Instant instant = Instant.from(ISO_INSTANT.parse(timeStr)); - return new Timestamp(instant.getEpochSecond() * MILLIS_PER_SECOND); - } - Date date = stringToDate(timeStr); - return null == date ? null : new Timestamp(date.getTime()); - } - - public static java.sql.Date getDateFromStr(String dateStr) { - if (DATE.matcher(dateStr).matches()) { - Instant instant = LocalDate.parse(dateStr).atTime(LocalTime.of(0, 0, 0, 0)).toInstant(ZoneOffset.UTC); - int offset = TimeZone.getDefault().getOffset(instant.toEpochMilli()); - return new java.sql.Date(instant.toEpochMilli() - offset); - } else if (DATETIME.matcher(dateStr).matches()) { - Instant instant = Instant.from(ISO_INSTANT.parse(dateStr)); - return new java.sql.Date(instant.toEpochMilli()); - } - Date date = stringToDate(dateStr); - return null == date ? null : new java.sql.Date(date.getTime()); - } - - public static java.sql.Time getTimeFromStr(String dateStr) { - if (TIME.matcher(dateStr).matches()) { - dateStr = dateStr.substring(0,dateStr.length()-1); - Instant instant = LocalTime.parse(dateStr).atDate(LocalDate.now()).toInstant(ZoneOffset.UTC); - return new java.sql.Time(instant.toEpochMilli()); - } else if (DATETIME.matcher(dateStr).matches()) { - Instant instant = Instant.from(ISO_INSTANT.parse(dateStr)); - return new java.sql.Time(instant.toEpochMilli()); - } - Date date = stringToDate(dateStr); - return null == date ? null : new java.sql.Time(date.getTime()); - } - - } diff --git a/core/src/main/java/com/dtstack/flink/sql/util/DtFileUtils.java b/core/src/main/java/com/dtstack/flink/sql/util/DtFileUtils.java deleted file mode 100644 index eb1c974df..000000000 --- a/core/src/main/java/com/dtstack/flink/sql/util/DtFileUtils.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.util; - -import org.apache.flink.util.Preconditions; - -import java.io.File; - -/** - * @program: flinkStreamSQL - * @author: wuren - * @create: 2020/09/21 - **/ -public class DtFileUtils { - public static void checkExists(String path) { - File file = new File(path); - String errorMsg = "%s file is not exist!"; - Preconditions.checkState(file.exists(), errorMsg, path); - } -} diff --git a/core/src/main/java/com/dtstack/flink/sql/util/DtStringUtil.java b/core/src/main/java/com/dtstack/flink/sql/util/DtStringUtil.java index 222189170..862b0700e 100644 --- a/core/src/main/java/com/dtstack/flink/sql/util/DtStringUtil.java +++ b/core/src/main/java/com/dtstack/flink/sql/util/DtStringUtil.java @@ -21,18 +21,15 @@ package com.dtstack.flink.sql.util; import com.dtstack.flink.sql.enums.ColumnType; +import org.apache.commons.lang3.StringUtils; import com.google.common.base.Strings; import com.google.common.collect.Maps; -import org.apache.commons.lang3.StringUtils; -import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.ObjectMapper; -import org.apache.flink.util.Preconditions; - -import java.math.BigDecimal; +import com.fasterxml.jackson.databind.ObjectMapper; import java.sql.Timestamp; +import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -47,7 +44,8 @@ public class DtStringUtil { private static final Pattern NO_VERSION_PATTERN = Pattern.compile("([a-zA-Z]+).*"); - private static final ObjectMapper objectMapper = new ObjectMapper(); + private static ObjectMapper objectMapper = new ObjectMapper(); + /** * Split the specified string delimiter --- ignored quotes delimiter @@ -55,7 +53,7 @@ public class DtStringUtil { * @param delimiter * @return */ - public static List splitIgnoreQuota(String str, char delimiter) { + public static List splitIgnoreQuota(String str, char delimiter){ List tokensList = new ArrayList<>(); boolean inQuotes = false; boolean inSingleQuotes = false; @@ -102,110 +100,12 @@ public static List splitIgnoreQuota(String str, char delimiter) { return tokensList; } - public static List splitField(String str) { - final char delimiter = ','; - List tokensList = new ArrayList<>(); - boolean inQuotes = false; - boolean inSingleQuotes = false; - int bracketLeftNum = 0; - StringBuilder b = new StringBuilder(); - char[] chars = str.toCharArray(); - int idx = 0; - for (char c : chars) { - char flag = 0; - if (idx > 0) { - flag = chars[idx - 1]; - } - if (c == delimiter) { - if (inQuotes) { - b.append(c); - } else if (inSingleQuotes) { - b.append(c); - } else if (bracketLeftNum > 0) { - b.append(c); - } else { - tokensList.add(b.toString()); - b = new StringBuilder(); - } - } else if (c == '\"' && '\\' != flag && !inSingleQuotes) { - inQuotes = !inQuotes; - b.append(c); - } else if (c == '\'' && '\\' != flag && !inQuotes) { - inSingleQuotes = !inSingleQuotes; - b.append(c); - } else if (c == '(' && !inSingleQuotes && !inQuotes) { - bracketLeftNum++; - b.append(c); - } else if (c == ')' && !inSingleQuotes && !inQuotes) { - bracketLeftNum--; - b.append(c); - } else if (c == '<' && !inSingleQuotes && !inQuotes) { - bracketLeftNum++; - b.append(c); - } else if (c == '>' && !inSingleQuotes && !inQuotes) { - bracketLeftNum--; - b.append(c); - } else { - b.append(c); - } - idx++; - } - - tokensList.add(b.toString()); - - return tokensList; - } public static String replaceIgnoreQuota(String str, String oriStr, String replaceStr){ String splitPatternStr = oriStr + "(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)(?=(?:[^']*'[^']*')*[^']*$)"; return str.replaceAll(splitPatternStr, replaceStr); } - /** - * 处理 sql 中 "--" 注释,而不删除引号内的内容 - * - * @param sql 解析出来的 sql - * @return 返回无注释内容的 sql - */ - public static String dealSqlComment(String sql) { - boolean inQuotes = false; - boolean inSingleQuotes = false; - StringBuilder b = new StringBuilder(sql.length()); - char[] chars = sql.toCharArray(); - for (int index = 0; index < chars.length; index ++) { - StringBuilder tempSb = new StringBuilder(2); - if (index >= 1) { - tempSb.append(chars[index - 1]); - tempSb.append(chars[index]); - } - - if ("--".equals(tempSb.toString())) { - if (inQuotes) { - b.append(chars[index]); - } else if (inSingleQuotes) { - b.append(chars[index]); - } else { - b.deleteCharAt(b.length() - 1); - while (chars[index] != '\n') { - // 判断注释内容是不是行尾或者 sql 的最后一行 - if (index == chars.length - 1) { - break; - } - index++; - } - } - } else if (chars[index] == '\"' && '\\' != chars[index] && !inSingleQuotes) { - inQuotes = !inQuotes; - b.append(chars[index]); - } else if (chars[index] == '\'' && '\\' != chars[index] && !inQuotes) { - inSingleQuotes = !inSingleQuotes; - b.append(chars[index]); - } else { - b.append(chars[index]); - } - } - return b.toString(); - } public static String col2string(Object column, String type) { String rowData = column.toString(); @@ -244,9 +144,6 @@ public static String col2string(Object column, String type) { case DATE: result = DateUtil.dateToString((java.util.Date)column); break; - case TIME: - result = DateUtil.getTimeFromStr(String.valueOf(column)); - break; case TIMESTAMP: result = DateUtil.timestampToString((java.util.Date)column); break; @@ -256,12 +153,10 @@ public static String col2string(Object column, String type) { return result.toString(); } - public static String getPluginTypeWithoutVersion(String engineType) { - Preconditions.checkNotNull(engineType, "type can't be null!"); + public static String getPluginTypeWithoutVersion(String engineType){ Matcher matcher = NO_VERSION_PATTERN.matcher(engineType); - - if (!matcher.find()) { + if(!matcher.find()){ return engineType; } @@ -290,9 +185,9 @@ public static String addJdbcParam(String dbUrl, Map addParams, b Map params = Maps.newHashMap(); if(splits.length > 1){ String existsParamStr = splits[1]; - String[] existsParams = StringUtils.split(existsParamStr, "&"); + String[] existsParams = existsParamStr.split("&"); for(String oneParam : existsParams){ - String[] kv = StringUtils.split(oneParam, "="); + String[] kv = oneParam.split("="); if(kv.length != 2){ throw new RuntimeException("illegal dbUrl:" + dbUrl); } @@ -324,14 +219,14 @@ public static String addJdbcParam(String dbUrl, Map addParams, b return preStr + "?" + sb.toString(); } - public static boolean isJson(String str) { + public static boolean isJosn(String str){ boolean flag = false; - if (StringUtils.isNotBlank(str)) { + if(StringUtils.isNotBlank(str)){ try { - objectMapper.readValue(str, Map.class); + objectMapper.readValue(str,Map.class); flag = true; } catch (Throwable e) { - flag = false; + flag=false; } } return flag; @@ -366,42 +261,14 @@ public static String firstUpperCase(String str) { } public static String getTableFullPath(String schema, String tableName) { - String[] tableInfoSplit = StringUtils.split(tableName, "."); - //表明表信息带了schema - if(tableInfoSplit.length == 2){ - schema = tableInfoSplit[0]; - tableName = tableInfoSplit[1]; - } - - //清理首个字符" 和最后字符 " - schema = rmStrQuote(schema); - tableName = rmStrQuote(tableName); - if (StringUtils.isEmpty(schema)){ return addQuoteForStr(tableName); } - - return addQuoteForStr(schema) + "." + addQuoteForStr(tableName); + String schemaAndTabName = addQuoteForStr(schema) + "." + addQuoteForStr(tableName); + return schemaAndTabName; } - /** - * 清理首个字符" 和最后字符 " - */ - public static String rmStrQuote(String str){ - if(StringUtils.isEmpty(str)){ - return str; - } - - if(str.startsWith("\"")){ - str = str.substring(1); - } - - if(str.endsWith("\"")){ - str = str.substring(0, str.length()-1); - } - return str; - } public static String addQuoteForStr(String column) { return getStartQuote() + column + getEndQuote(); @@ -414,19 +281,4 @@ public static String getStartQuote() { public static String getEndQuote() { return "\""; } - - public static String removeStartAndEndQuota(String str) { - String removeStart = StringUtils.removeStart(str, "'"); - return StringUtils.removeEnd(removeStart, "'"); - } - - /** - * 判断当前对象是null 还是空格 - * - * @param obj 需要判断的对象 - * @return 返回true 如果对象是空格或者为null - */ - public static boolean isEmptyOrNull(Object obj) { - return Objects.isNull(obj) || obj.toString().isEmpty(); - } } diff --git a/core/src/main/java/com/dtstack/flink/sql/util/FieldReplaceUtil.java b/core/src/main/java/com/dtstack/flink/sql/util/FieldReplaceUtil.java deleted file mode 100644 index 3856d777e..000000000 --- a/core/src/main/java/com/dtstack/flink/sql/util/FieldReplaceUtil.java +++ /dev/null @@ -1,355 +0,0 @@ -package com.dtstack.flink.sql.util; - -import com.dtstack.flink.sql.side.FieldReplaceInfo; -import com.google.common.collect.Lists; -import org.apache.calcite.sql.*; -import org.apache.calcite.sql.fun.SqlCase; -import org.apache.calcite.sql.parser.SqlParserPos; -import org.apache.commons.collections.CollectionUtils; - -import java.util.Collection; -import java.util.List; -import java.util.Map; - -import static org.apache.calcite.sql.SqlKind.*; - -/** - * 替换 字段 - */ -public class FieldReplaceUtil { - - /** - * 需要考虑更多的情况 - */ - public static void replaceFieldName(SqlNode sqlNode, - String oldTbName, - String newTbName, - Map mappingField) { - SqlKind sqlKind = sqlNode.getKind(); - switch (sqlKind) { - case INSERT: - SqlNode sqlSource = ((SqlInsert) sqlNode).getSource(); - replaceFieldName(sqlSource, oldTbName, newTbName, mappingField); - break; - case AS: - SqlNode asNode = ((SqlBasicCall) sqlNode).getOperands()[0]; - replaceFieldName(asNode, oldTbName, newTbName, mappingField); - break; - case SELECT: - SqlSelect sqlSelect = (SqlSelect) sqlNode; - SqlNodeList sqlSelectList = sqlSelect.getSelectList(); - SqlNode whereNode = sqlSelect.getWhere(); - SqlNodeList sqlGroup = sqlSelect.getGroup(); - - //TODO 抽取,暂时使用使用单个join条件作为测试 - if(sqlSelect.getFrom().getKind().equals(JOIN)){ - SqlJoin joinNode = (SqlJoin) sqlSelect.getFrom(); - SqlNode joinCondition = joinNode.getCondition(); - replaceFieldName(((SqlBasicCall)joinCondition).operands[0], oldTbName, newTbName, mappingField); - replaceFieldName(((SqlBasicCall)joinCondition).operands[1], oldTbName, newTbName, mappingField); - } - - //TODO 暂时不处理having - SqlNode sqlHaving = sqlSelect.getHaving(); - - List newSelectNodeList = Lists.newArrayList(); - for( int i=0; i replaceNodeList = replaceSelectStarFieldName(selectNode, replaceInfo); - //newSelectNodeList.addAll(replaceNodeList); - throw new RuntimeException("not support table.* now"); - } - - SqlNode replaceNode = replaceSelectFieldName(selectNode, oldTbName, newTbName, mappingField); - if(replaceNode == null){ - continue; - } - - newSelectNodeList.add(replaceNode); - } - - SqlNodeList newSelectList = new SqlNodeList(newSelectNodeList, sqlSelectList.getParserPosition()); - sqlSelect.setSelectList(newSelectList); - - //where - if(whereNode != null){ - SqlNode[] sqlNodeList = ((SqlBasicCall)whereNode).getOperands(); - for(int i =0; i mappingField) { - if(orderNode.getKind() == IDENTIFIER){ - return createNewIdentify((SqlIdentifier) orderNode, oldTbName, newTbName, mappingField); - } else if (orderNode instanceof SqlBasicCall) { - SqlBasicCall sqlBasicCall = (SqlBasicCall) orderNode; - for(int i=0; i mappingField){ - if(groupNode.getKind() == IDENTIFIER){ - return createNewIdentify((SqlIdentifier) groupNode, oldTbName, newTbName, mappingField); - }else if(groupNode instanceof SqlBasicCall){ - SqlBasicCall sqlBasicCall = (SqlBasicCall) groupNode; - for(int i=0; i mappingField){ - - if (sqlIdentifier.names.size() == 1) { - return sqlIdentifier; - } - - String tableName = sqlIdentifier.names.get(0); - String fieldName = sqlIdentifier.names.get(1); - if(!tableName.equalsIgnoreCase(oldTbName)){ - return sqlIdentifier; - } - - sqlIdentifier = sqlIdentifier.setName(0, newTbName); - - String mappingFieldName = mappingField.get(fieldName); - if(mappingFieldName == null){ - return sqlIdentifier; - } - sqlIdentifier = sqlIdentifier.setName(1, mappingFieldName); - return sqlIdentifier; - } - - public static boolean filterNodeWithTargetName(SqlNode sqlNode, String targetTableName) { - - SqlKind sqlKind = sqlNode.getKind(); - switch (sqlKind){ - case SELECT: - SqlNode fromNode = ((SqlSelect)sqlNode).getFrom(); - if(fromNode.getKind() == AS && ((SqlBasicCall)fromNode).getOperands()[0].getKind() == IDENTIFIER){ - if(((SqlBasicCall)fromNode).getOperands()[0].toString().equalsIgnoreCase(targetTableName)){ - return true; - }else{ - return false; - } - }else{ - return filterNodeWithTargetName(fromNode, targetTableName); - } - case AS: - SqlNode aliasName = ((SqlBasicCall)sqlNode).getOperands()[1]; - return aliasName.toString().equalsIgnoreCase(targetTableName); - case JOIN: - SqlNode leftNode = ((SqlJoin)sqlNode).getLeft(); - SqlNode rightNode = ((SqlJoin)sqlNode).getRight(); - boolean leftReturn = filterNodeWithTargetName(leftNode, targetTableName); - boolean rightReturn = filterNodeWithTargetName(rightNode, targetTableName); - - return leftReturn || rightReturn; - - default: - return false; - } - } - - public static SqlNode replaceSelectFieldName(SqlNode selectNode, - String oldTbName, - String newTbName, - Map mappingField) { - - if (selectNode.getKind() == AS) { - SqlNode leftNode = ((SqlBasicCall) selectNode).getOperands()[0]; - SqlNode replaceNode = replaceSelectFieldName(leftNode, oldTbName, newTbName, mappingField); - if (replaceNode != null) { - ((SqlBasicCall) selectNode).getOperands()[0] = replaceNode; - } - - return selectNode; - }else if(selectNode.getKind() == IDENTIFIER){ - return createNewIdentify((SqlIdentifier) selectNode, oldTbName, newTbName, mappingField); - }else if(selectNode.getKind() == LITERAL || selectNode.getKind() == LITERAL_CHAIN){//字面含义 - return selectNode; - }else if(AGGREGATE.contains(selectNode.getKind()) - || AVG_AGG_FUNCTIONS.contains(selectNode.getKind()) - || COMPARISON.contains(selectNode.getKind()) - || FUNCTION.contains(selectNode.getKind()) - || COVAR_AVG_AGG_FUNCTIONS.contains(selectNode.getKind()) - || BINARY_ARITHMETIC.contains(selectNode.getKind()) - || BINARY_COMPARISON.contains(selectNode.getKind()) - || selectNode.getKind() == NOT_IN - || selectNode.getKind() == OR - || selectNode.getKind() == AND - || selectNode.getKind() == TUMBLE - || selectNode.getKind() == TUMBLE_START - || selectNode.getKind() == TUMBLE_END - || selectNode.getKind() == SESSION - || selectNode.getKind() == SESSION_START - || selectNode.getKind() == SESSION_END - || selectNode.getKind() == HOP - || selectNode.getKind() == HOP_START - || selectNode.getKind() == HOP_END - || selectNode.getKind() == BETWEEN - || selectNode.getKind() == IS_NULL - || selectNode.getKind() == IS_NOT_NULL - || selectNode.getKind() == CONTAINS - || selectNode.getKind() == TIMESTAMP_ADD - || selectNode.getKind() == TIMESTAMP_DIFF - || selectNode.getKind() == LIKE - || selectNode.getKind() == COALESCE - ){ - SqlBasicCall sqlBasicCall = (SqlBasicCall) selectNode; - for(int i=0; i replaceSelectStarFieldName(SqlNode selectNode, FieldReplaceInfo replaceInfo){ - SqlIdentifier sqlIdentifier = (SqlIdentifier) selectNode; - List sqlNodes = Lists.newArrayList(); - if(sqlIdentifier.isStar()){//处理 [* or table.*] - int identifierSize = sqlIdentifier.names.size(); - Collection columns = null; - if(identifierSize == 1){ - columns = replaceInfo.getMappingTable().values(); - }else{ - columns = replaceInfo.getMappingTable().row(sqlIdentifier.names.get(0)).values(); - } - - for(String colAlias : columns){ - SqlParserPos sqlParserPos = new SqlParserPos(0, 0); - List columnInfo = Lists.newArrayList(); - columnInfo.add(replaceInfo.getTargetTableAlias()); - columnInfo.add(colAlias); - SqlIdentifier sqlIdentifierAlias = new SqlIdentifier(columnInfo, sqlParserPos); - sqlNodes.add(sqlIdentifierAlias); - } - - return sqlNodes; - }else{ - throw new RuntimeException("is not a star select field." + selectNode); - } - } - -} diff --git a/core/src/main/java/com/dtstack/flink/sql/util/FlinkUtil.java b/core/src/main/java/com/dtstack/flink/sql/util/FlinkUtil.java new file mode 100644 index 000000000..5811105e4 --- /dev/null +++ b/core/src/main/java/com/dtstack/flink/sql/util/FlinkUtil.java @@ -0,0 +1,312 @@ +/* + * 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 com.dtstack.flink.sql.util; + + +import com.dtstack.flink.sql.classloader.ClassLoaderManager; +import com.dtstack.flink.sql.constrant.ConfigConstrant; +import org.apache.commons.lang3.StringUtils; +import org.apache.flink.api.common.typeinfo.TypeInformation; +import org.apache.flink.runtime.state.filesystem.FsStateBackend; +import org.apache.flink.streaming.api.CheckpointingMode; +import org.apache.flink.streaming.api.TimeCharacteristic; +import org.apache.flink.streaming.api.environment.CheckpointConfig; +import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; +import org.apache.flink.table.api.TableEnvironment; +import org.apache.flink.table.api.java.BatchTableEnvironment; +import org.apache.flink.table.api.java.StreamTableEnvironment; +import org.apache.flink.table.functions.ScalarFunction; +import org.apache.flink.table.functions.TableFunction; +import org.apache.flink.table.functions.AggregateFunction; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.List; +import java.util.Properties; + +/** + * Reason: + * Date: 2017/2/21 + * Company: www.dtstack.com + * @author xuchao + */ + +public class FlinkUtil { + + private static final Logger logger = LoggerFactory.getLogger(FlinkUtil.class); + + /** + * 开启checkpoint + * @param env + * @throws IOException + */ + public static void openCheckpoint(StreamExecutionEnvironment env, Properties properties) throws IOException { + + if(properties == null){ + return; + } + + //设置了时间间隔才表明开启了checkpoint + if(properties.getProperty(ConfigConstrant.SQL_CHECKPOINT_INTERVAL_KEY) == null && properties.getProperty(ConfigConstrant.FLINK_CHECKPOINT_INTERVAL_KEY) == null){ + return; + }else{ + Long sql_interval = Long.valueOf(properties.getProperty(ConfigConstrant.SQL_CHECKPOINT_INTERVAL_KEY,"0")); + Long flink_interval = Long.valueOf(properties.getProperty(ConfigConstrant.FLINK_CHECKPOINT_INTERVAL_KEY, "0")); + long checkpointInterval = Math.max(sql_interval, flink_interval); + //start checkpoint every ${interval} + env.enableCheckpointing(checkpointInterval); + } + + String checkMode = properties.getProperty(ConfigConstrant.FLINK_CHECKPOINT_MODE_KEY); + if(checkMode != null){ + if(checkMode.equalsIgnoreCase("EXACTLY_ONCE")){ + env.getCheckpointConfig().setCheckpointingMode(CheckpointingMode.EXACTLY_ONCE); + }else if(checkMode.equalsIgnoreCase("AT_LEAST_ONCE")){ + env.getCheckpointConfig().setCheckpointingMode(CheckpointingMode.AT_LEAST_ONCE); + }else{ + throw new RuntimeException("not support of FLINK_CHECKPOINT_MODE_KEY :" + checkMode); + } + } + + String checkpointTimeoutStr = properties.getProperty(ConfigConstrant.FLINK_CHECKPOINT_TIMEOUT_KEY); + if(checkpointTimeoutStr != null){ + Long checkpointTimeout = Long.valueOf(checkpointTimeoutStr); + //checkpoints have to complete within one min,or are discard + env.getCheckpointConfig().setCheckpointTimeout(checkpointTimeout); + } + + String maxConcurrCheckpointsStr = properties.getProperty(ConfigConstrant.FLINK_MAXCONCURRENTCHECKPOINTS_KEY); + if(maxConcurrCheckpointsStr != null){ + Integer maxConcurrCheckpoints = Integer.valueOf(maxConcurrCheckpointsStr); + //allow only one checkpoint to be int porgress at the same time + env.getCheckpointConfig().setMaxConcurrentCheckpoints(maxConcurrCheckpoints); + } + + Boolean sqlCleanMode = MathUtil.getBoolean(properties.getProperty(ConfigConstrant.SQL_CHECKPOINT_CLEANUPMODE_KEY), false); + Boolean flinkCleanMode = MathUtil.getBoolean(properties.getProperty(ConfigConstrant.FLINK_CHECKPOINT_CLEANUPMODE_KEY), false); + + String cleanupModeStr = "false"; + if (sqlCleanMode || flinkCleanMode ){ + cleanupModeStr = "true"; + } + + if ("true".equalsIgnoreCase(cleanupModeStr)){ + env.getCheckpointConfig().enableExternalizedCheckpoints( + CheckpointConfig.ExternalizedCheckpointCleanup.DELETE_ON_CANCELLATION); + } else if("false".equalsIgnoreCase(cleanupModeStr) || cleanupModeStr == null){ + env.getCheckpointConfig().enableExternalizedCheckpoints( + CheckpointConfig.ExternalizedCheckpointCleanup.RETAIN_ON_CANCELLATION); + } else{ + throw new RuntimeException("not support value of cleanup mode :" + cleanupModeStr); + } + + String backendPath = properties.getProperty(ConfigConstrant.FLINK_CHECKPOINT_DATAURI_KEY); + if(backendPath != null){ + //set checkpoint save path on file system, 根据实际的需求设定文件路径,hdfs://, file:// + env.setStateBackend(new FsStateBackend(backendPath)); + } + + } + + /** + * #ProcessingTime(默认),IngestionTime,EventTime + * @param env + * @param properties + */ + public static void setStreamTimeCharacteristic(StreamExecutionEnvironment env, Properties properties){ + if(!properties.containsKey(ConfigConstrant.FLINK_TIME_CHARACTERISTIC_KEY)){ + //走默认值 + return; + } + + String characteristicStr = properties.getProperty(ConfigConstrant.FLINK_TIME_CHARACTERISTIC_KEY); + Boolean flag = false; + for(TimeCharacteristic tmp : TimeCharacteristic.values()){ + if(characteristicStr.equalsIgnoreCase(tmp.toString())){ + env.setStreamTimeCharacteristic(tmp); + flag = true; + break; + } + } + + if(!flag){ + throw new RuntimeException("illegal property :" + ConfigConstrant.FLINK_TIME_CHARACTERISTIC_KEY); + } + } + + + /** + * TABLE|SCALA|AGGREGATE + * 注册UDF到table env + */ + public static void registerUDF(String type, String classPath, String funcName, TableEnvironment tableEnv, ClassLoader classLoader){ + if("SCALA".equalsIgnoreCase(type)){ + registerScalaUDF(classPath, funcName, tableEnv, classLoader); + }else if("TABLE".equalsIgnoreCase(type)){ + registerTableUDF(classPath, funcName, tableEnv, classLoader); + }else if("AGGREGATE".equalsIgnoreCase(type)){ + registerAggregateUDF(classPath, funcName, tableEnv, classLoader); + }else{ + throw new RuntimeException("not support of UDF which is not in (TABLE, SCALA, AGGREGATE)"); + } + + } + + /** + * 注册自定义方法到env上 + * @param classPath + * @param funcName + * @param tableEnv + */ + public static void registerScalaUDF(String classPath, String funcName, TableEnvironment tableEnv, ClassLoader classLoader){ + try{ + ScalarFunction udfFunc = Class.forName(classPath, false, classLoader) + .asSubclass(ScalarFunction.class).newInstance(); + tableEnv.registerFunction(funcName, udfFunc); + logger.info("register scala function:{} success.", funcName); + }catch (Exception e){ + logger.error("", e); + throw new RuntimeException("register UDF exception:", e); + } + } + + /** + * 注册自定义TABLEFFUNC方法到env上 + * + * @param classPath + * @param funcName + * @param tableEnv + */ + public static void registerTableUDF(String classPath, String funcName, TableEnvironment tableEnv, ClassLoader classLoader){ + try { + TableFunction udfFunc = Class.forName(classPath, false, classLoader) + .asSubclass(TableFunction.class).newInstance(); + if(tableEnv instanceof StreamTableEnvironment){ + ((StreamTableEnvironment)tableEnv).registerFunction(funcName, udfFunc); + }else if(tableEnv instanceof BatchTableEnvironment){ + ((BatchTableEnvironment)tableEnv).registerFunction(funcName, udfFunc); + }else{ + throw new RuntimeException("no support tableEnvironment class for " + tableEnv.getClass().getName()); + } + + logger.info("register table function:{} success.", funcName); + }catch (Exception e){ + logger.error("", e); + throw new RuntimeException("register Table UDF exception:", e); + } + } + + /** + * 注册自定义Aggregate FUNC方法到env上 + * + * @param classPath + * @param funcName + * @param tableEnv + */ + public static void registerAggregateUDF(String classPath, String funcName, TableEnvironment tableEnv, ClassLoader classLoader) { + try { + AggregateFunction udfFunc = Class.forName(classPath, false, classLoader) + .asSubclass(AggregateFunction.class).newInstance(); + if (tableEnv instanceof StreamTableEnvironment) { + ((StreamTableEnvironment) tableEnv).registerFunction(funcName, udfFunc); + } else if (tableEnv instanceof BatchTableEnvironment) { + ((BatchTableEnvironment) tableEnv).registerFunction(funcName, udfFunc); + } else { + throw new RuntimeException("no support tableEnvironment class for " + tableEnv.getClass().getName()); + } + + logger.info("register Aggregate function:{} success.", funcName); + } catch (Exception e) { + logger.error("", e); + throw new RuntimeException("register Aggregate UDF exception:", e); + } + } + + /** + * + * FIXME 仅针对sql执行方式,暂时未找到区分设置source,transform,sink 并行度的方式 + * 设置job运行的并行度 + * @param properties + */ + public static int getEnvParallelism(Properties properties){ + String parallelismStr = properties.getProperty(ConfigConstrant.SQL_ENV_PARALLELISM); + return StringUtils.isNotBlank(parallelismStr)?Integer.parseInt(parallelismStr):1; + } + + + /** + * 最大并发度 + * @param properties + * @return + */ + public static int getMaxEnvParallelism(Properties properties){ + String parallelismStr = properties.getProperty(ConfigConstrant.SQL_MAX_ENV_PARALLELISM); + return StringUtils.isNotBlank(parallelismStr)?Integer.parseInt(parallelismStr):0; + } + + /** + * + * @param properties + * @return + */ + public static long getBufferTimeoutMillis(Properties properties){ + String mills = properties.getProperty(ConfigConstrant.SQL_BUFFER_TIMEOUT_MILLIS); + return StringUtils.isNotBlank(mills)?Long.parseLong(mills):0L; + } + + public static URLClassLoader loadExtraJar(List jarURLList, URLClassLoader classLoader) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { + for(URL url : jarURLList){ + if(url.toString().endsWith(".jar")){ + urlClassLoaderAddUrl(classLoader, url); + } + } + + return classLoader; + } + + private static void urlClassLoaderAddUrl(URLClassLoader classLoader, URL url) throws InvocationTargetException, IllegalAccessException { + Method method = ReflectionUtils.getDeclaredMethod(classLoader, "addURL", URL.class); + + if(method == null){ + throw new RuntimeException("can't not find declared method addURL, curr classLoader is " + classLoader.getClass()); + } + + method.setAccessible(true); + method.invoke(classLoader, url); + } + + + public static TypeInformation[] transformTypes(Class[] fieldTypes){ + TypeInformation[] types = new TypeInformation[fieldTypes.length]; + for(int i=0; i checkProperties); +import java.sql.DriverManager; + +public class JDBCUtils { + + private static final Logger LOG = LoggerFactory.getLogger(ClassUtil.class); + + public final static String lock_str = "jdbc_lock_str"; + + public static void forName(String clazz, ClassLoader classLoader) { + synchronized (lock_str){ + try { + Class.forName(clazz, true, classLoader); + DriverManager.setLoginTimeout(10); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + + + public synchronized static void forName(String clazz) { + try { + Class driverClass = Class.forName(clazz); + driverClass.newInstance(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } } diff --git a/core/src/main/java/com/dtstack/flink/sql/util/KrbUtils.java b/core/src/main/java/com/dtstack/flink/sql/util/KrbUtils.java deleted file mode 100644 index b1d0f8888..000000000 --- a/core/src/main/java/com/dtstack/flink/sql/util/KrbUtils.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.util; - -import com.esotericsoftware.minlog.Log; -import org.apache.flink.runtime.security.DynamicConfiguration; -import org.apache.flink.runtime.security.KerberosUtils; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.security.UserGroupInformation; -import org.apache.hadoop.security.authentication.util.KerberosName; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import sun.security.krb5.Config; -import sun.security.krb5.KrbException; - -import javax.security.auth.login.AppConfigurationEntry; -import java.io.IOException; - -/** - * @program: flinkStreamSQL - * @author: wuren - * @create: 2020/09/14 - **/ -public class KrbUtils { - - private static final Logger LOG = LoggerFactory.getLogger(KrbUtils.class); - - public static final String KRB5_CONF_KEY = "java.security.krb5.conf"; - public static final String HADOOP_AUTH_KEY = "hadoop.security.authentication"; - public static final String KRB_STR = "Kerberos"; -// public static final String FALSE_STR = "false"; -// public static final String SUBJECT_ONLY_KEY = "javax.security.auth.useSubjectCredsOnly"; - - public static UserGroupInformation loginAndReturnUgi(String principal, String keytabPath, String krb5confPath) throws IOException { - LOG.info("Kerberos login with principal: {} and keytab: {}", principal, keytabPath); - System.setProperty(KRB5_CONF_KEY, krb5confPath); - // 不刷新会读/etc/krb5.conf - try { - Config.refresh(); - KerberosName.resetDefaultRealm(); - } catch (KrbException e) { - LOG.warn("resetting default realm failed, current default realm will still be used.", e); - } - // TODO 尚未探索出此选项的意义,以后研究明白方可打开 -// System.setProperty(SUBJECT_ONLY_KEY, FALSE_STR); - Configuration configuration = new Configuration(); - configuration.set(HADOOP_AUTH_KEY , KRB_STR); - UserGroupInformation.setConfiguration(configuration); - return UserGroupInformation.loginUserFromKeytabAndReturnUGI(principal, keytabPath); - } - - public synchronized static void appendJaasConf(String name, String keytab, String principal) { - javax.security.auth.login.Configuration priorConfig = javax.security.auth.login.Configuration.getConfiguration(); - // construct a dynamic JAAS configuration - DynamicConfiguration currentConfig = new DynamicConfiguration(priorConfig); - // wire up the configured JAAS login contexts to use the krb5 entries - AppConfigurationEntry krb5Entry = KerberosUtils.keytabEntry(keytab, principal); - currentConfig.addAppConfigurationEntry(name, krb5Entry); - javax.security.auth.login.Configuration.setConfiguration(currentConfig); - } -} diff --git a/core/src/main/java/com/dtstack/flink/sql/util/MathUtil.java b/core/src/main/java/com/dtstack/flink/sql/util/MathUtil.java index cf9a0a701..37b06c8b8 100644 --- a/core/src/main/java/com/dtstack/flink/sql/util/MathUtil.java +++ b/core/src/main/java/com/dtstack/flink/sql/util/MathUtil.java @@ -16,265 +16,87 @@ * limitations under the License. */ + package com.dtstack.flink.sql.util; import java.math.BigDecimal; -import java.math.BigInteger; -import java.sql.Date; -import java.sql.Time; -import java.sql.Timestamp; /** - * Convert val to specified numeric type * Date: 2017/4/21 * Company: www.dtstack.com * @author xuchao */ public class MathUtil { - public static Long getLongVal(Object obj) { - if (obj == null) { + + public static Long getLongVal(Object obj){ + if(obj == null){ return null; } - if (obj instanceof String) { + if(obj instanceof String){ return Long.valueOf((String) obj); - } else if (obj instanceof Long) { + }else if(obj instanceof Long){ return (Long) obj; - } else if (obj instanceof Integer) { + }else if(obj instanceof Integer){ return Long.valueOf(obj.toString()); - } else if (obj instanceof BigDecimal) { - return ((BigDecimal) obj).longValue(); - } else if (obj instanceof BigInteger) { - return ((BigInteger) obj).longValue(); - } - throw new RuntimeException("not support type of " + obj.getClass() + " convert to Long."); - } - - public static Long getLongVal(Object obj, long defaultVal) { - if (obj == null) { - return defaultVal; } - return getLongVal(obj); + throw new RuntimeException("not support type of " + obj.getClass() + " convert to Long." ); } - public static Integer getIntegerVal(Object obj) { - if (obj == null) { + public static Integer getIntegerVal(Object obj){ + if(obj == null){ return null; } - if (obj instanceof String) { + if(obj instanceof String){ return Integer.valueOf((String) obj); - } else if (obj instanceof Integer) { + } else if (obj instanceof Integer){ return (Integer) obj; - } else if (obj instanceof Long) { - return ((Long) obj).intValue(); - } else if (obj instanceof Double) { - return ((Double) obj).intValue(); - } else if (obj instanceof BigDecimal) { - return ((BigDecimal) obj).intValue(); - } else if (obj instanceof BigInteger) { - return ((BigInteger) obj).intValue(); - } - - throw new RuntimeException("not support type of " + obj.getClass() + " convert to Integer."); - } - - public static Integer getIntegerVal(Object obj, int defaultVal) { - if (obj == null) { - return defaultVal; + } else if (obj instanceof Long){ + return ((Long)obj).intValue(); + } else if(obj instanceof Double){ + return ((Double)obj).intValue(); + } else if(obj instanceof BigDecimal){ + return ((BigDecimal)obj).intValue(); } - return getIntegerVal(obj); + throw new RuntimeException("not support type of " + obj.getClass() + " convert to Integer." ); } - public static Float getFloatVal(Object obj) { - if (obj == null) { - return null; - } - - if (obj instanceof String) { - return Float.valueOf((String) obj); - } else if (obj instanceof Float) { - return (Float) obj; - } else if (obj instanceof BigDecimal) { - return ((BigDecimal) obj).floatValue(); - } - - throw new RuntimeException("not support type of " + obj.getClass() + " convert to Float."); - } - - public static Float getFloatVal(Object obj, float defaultVal) { - if (obj == null) { + public static Boolean getBoolean(Object obj, boolean defaultVal){ + if(obj == null){ return defaultVal; } - return getFloatVal(obj); - } - - public static Double getDoubleVal(Object obj) { - if (obj == null) { - return null; - } - - if (obj instanceof String) { - return Double.valueOf((String) obj); - } else if (obj instanceof Float) { - return ((Float) obj).doubleValue(); - } else if (obj instanceof Double) { - return (Double) obj; - } else if (obj instanceof BigDecimal) { - return ((BigDecimal) obj).doubleValue(); - } else if (obj instanceof Integer) { - return ((Integer) obj).doubleValue(); - } else if (obj instanceof BigInteger) { - return ((BigInteger) obj).doubleValue(); - } - - throw new RuntimeException("not support type of " + obj.getClass() + " convert to Double."); - } - - public static Double getDoubleVal(Object obj, double defaultVal) { - if (obj == null) { - return defaultVal; - } - - return getDoubleVal(obj); + return getBoolean(obj); } - - public static Boolean getBoolean(Object obj) { - if (obj == null) { + public static Boolean getBoolean(Object obj){ + if(obj == null){ return null; } - if (obj instanceof String) { + if(obj instanceof String){ return Boolean.valueOf((String) obj); - } else if (obj instanceof Boolean) { + }else if(obj instanceof Boolean){ return (Boolean) obj; } - throw new RuntimeException("not support type of " + obj.getClass() + " convert to Boolean."); + throw new RuntimeException("not support type of " + obj.getClass() + " convert to Boolean." ); } - public static Boolean getBoolean(Object obj, boolean defaultVal) { - if (obj == null) { - return defaultVal; - } - - return getBoolean(obj); - } - - public static String getString(Object obj) { - if (obj == null) { + public static String getString(Object obj){ + if(obj == null){ return null; } - if (obj instanceof String) { + if(obj instanceof String){ return (String) obj; + }else { + return obj.toString(); } - - return obj.toString(); - } - - public static Byte getByte(Object obj) { - if (obj == null) { - return null; - } - - if (obj instanceof String) { - return Byte.valueOf((String) obj); - } else if (obj instanceof Byte) { - return (Byte) obj; - } - - throw new RuntimeException("not support type of " + obj.getClass() + " convert to Byte."); - } - - public static Short getShort(Object obj) { - if (obj == null) { - return null; - } - - if (obj instanceof String) { - return Short.valueOf((String) obj); - } else if (obj instanceof Short) { - return (Short) obj; - } - - throw new RuntimeException("not support type of " + obj.getClass() + " convert to Short."); - } - - public static BigDecimal getBigDecimal(Object obj) { - if (obj == null) { - return null; - } - if (obj instanceof String) { - return new BigDecimal((String) obj); - } else if (obj instanceof BigDecimal) { - return (BigDecimal) obj; - } else if (obj instanceof BigInteger) { - return new BigDecimal((BigInteger) obj); - } else if (obj instanceof Number) { - return BigDecimal.valueOf(((Number) obj).doubleValue()); - } - throw new RuntimeException("not support type of " + obj.getClass() + " convert to BigDecimal."); - } - - public static Date getDate(Object obj) { - if (obj == null) { - return null; - } - if (obj instanceof String) { - return DateUtil.getDateFromStr((String) obj); - } else if (obj instanceof Timestamp) { - return new Date(((Timestamp) obj).getTime()); - } else if (obj instanceof Date) { - return (Date) obj; - } - throw new RuntimeException("not support type of " + obj.getClass() + " convert to Date."); - } - - public static Time getTime(Object obj) { - if (obj == null) { - return null; - } - if (obj instanceof String) { - return DateUtil.getTimeFromStr((String) obj); - } else if (obj instanceof Timestamp) { - return new Time(((Timestamp) obj).getTime()); - } else if (obj instanceof Time) { - return (Time) obj; - } - throw new RuntimeException("not support type of " + obj.getClass() + " convert to Time."); - } - - public static Timestamp getTimestamp(Object obj) { - if (obj == null) { - return null; - } - if (obj instanceof Timestamp) { - return (Timestamp) obj; - } else if (obj instanceof Date) { - return new Timestamp(((Date) obj).getTime()); - } else if (obj instanceof String) { - return DateUtil.getTimestampFromStr(obj.toString()); - } - throw new RuntimeException("not support type of " + obj.getClass() + " convert to Date."); - } - - public static Character getChar(Object obj) { - if (obj == null) { - return null; - } - if (obj instanceof Character) { - return (Character) obj; - } - if (obj instanceof String) { - return String.valueOf(obj).charAt(0); - } - throw new RuntimeException("not support type of " + obj.getClass() + " convert to Char"); } } diff --git a/core/src/main/java/com/dtstack/flink/sql/util/ParseUtils.java b/core/src/main/java/com/dtstack/flink/sql/util/ParseUtils.java index 096bb596e..73f0e9baa 100644 --- a/core/src/main/java/com/dtstack/flink/sql/util/ParseUtils.java +++ b/core/src/main/java/com/dtstack/flink/sql/util/ParseUtils.java @@ -36,26 +36,15 @@ package com.dtstack.flink.sql.util; -import com.google.common.collect.HashBasedTable; - -import com.google.common.collect.HashBiMap; -import org.apache.calcite.sql.SqlBasicCall; -import org.apache.calcite.sql.SqlIdentifier; -import org.apache.calcite.sql.SqlJoin; -import org.apache.calcite.sql.SqlKind; -import org.apache.calcite.sql.SqlNode; +import com.google.common.collect.Lists; +import org.apache.calcite.sql.*; +import org.apache.calcite.sql.fun.SqlCase; +import org.apache.calcite.sql.parser.SqlParserPos; import org.apache.commons.lang3.StringUtils; -import org.apache.flink.api.java.tuple.Tuple2; - -import java.util.Arrays; import java.util.List; import java.util.Map; -import java.util.Set; - -import static org.apache.calcite.sql.SqlKind.AS; -import static org.apache.calcite.sql.SqlKind.IDENTIFIER; -import static org.apache.calcite.sql.SqlKind.JOIN; +import static org.apache.calcite.sql.SqlKind.*; /** * @Auther: jiangjunjie @@ -63,28 +52,68 @@ * @Description: */ public class ParseUtils { - public static void parseAnd(SqlNode conditionNode, List sqlNodeList) { - if (conditionNode.getKind() == SqlKind.AND && ((SqlBasicCall) conditionNode).getOperandList().size() == 2) { - parseAnd(((SqlBasicCall) conditionNode).getOperands()[0], sqlNodeList); - sqlNodeList.add(((SqlBasicCall) conditionNode).getOperands()[1]); + public static void parseSideWhere(SqlNode whereNode, Map physicalFields, List whereConditionList) { + SqlKind sqlKind = whereNode.getKind(); + if ((sqlKind == SqlKind.OR || sqlKind == SqlKind.AND) && ((SqlBasicCall) whereNode).getOperandList().size() == 2) { + SqlNode[] sqlOperandsList = ((SqlBasicCall) whereNode).getOperands(); + // whereNode是一颗先解析or再解析and的二叉树。二叉树中序遍历,先左子树,其次中间节点,最后右子树 + parseSideWhere(sqlOperandsList[0], physicalFields, whereConditionList); + whereConditionList.add(sqlKind.name()); + parseSideWhere(sqlOperandsList[1], physicalFields, whereConditionList); } else { + SqlIdentifier sqlIdentifier = (SqlIdentifier) ((SqlBasicCall) whereNode).getOperands()[0]; + String fieldName = null; + if (sqlIdentifier.names.size() == 1) { + fieldName = sqlIdentifier.getComponent(0).getSimple(); + } else { + fieldName = sqlIdentifier.getComponent(1).getSimple(); + } + if (physicalFields.containsKey(fieldName)) { + String sideFieldName = physicalFields.get(fieldName); + // clone SqlIdentifier node + SqlParserPos sqlParserPos = new SqlParserPos(0, 0); + SqlIdentifier sqlIdentifierClone = new SqlIdentifier("", null, sqlParserPos); + List namesClone = Lists.newArrayList(); + for(String name :sqlIdentifier.names){ + namesClone.add(name); + } + sqlIdentifierClone.setNames(namesClone,null); + // clone SqlBasicCall node + SqlBasicCall sqlBasicCall = (SqlBasicCall)whereNode; + SqlNode[] sqlNodes = sqlBasicCall.getOperands(); + SqlNode[] sqlNodesClone = new SqlNode[sqlNodes.length]; + for (int i = 0; i < sqlNodes.length; i++) { + sqlNodesClone[i] = sqlNodes[i]; + } + SqlBasicCall sqlBasicCallClone = new SqlBasicCall(sqlBasicCall.getOperator(), sqlNodesClone, sqlParserPos); + // 替换维表中真实字段名 + List names = Lists.newArrayList(); + names.add(sideFieldName); + sqlIdentifierClone.setNames(names, null); + + sqlBasicCallClone.setOperand(0, sqlIdentifierClone); + whereConditionList.add(sqlBasicCallClone.toString()); + } else { + // 如果字段不是维表中字段,删除字段前的链接符 + if (whereConditionList.size() >= 1) { + whereConditionList.remove(whereConditionList.size() - 1); + } + } + } + } + + public static void parseAnd(SqlNode conditionNode, List sqlNodeList){ + if(conditionNode.getKind() == SqlKind.AND && ((SqlBasicCall)conditionNode).getOperandList().size()==2){ + parseAnd(((SqlBasicCall)conditionNode).getOperands()[0], sqlNodeList); + sqlNodeList.add(((SqlBasicCall)conditionNode).getOperands()[1]); + }else{ sqlNodeList.add(conditionNode); } } public static void parseJoinCompareOperate(SqlNode condition, List sqlJoinCompareOperate) { SqlBasicCall joinCondition = (SqlBasicCall) condition; - - // 跳过常量JOIN的等式 - if (joinCondition.getKind() == SqlKind.EQUALS) { - SqlNode left = joinCondition.getOperands()[0]; - SqlNode right = joinCondition.getOperands()[1]; - if (left.getKind() != SqlKind.LITERAL && - right.getKind() != SqlKind.LITERAL) { - String operator = transformNotEqualsOperator(joinCondition.getKind()); - sqlJoinCompareOperate.add(operator); - } - } else if (joinCondition.getKind() == SqlKind.AND) { + if (joinCondition.getKind() == SqlKind.AND) { List operandList = joinCondition.getOperandList(); for (SqlNode sqlNode : operandList) { parseJoinCompareOperate(sqlNode, sqlJoinCompareOperate); @@ -96,110 +125,180 @@ public static void parseJoinCompareOperate(SqlNode condition, List sqlJo } public static String transformNotEqualsOperator(SqlKind sqlKind) { - if (StringUtils.equalsIgnoreCase(sqlKind.toString(), "NOT_EQUALS")) { + if (StringUtils.equalsIgnoreCase(sqlKind.toString(), "NOT_EQUALS")){ return "!="; } return sqlKind.sql; } + public static SqlNode replaceJoinConditionTabName(SqlNode conditionNode, Map mappingTable) { + SqlNode[] operands = ((SqlBasicCall) conditionNode).getOperands(); + + for (int i = 0; i < operands.length; i++) { + SqlNode sqlNode = operands[i]; + SqlNode replaceNode = replaceNodeInfo(sqlNode, mappingTable); + operands[i] = replaceNode; + } + return conditionNode; + } + /** - * parse multi join table name, child query RealTabName is null - * @param leftJoin - * @param aliasAndRealTabName + * m.id covert m_x_0.id + * @param selectNode + * @param mapTab + * @return */ - public static void parseLeftNodeTableName(SqlNode leftJoin, List> aliasAndRealTabName, Set sideTableSet) { - if (leftJoin.getKind() == IDENTIFIER) { - SqlIdentifier sqlIdentifier = (SqlIdentifier) leftJoin; - if (sqlIdentifier.names.size() == 1 && !sideTableSet.contains(sqlIdentifier.names.get(0))) { - aliasAndRealTabName.add(new Tuple2<>(sqlIdentifier.names.get(0), sqlIdentifier.names.get(0))); + public static SqlNode replaceSelectFieldTabName(SqlNode selectNode, Map mapTab) { + if (selectNode.getKind() == AS) { + SqlNode leftNode = ((SqlBasicCall) selectNode).getOperands()[0]; + SqlNode replaceNode = replaceSelectFieldTabName(leftNode, mapTab); + if (replaceNode != null) { + ((SqlBasicCall) selectNode).getOperands()[0] = replaceNode; } - } else if (leftJoin.getKind() == AS) { - SqlNode sqlNode = ((SqlBasicCall) leftJoin).getOperands()[0]; - if (sideTableSet.contains(sqlNode.toString())) { - return; + + return selectNode; + }else if(selectNode.getKind() == IDENTIFIER){ + SqlIdentifier sqlIdentifier = (SqlIdentifier) selectNode; + + if(sqlIdentifier.names.size() == 1){ + return selectNode; } - if (sqlNode.getKind() == IDENTIFIER) { - aliasAndRealTabName.add(new Tuple2<>(((SqlBasicCall) leftJoin).getOperands()[1].toString(), sqlNode.toString())); - } else { - // child query - aliasAndRealTabName.add(new Tuple2<>(((SqlBasicCall) leftJoin).getOperands()[1].toString(), null)); + + String newTableName = ParseUtils.getRootName(mapTab, sqlIdentifier.getComponent(0).getSimple()); + + if(newTableName == null){ + return selectNode; } - } else if (leftJoin.getKind() == JOIN) { - parseLeftNodeTableName(((SqlJoin) leftJoin).getLeft(), aliasAndRealTabName, sideTableSet); - parseLeftNodeTableName(((SqlJoin) leftJoin).getRight(), aliasAndRealTabName, sideTableSet); + sqlIdentifier = sqlIdentifier.setName(0, newTableName); + return sqlIdentifier; + + }else if(selectNode.getKind() == LITERAL || selectNode.getKind() == LITERAL_CHAIN){//字面含义 + return selectNode; + }else if( AGGREGATE.contains(selectNode.getKind()) + || AVG_AGG_FUNCTIONS.contains(selectNode.getKind()) + || COMPARISON.contains(selectNode.getKind()) + || selectNode.getKind() == OTHER_FUNCTION + || selectNode.getKind() == DIVIDE + || selectNode.getKind() == CAST + || selectNode.getKind() == TRIM + || selectNode.getKind() == TIMES + || selectNode.getKind() == PLUS + || selectNode.getKind() == NOT_IN + || selectNode.getKind() == OR + || selectNode.getKind() == AND + || selectNode.getKind() == MINUS + || selectNode.getKind() == TUMBLE + || selectNode.getKind() == TUMBLE_START + || selectNode.getKind() == TUMBLE_END + || selectNode.getKind() == SESSION + || selectNode.getKind() == SESSION_START + || selectNode.getKind() == SESSION_END + || selectNode.getKind() == HOP + || selectNode.getKind() == HOP_START + || selectNode.getKind() == HOP_END + || selectNode.getKind() == BETWEEN + || selectNode.getKind() == IS_NULL + || selectNode.getKind() == IS_NOT_NULL + || selectNode.getKind() == CONTAINS + || selectNode.getKind() == TIMESTAMP_ADD + || selectNode.getKind() == TIMESTAMP_DIFF + + ){ + SqlBasicCall sqlBasicCall = (SqlBasicCall) selectNode; + for(int i=0; i mappingTable, String tabAlias) { - if (conditionNode.getKind() == SqlKind.AND && ((SqlBasicCall) conditionNode).getOperandList().size() == 2) { - SqlNode[] operands = ((SqlBasicCall) conditionNode).getOperands(); - Arrays.stream(operands).forEach(op -> replaceJoinConditionTabName(op, mappingTable, tabAlias)); - } else { - SqlNode[] operands = ((SqlBasicCall) conditionNode).getOperands(); - for (int i = 0; i < operands.length; i++) { - SqlNode sqlNode = operands[i]; - SqlNode replaceNode = replaceNodeInfo(sqlNode, mappingTable, tabAlias); - operands[i] = replaceNode; + private static void replaceWhenOrThenSelectFieldTabName(Map mapTab, SqlNodeList thenOperands) { + for(int i=0; i mappingTable, String tabAlias) { + public static SqlNode replaceNodeInfo(SqlNode parseNode, Map mapTab) { if (parseNode.getKind() == IDENTIFIER) { SqlIdentifier sqlIdentifier = (SqlIdentifier) parseNode; + String newTableName = ParseUtils.getRootName(mapTab, sqlIdentifier.getComponent(0).getSimple());; + if (newTableName == null || sqlIdentifier.names.size() == 1) { + return sqlIdentifier; + } + sqlIdentifier = sqlIdentifier.setName(0, newTableName); return sqlIdentifier; - } - return parseNode; - } - - public static void fillFieldNameMapping(HashBasedTable midTableMapping, String[] fieldNames, String tableAlias) { - Arrays.asList(fieldNames).forEach(fieldName -> { - String mappingTableName = dealDuplicateFieldName(midTableMapping, fieldName); - midTableMapping.put(tableAlias, fieldName, mappingTableName); - }); - } + } else if (parseNode instanceof SqlBasicCall) { + SqlBasicCall sqlBasicCall = (SqlBasicCall) parseNode; + for (int i = 0; i < sqlBasicCall.getOperandList().size(); i++) { + SqlNode sqlNode = sqlBasicCall.getOperandList().get(i); + SqlNode replaceNode = replaceSelectFieldTabName(sqlNode, mapTab); + sqlBasicCall.getOperands()[i] = replaceNode; + } - public static String dealDuplicateFieldName(HashBasedTable mappingTable, String fieldName) { - String mappingFieldName = fieldName; - int index = 1; - while (!mappingTable.column(mappingFieldName).isEmpty()) { - mappingFieldName = suffixWithChar(fieldName, '0', index); - index++; + return sqlBasicCall; + } else { + return parseNode; } - return mappingFieldName; } - public static String dealDuplicateFieldName(HashBiMap refFieldMap, String fieldName) { - String mappingFieldName = fieldName; - int index = 1; - while (refFieldMap.inverse().get(mappingFieldName) != null ) { - mappingFieldName = suffixWithChar(fieldName, '0', index); - index++; - } - - return mappingFieldName; - } - public static String dealDuplicateFieldName(Map refFieldMap, String fieldName) { - String mappingFieldName = fieldName; - int index = 1; - while (refFieldMap.containsKey(mappingFieldName)){ - mappingFieldName = suffixWithChar(fieldName, '0', index); - index++; + public static String getRootName(Map maps, String key) { + String res = null; + while (maps.get(key) !=null) { + res = maps.get(key); + key = res; } - - return mappingFieldName; + return res; } - public static String suffixWithChar(String str, char padChar, int repeat){ - StringBuilder stringBuilder = new StringBuilder(str); - for(int i=0; i tablesName) { + if (leftJoin.getKind() == IDENTIFIER) { + SqlIdentifier sqlIdentifier = (SqlIdentifier) leftJoin; + tablesName.add(sqlIdentifier.names.get(0)); + } else if (leftJoin.getKind() == AS) { + SqlNode sqlNode = ((SqlBasicCall) leftJoin).getOperands()[1]; + tablesName.add(sqlNode.toString()); + } else if (leftJoin.getKind() == JOIN) { + parseLeftNodeTableName(((SqlJoin) leftJoin).getLeft(), tablesName); + parseLeftNodeTableName(((SqlJoin) leftJoin).getRight(), tablesName); } - - return stringBuilder.toString(); } } diff --git a/core/src/main/java/com/dtstack/flink/sql/util/PluginUtil.java b/core/src/main/java/com/dtstack/flink/sql/util/PluginUtil.java index fb2124670..f1c26b047 100644 --- a/core/src/main/java/com/dtstack/flink/sql/util/PluginUtil.java +++ b/core/src/main/java/com/dtstack/flink/sql/util/PluginUtil.java @@ -16,29 +16,26 @@ * limitations under the License. */ - + package com.dtstack.flink.sql.util; -import com.dtstack.flink.sql.dirtyManager.consumer.DirtyConsumerFactory; -import com.dtstack.flink.sql.enums.EPluginLoadMode; +import com.dtstack.flink.sql.classloader.DtClassLoader; import org.apache.commons.lang3.StringUtils; -import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.core.JsonProcessingException; -import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.ObjectMapper; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.core.JsonGenerationException; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; import java.io.ByteArrayInputStream; import java.io.File; +import java.io.FilenameFilter; import java.io.IOException; import java.net.MalformedURLException; -import java.net.URI; import java.net.URL; -import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.Properties; /** @@ -50,64 +47,37 @@ public class PluginUtil { - private static final String SP = File.separator; + private static String SP = File.separator; private static final String JAR_SUFFIX = ".jar"; private static final String CLASS_PRE_STR = "com.dtstack.flink.sql"; - private static final String DIRTY_DATA_PRE = "dirtyData"; - - private static final Logger LOG = LoggerFactory.getLogger(PluginUtil.class); - - private static final ObjectMapper objectMapper = new ObjectMapper(); + private static ObjectMapper objectMapper = new ObjectMapper(); - public static URL buildSourceAndSinkPathByLoadMode(String type, String suffix, String localSqlPluginPath, String remoteSqlPluginPath, String pluginLoadMode) throws Exception { - if (StringUtils.equalsIgnoreCase(pluginLoadMode, EPluginLoadMode.CLASSPATH.name())) { - return getRemoteJarFilePath(type, suffix, remoteSqlPluginPath, localSqlPluginPath, pluginLoadMode); - } - return getLocalJarFilePath(type, suffix, localSqlPluginPath, pluginLoadMode); - } - public static URL buildSidePathByLoadMode(String type, String operator, String suffix, String localSqlPluginPath, String remoteSqlPluginPath, String pluginLoadMode) throws Exception { - if (StringUtils.equalsIgnoreCase(pluginLoadMode, EPluginLoadMode.CLASSPATH.name())) { - return getRemoteSideJarFilePath(type, operator, suffix, remoteSqlPluginPath, localSqlPluginPath, pluginLoadMode); - } - return getLocalSideJarFilePath(type, operator, suffix, localSqlPluginPath, pluginLoadMode); - } - - public static String getJarFileDirPath(String type, String sqlRootDir, String pluginLoadMode){ + public static String getJarFileDirPath(String type, String sqlRootDir){ String jarPath = sqlRootDir + SP + type; + File jarFile = new File(jarPath); - checkJarFileDirPath(sqlRootDir, jarPath, pluginLoadMode); + if(!jarFile.exists()){ + throw new RuntimeException(String.format("path %s not exists!!!", jarPath)); + } return jarPath; } - public static String getSideJarFileDirPath(String pluginType, String sideOperator, String tableType, String sqlRootDir, String pluginLoadMode) throws MalformedURLException { + public static String getSideJarFileDirPath(String pluginType, String sideOperator, String tableType, String sqlRootDir) throws MalformedURLException { String dirName = sqlRootDir + SP + pluginType + sideOperator + tableType.toLowerCase(); + File jarFile = new File(dirName); - checkJarFileDirPath(sqlRootDir, dirName, pluginLoadMode); + if(!jarFile.exists()){ + throw new RuntimeException(String.format("path %s not exists!!!", dirName)); + } return dirName; } - private static void checkJarFileDirPath(String sqlRootDir, String path, String pluginLoadMode) { - if (pluginLoadMode.equalsIgnoreCase(EPluginLoadMode.LOCALTEST.name())) { - LOG.warn("be sure you are not in LocalTest mode, if not, check the sqlRootDir"); - } else { - if (sqlRootDir == null || sqlRootDir.isEmpty()) { - throw new RuntimeException("sqlPlugin is empty !"); - } - - File jarFile = new File(path); - - if (!jarFile.exists()) { - throw new RuntimeException(String.format("path %s not exists!!!", path)); - } - } - } - public static String getGenerClassName(String pluginTypeName, String type) throws IOException { String pluginClassName = upperCaseFirstChar(pluginTypeName) + upperCaseFirstChar(type); return CLASS_PRE_STR + "." + type.toLowerCase() + "." + pluginTypeName + "." + pluginClassName; @@ -125,93 +95,50 @@ public static String getSqlSideClassName(String pluginTypeName, String type, Str return CLASS_PRE_STR + "." + type.toLowerCase() + "." + pluginTypeName + "." + pluginClassName; } - public static Map objectToMap(Object obj) throws Exception{ + public static Map ObjectToMap(Object obj) throws Exception{ return objectMapper.readValue(objectMapper.writeValueAsBytes(obj), Map.class); } - public static String objectToString(Object obj) throws JsonProcessingException { - return objectMapper.writeValueAsString(obj); - } - - public static T jsonStrToObject(String jsonStr, Class clazz) throws IOException{ + public static T jsonStrToObject(String jsonStr, Class clazz) throws JsonParseException, JsonMappingException, JsonGenerationException, IOException{ return objectMapper.readValue(jsonStr, clazz); } public static Properties stringToProperties(String str) throws IOException{ Properties properties = new Properties(); - properties.load(new ByteArrayInputStream(str.getBytes(StandardCharsets.UTF_8))); + properties.load(new ByteArrayInputStream(str.getBytes("UTF-8"))); return properties; } - public static URL getRemoteJarFilePath(String pluginType, String tableType, String remoteSqlRootDir, String localSqlPluginPath, String pluginLoadMode) throws Exception { - return buildFinalJarFilePath(pluginType, tableType, remoteSqlRootDir, localSqlPluginPath, pluginLoadMode); + public static URL getRemoteJarFilePath(String pluginType, String tableType, String remoteSqlRootDir, String localSqlPluginPath) throws Exception { + return buildFinalJarFilePath(pluginType, tableType, remoteSqlRootDir, localSqlPluginPath); } - public static URL getLocalJarFilePath(String pluginType, String tableType, String localSqlPluginPath, String pluginLoadMode) throws Exception { - return buildFinalJarFilePath(pluginType, tableType, null, localSqlPluginPath, pluginLoadMode); + public static URL getLocalJarFilePath(String pluginType, String tableType, String localSqlPluginPath) throws Exception { + return buildFinalJarFilePath(pluginType, tableType, null, localSqlPluginPath); } - public static URL buildFinalJarFilePath(String pluginType, String tableType, String remoteSqlRootDir, String localSqlPluginPath, String pluginLoadMode) throws Exception { + public static URL buildFinalJarFilePath(String pluginType, String tableType, String remoteSqlRootDir, String localSqlPluginPath) throws Exception { String dirName = pluginType + tableType.toLowerCase(); String prefix = String.format("%s-%s", pluginType, tableType.toLowerCase()); String jarPath = localSqlPluginPath + SP + dirName; - String jarName = getCoreJarFileName(jarPath, prefix, pluginLoadMode); + String jarName = getCoreJarFileName(jarPath, prefix); String sqlRootDir = remoteSqlRootDir == null ? localSqlPluginPath : remoteSqlRootDir; return new URL("file:" + sqlRootDir + SP + dirName + SP + jarName); } - /** - * build dirty data url from plugin path - * - * @param dirtyType type of dirty type - * @param localPath local path - * @param remotePath remote path - * @param pluginLoadMode load plugin mode - * @return dirty plugin url - * @throws Exception exception - */ - public static URL buildDirtyPluginUrl( - String dirtyType, - String localPath, - String remotePath, - String pluginLoadMode) throws Exception { - if (Objects.isNull(dirtyType)) { - dirtyType = DirtyConsumerFactory.DEFAULT_DIRTY_TYPE; - } - String prefix = String.format("dirtyConsumer-%s", dirtyType.toLowerCase()).toLowerCase(); - String consumerType = DirtyConsumerFactory.DIRTY_CONSUMER_PATH + File.separator + dirtyType; - String consumerJar = PluginUtil.getJarFileDirPath(consumerType, localPath, pluginLoadMode); - String jarFileName = PluginUtil.getCoreJarFileName( - consumerJar, - prefix, - pluginLoadMode - ); - - String path; - if (StringUtils.equalsIgnoreCase(pluginLoadMode, EPluginLoadMode.CLASSPATH.name())) { - path = remotePath == null ? localPath : remotePath; - } else { - path = localPath; - } - - String dirtyPath = path + SP + DIRTY_DATA_PRE + SP + dirtyType; - URI uri = URI.create("file:" + dirtyPath + SP + jarFileName); - return uri.toURL(); + public static URL getRemoteSideJarFilePath(String pluginType, String sideOperator, String tableType, String remoteSqlRootDir, String localSqlPluginPath) throws Exception { + return buildFinalSideJarFilePath(pluginType, sideOperator, tableType, remoteSqlRootDir, localSqlPluginPath); } - public static URL getRemoteSideJarFilePath(String pluginType, String sideOperator, String tableType, String remoteSqlRootDir, String localSqlPluginPath, String pluginLoadMode) throws Exception { - return buildFinalSideJarFilePath(pluginType, sideOperator, tableType, remoteSqlRootDir, localSqlPluginPath, pluginLoadMode); + public static URL getLocalSideJarFilePath(String pluginType, String sideOperator, String tableType, String localSqlPluginPath) throws Exception { + return buildFinalSideJarFilePath(pluginType, sideOperator, tableType, null, localSqlPluginPath); } - public static URL getLocalSideJarFilePath(String pluginType, String sideOperator, String tableType, String localSqlPluginPath, String pluginLoadMode) throws Exception { - return buildFinalSideJarFilePath(pluginType, sideOperator, tableType, null, localSqlPluginPath, pluginLoadMode); - } - - public static URL buildFinalSideJarFilePath(String pluginType, String sideOperator, String tableType, String remoteSqlRootDir, String localSqlPluginPath, String pluginLoadMode) throws Exception { + public static URL buildFinalSideJarFilePath(String pluginType, String sideOperator, String tableType, String remoteSqlRootDir, String localSqlPluginPath) throws Exception { String dirName = pluginType + sideOperator + tableType.toLowerCase(); String prefix = String.format("%s-%s-%s", pluginType, sideOperator, tableType.toLowerCase()); String jarPath = localSqlPluginPath + SP + dirName; - String jarName = getCoreJarFileName(jarPath, prefix, pluginLoadMode); + String jarName = getCoreJarFileName(jarPath, prefix); String sqlRootDir = remoteSqlRootDir == null ? localSqlPluginPath : remoteSqlRootDir; return new URL("file:" + sqlRootDir + SP + dirName + SP + jarName); } @@ -220,15 +147,26 @@ public static String upperCaseFirstChar(String str){ return str.substring(0, 1).toUpperCase() + str.substring(1); } - public static URL[] getPluginJarUrls(String pluginDir) throws MalformedURLException { - List urlList = new ArrayList<>(); - + public static void addPluginJar(String pluginDir, DtClassLoader classLoader) throws MalformedURLException { File dirFile = new File(pluginDir); + if(!dirFile.exists() || !dirFile.isDirectory()){ + throw new RuntimeException("plugin path:" + pluginDir + "is not exist."); + } - if (pluginDir.contains("null")) { - return urlList.toArray(new URL[0]); + File[] files = dirFile.listFiles(tmpFile -> tmpFile.isFile() && tmpFile.getName().endsWith(JAR_SUFFIX)); + if(files == null || files.length == 0){ + throw new RuntimeException("plugin path:" + pluginDir + " is null."); } + for(File file : files){ + URL pluginJarURL = file.toURI().toURL(); + classLoader.addURL(pluginJarURL); + } + } + + public static URL[] getPluginJarUrls(String pluginDir) throws MalformedURLException { + List urlList = new ArrayList<>(); + File dirFile = new File(pluginDir); if(!dirFile.exists() || !dirFile.isDirectory()){ throw new RuntimeException("plugin path:" + pluginDir + "is not exist."); } @@ -239,29 +177,33 @@ public static URL[] getPluginJarUrls(String pluginDir) throws MalformedURLExcept } for(File file : files){ - URL pluginJarUrl = file.toURI().toURL(); - urlList.add(pluginJarUrl); + URL pluginJarURL = file.toURI().toURL(); + urlList.add(pluginJarURL); } - - return urlList.toArray(new URL[0]); + return urlList.toArray(new URL[urlList.size()]); } - - public static String getCoreJarFileName(String path, String prefix, String pluginLoadMode) throws Exception { + + public static String getCoreJarFileName (String path, String prefix) throws Exception { String coreJarFileName = null; File pluginDir = new File(path); if (pluginDir.exists() && pluginDir.isDirectory()){ - File[] jarFiles = pluginDir.listFiles((dir, name) -> - name.toLowerCase().startsWith(prefix) && name.toLowerCase().endsWith(".jar")); + File[] jarFiles = pluginDir.listFiles(new FilenameFilter() { + @Override + public boolean accept(File dir, String name) { + return name.toLowerCase().startsWith(prefix) && name.toLowerCase().endsWith(".jar"); + } + }); if (jarFiles != null && jarFiles.length > 0){ coreJarFileName = jarFiles[0].getName(); } } - if (StringUtils.isEmpty(coreJarFileName) && !pluginLoadMode.equalsIgnoreCase(EPluginLoadMode.LOCALTEST.name())){ + if (StringUtils.isEmpty(coreJarFileName)){ throw new Exception("Can not find core jar file in path:" + path); } return coreJarFileName; } + } diff --git a/core/src/main/java/com/dtstack/flink/sql/util/RowDataComplete.java b/core/src/main/java/com/dtstack/flink/sql/util/RowDataComplete.java deleted file mode 100644 index ac3886401..000000000 --- a/core/src/main/java/com/dtstack/flink/sql/util/RowDataComplete.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.util; - -import org.apache.commons.compress.utils.Lists; -import org.apache.flink.streaming.api.functions.async.ResultFuture; -import org.apache.flink.table.dataformat.BaseRow; -import org.apache.flink.util.Collector; - -import java.util.Collections; -import java.util.List; - -/** - * Company: www.dtstack.com - * - * @author xuchao - * @date 2020-05-20 - */ -public class RowDataComplete { - - public static void completeBaseRow(ResultFuture resultFuture, BaseRow row) { - resultFuture.complete(Collections.singleton(RowDataConvert.convertToBaseRow(row))); - } - - public static void completeBaseRow(ResultFuture resultFuture, List rowList) { - List baseRowList = Lists.newArrayList(); - for (BaseRow baseRow : rowList) { - baseRowList.add(RowDataConvert.convertToBaseRow(baseRow)); - } - resultFuture.complete(baseRowList); - } - - public static void collectBaseRow(Collector out, BaseRow row) { - out.collect(RowDataConvert.convertToBaseRow(row)); - } -} \ No newline at end of file diff --git a/core/src/main/java/com/dtstack/flink/sql/util/RowDataConvert.java b/core/src/main/java/com/dtstack/flink/sql/util/RowDataConvert.java deleted file mode 100644 index 6da8937ae..000000000 --- a/core/src/main/java/com/dtstack/flink/sql/util/RowDataConvert.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.util; - -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.table.dataformat.BaseRow; -import org.apache.flink.table.dataformat.BinaryString; -import org.apache.flink.table.dataformat.DataFormatConverters; -import org.apache.flink.table.dataformat.Decimal; -import org.apache.flink.table.dataformat.GenericRow; -import org.apache.flink.table.dataformat.SqlTimestamp; -import org.apache.flink.table.dataformat.util.BaseRowUtil; -import org.apache.flink.types.Row; - -import java.math.BigDecimal; -import java.sql.Date; -import java.sql.Time; -import java.sql.Timestamp; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; - -/** - * Company: www.dtstack.com - * - * @author xuchao - * @date 2020-05-20 - */ -public class RowDataConvert { - - public static BaseRow convertToBaseRow(Tuple2 input) { - Row row = input.f1; - int length = row.getArity(); - GenericRow genericRow = new GenericRow(length); - for (int i = 0; i < length; i++) { - if (row.getField(i) == null) { - genericRow.setField(i, row.getField(i)); - } else if (row.getField(i) instanceof String) { - genericRow.setField(i, BinaryString.fromString((String) row.getField(i))); - } else if (row.getField(i) instanceof Timestamp) { - SqlTimestamp newTimestamp = SqlTimestamp.fromTimestamp(((Timestamp) row.getField(i))); - genericRow.setField(i, newTimestamp); - } else if (row.getField(i) instanceof LocalDateTime) { - genericRow.setField(i, SqlTimestamp.fromLocalDateTime((LocalDateTime) row.getField(i))); - } else if (row.getField(i) instanceof Time) { - genericRow.setField(i, DataFormatConverters.TimeConverter.INSTANCE.toInternal((Time) row.getField(i))); - } else if (row.getField(i) instanceof Double || row.getField(i).getClass().equals(double.class)) { - genericRow.setField(i, DataFormatConverters.DoubleConverter.INSTANCE.toInternal((Double) row.getField(i))); - } else if (row.getField(i) instanceof Float || row.getField(i).getClass().equals(float.class)) { - genericRow.setField(i, DataFormatConverters.FloatConverter.INSTANCE.toInternal((Float) row.getField(i))); - } else if (row.getField(i) instanceof Long || row.getField(i).getClass().equals(long.class)) { - genericRow.setField(i, DataFormatConverters.LongConverter.INSTANCE.toInternal((Long) row.getField(i))); - } else if (row.getField(i) instanceof Boolean || row.getField(i).getClass().equals(boolean.class)) { - genericRow.setField(i, DataFormatConverters.BooleanConverter.INSTANCE.toInternal((Boolean) row.getField(i))); - } else if (row.getField(i) instanceof Integer || row.getField(i).getClass().equals(int.class)) { - genericRow.setField(i, DataFormatConverters.IntConverter.INSTANCE.toInternal((Integer) row.getField(i))); - } else if (row.getField(i) instanceof Short || row.getField(i).getClass().equals(short.class)) { - genericRow.setField(i, DataFormatConverters.ShortConverter.INSTANCE.toInternal((Short) row.getField(i))); - } else if (row.getField(i) instanceof Byte || row.getField(i).getClass().equals(byte.class)) { - genericRow.setField(i, DataFormatConverters.ByteConverter.INSTANCE.toInternal((Byte) row.getField(i))); - } else if (row.getField(i) instanceof Date) { - genericRow.setField(i, DataFormatConverters.DateConverter.INSTANCE.toInternal((Date) row.getField(i))); - } else if (row.getField(i) instanceof LocalDate) { - genericRow.setField(i, DataFormatConverters.LocalDateConverter.INSTANCE.toInternal((LocalDate) row.getField(i))); - } else if (row.getField(i) instanceof LocalTime) { - genericRow.setField(i, DataFormatConverters.LocalTimeConverter.INSTANCE.toInternal((LocalTime) row.getField(i))); - } else if (row.getField(i) instanceof BigDecimal) { - BigDecimal tempDecimal = (BigDecimal) row.getField(i); - int precision = ((BigDecimal) row.getField(i)).precision(); - int scale = ((BigDecimal) row.getField(i)).scale(); - DataFormatConverters.DecimalConverter decimalConverter = new DataFormatConverters.DecimalConverter(precision, scale); - genericRow.setField(i, decimalConverter.toExternal(Decimal.fromBigDecimal(tempDecimal, precision, scale))); - } else { - genericRow.setField(i, row.getField(i)); - } - } - - if (input.f0) { - BaseRowUtil.setAccumulate(genericRow); - } else { - BaseRowUtil.setRetract(genericRow); - } - - return genericRow; - } - - - public static BaseRow convertToBaseRow(BaseRow input) { - GenericRow row = (GenericRow) input; - int length = row.getArity(); - GenericRow genericRow = new GenericRow(length); - genericRow.setHeader(row.getHeader()); - for (int i = 0; i < length; i++) { - if (row.getField(i) == null) { - genericRow.setField(i, row.getField(i)); - } else if (row.getField(i) instanceof String) { - genericRow.setField(i, BinaryString.fromString((String) row.getField(i))); - } else if (row.getField(i) instanceof Timestamp) { - SqlTimestamp newTimestamp = SqlTimestamp.fromTimestamp(((Timestamp) row.getField(i))); - genericRow.setField(i, newTimestamp); - } else if (row.getField(i) instanceof LocalDateTime) { - genericRow.setField(i, SqlTimestamp.fromLocalDateTime((LocalDateTime) row.getField(i))); - } else if (row.getField(i) instanceof Time) { - genericRow.setField(i, DataFormatConverters.TimeConverter.INSTANCE.toInternal((Time) row.getField(i))); - } else if (row.getField(i) instanceof Double || row.getField(i).getClass().equals(double.class)) { - genericRow.setField(i, DataFormatConverters.DoubleConverter.INSTANCE.toInternal((Double) row.getField(i))); - } else if (row.getField(i) instanceof Float || row.getField(i).getClass().equals(float.class)) { - genericRow.setField(i, DataFormatConverters.FloatConverter.INSTANCE.toInternal((Float) row.getField(i))); - } else if (row.getField(i) instanceof Long || row.getField(i).getClass().equals(long.class)) { - genericRow.setField(i, DataFormatConverters.LongConverter.INSTANCE.toInternal((Long) row.getField(i))); - } else if (row.getField(i) instanceof Boolean || row.getField(i).getClass().equals(boolean.class)) { - genericRow.setField(i, DataFormatConverters.BooleanConverter.INSTANCE.toInternal((Boolean) row.getField(i))); - } else if (row.getField(i) instanceof Integer || row.getField(i).getClass().equals(int.class)) { - genericRow.setField(i, DataFormatConverters.IntConverter.INSTANCE.toInternal((Integer) row.getField(i))); - } else if (row.getField(i) instanceof Short || row.getField(i).getClass().equals(short.class)) { - genericRow.setField(i, DataFormatConverters.ShortConverter.INSTANCE.toInternal((Short) row.getField(i))); - } else if (row.getField(i) instanceof Byte || row.getField(i).getClass().equals(byte.class)) { - genericRow.setField(i, DataFormatConverters.ByteConverter.INSTANCE.toInternal((Byte) row.getField(i))); - } else if (row.getField(i) instanceof Date) { - genericRow.setField(i, DataFormatConverters.DateConverter.INSTANCE.toInternal((Date) row.getField(i))); - } else if (row.getField(i) instanceof LocalDate) { - genericRow.setField(i, DataFormatConverters.LocalDateConverter.INSTANCE.toInternal((LocalDate) row.getField(i))); - } else if (row.getField(i) instanceof LocalTime) { - genericRow.setField(i, DataFormatConverters.LocalTimeConverter.INSTANCE.toInternal((LocalTime) row.getField(i))); - } else if (row.getField(i) instanceof BigDecimal) { - BigDecimal tempDecimal = (BigDecimal) row.getField(i); - int precision = ((BigDecimal) row.getField(i)).precision(); - int scale = ((BigDecimal) row.getField(i)).scale(); - DataFormatConverters.DecimalConverter decimalConverter = new DataFormatConverters.DecimalConverter(precision, scale); - genericRow.setField(i, decimalConverter.toExternal(Decimal.fromBigDecimal(tempDecimal, precision, scale))); - } else { - genericRow.setField(i, row.getField(i)); - } - } - return genericRow; - } -} \ No newline at end of file diff --git a/core/src/main/java/com/dtstack/flink/sql/util/TableUtils.java b/core/src/main/java/com/dtstack/flink/sql/util/TableUtils.java deleted file mode 100644 index 22e670d59..000000000 --- a/core/src/main/java/com/dtstack/flink/sql/util/TableUtils.java +++ /dev/null @@ -1,825 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.util; - -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.PredicateInfo; -import com.google.common.base.Preconditions; -import com.google.common.base.Strings; -import com.google.common.collect.HashBasedTable; -import com.google.common.collect.Lists; -import org.apache.calcite.sql.SqlAsOperator; -import org.apache.calcite.sql.SqlBasicCall; -import org.apache.calcite.sql.SqlDataTypeSpec; -import org.apache.calcite.sql.SqlIdentifier; -import org.apache.calcite.sql.SqlInsert; -import org.apache.calcite.sql.SqlJoin; -import org.apache.calcite.sql.SqlKind; -import org.apache.calcite.sql.SqlLiteral; -import org.apache.calcite.sql.SqlNode; -import org.apache.calcite.sql.SqlNodeList; -import org.apache.calcite.sql.SqlOperator; -import org.apache.calcite.sql.SqlSelect; -import org.apache.calcite.sql.fun.SqlCase; -import org.apache.calcite.sql.parser.SqlParserPos; -import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.flink.table.api.Table; - -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Queue; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import static org.apache.calcite.sql.SqlKind.AGGREGATE; -import static org.apache.calcite.sql.SqlKind.AND; -import static org.apache.calcite.sql.SqlKind.AS; -import static org.apache.calcite.sql.SqlKind.AVG_AGG_FUNCTIONS; -import static org.apache.calcite.sql.SqlKind.BETWEEN; -import static org.apache.calcite.sql.SqlKind.CASE; -import static org.apache.calcite.sql.SqlKind.CAST; -import static org.apache.calcite.sql.SqlKind.COALESCE; -import static org.apache.calcite.sql.SqlKind.COMPARISON; -import static org.apache.calcite.sql.SqlKind.CONTAINS; -import static org.apache.calcite.sql.SqlKind.DIVIDE; -import static org.apache.calcite.sql.SqlKind.EQUALS; -import static org.apache.calcite.sql.SqlKind.HOP; -import static org.apache.calcite.sql.SqlKind.HOP_END; -import static org.apache.calcite.sql.SqlKind.HOP_START; -import static org.apache.calcite.sql.SqlKind.IDENTIFIER; -import static org.apache.calcite.sql.SqlKind.IS_NOT_NULL; -import static org.apache.calcite.sql.SqlKind.IS_NULL; -import static org.apache.calcite.sql.SqlKind.LIKE; -import static org.apache.calcite.sql.SqlKind.LITERAL; -import static org.apache.calcite.sql.SqlKind.LITERAL_CHAIN; -import static org.apache.calcite.sql.SqlKind.MINUS; -import static org.apache.calcite.sql.SqlKind.NOT_IN; -import static org.apache.calcite.sql.SqlKind.OR; -import static org.apache.calcite.sql.SqlKind.OTHER; -import static org.apache.calcite.sql.SqlKind.OTHER_FUNCTION; -import static org.apache.calcite.sql.SqlKind.PLUS; -import static org.apache.calcite.sql.SqlKind.POSITION; -import static org.apache.calcite.sql.SqlKind.SELECT; -import static org.apache.calcite.sql.SqlKind.SESSION; -import static org.apache.calcite.sql.SqlKind.SESSION_END; -import static org.apache.calcite.sql.SqlKind.SESSION_START; -import static org.apache.calcite.sql.SqlKind.TIMES; -import static org.apache.calcite.sql.SqlKind.TIMESTAMP_ADD; -import static org.apache.calcite.sql.SqlKind.TIMESTAMP_DIFF; -import static org.apache.calcite.sql.SqlKind.TRIM; -import static org.apache.calcite.sql.SqlKind.TUMBLE; -import static org.apache.calcite.sql.SqlKind.TUMBLE_END; -import static org.apache.calcite.sql.SqlKind.TUMBLE_START; -import static org.apache.calcite.sql.SqlKind.UNION; - -/** - * 表的解析相关 - * Date: 2020/2/17 - * Company: www.dtstack.com - * @author xuchao - */ - -public class TableUtils { - - public static final char SPLIT = '_'; - public static final Pattern stringPattern = Pattern.compile("\".*?\"|\'.*?\'"); - /** - * 获取select 的字段 - * @param sqlSelect - */ - public static List parserSelectField(SqlSelect sqlSelect, Map localTableCache){ - SqlNodeList sqlNodeList = sqlSelect.getSelectList(); - List fieldInfoList = Lists.newArrayList(); - String fromNode = sqlSelect.getFrom().toString(); - - for (SqlNode fieldNode : sqlNodeList.getList()) { - extractSelectFieldToFieldInfo(fieldNode,fromNode,fieldInfoList,localTableCache); - } - - return fieldInfoList; - } - - /** - * 解析select Node 提取FieldInfo - * @param fieldNode - * @param fromNode - * @param fieldInfoList - * @param localTableCache - */ - public static void extractSelectFieldToFieldInfo(SqlNode fieldNode, String fromNode, List fieldInfoList, Map localTableCache) { - if (fieldNode.getKind() == IDENTIFIER) { - SqlIdentifier identifier = (SqlIdentifier) fieldNode; - if (!identifier.isStar()) { - String tableName = identifier.names.size() == 1 ? fromNode : identifier.getComponent(0).getSimple(); - String fieldName = identifier.names.size() == 1 ? identifier.getComponent(0).getSimple() : identifier.getComponent(1).getSimple(); - FieldInfo fieldInfo = new FieldInfo(); - fieldInfo.setTable(tableName); - fieldInfo.setFieldName(fieldName); - - if (!fieldInfoList.contains(fieldInfo)) { - fieldInfoList.add(fieldInfo); - } - } else { - //处理 - int identifierSize = identifier.names.size(); - switch (identifierSize) { - case 1: - throw new RuntimeException("not support to parse * without scope of table"); - default: - SqlIdentifier tableIdentify = identifier.skipLast(1); - Table registerTable = localTableCache.get(tableIdentify.getSimple()); - if (registerTable == null) { - throw new RuntimeException("can't find table alias " + tableIdentify.getSimple()); - } - - String[] fieldNames = registerTable.getSchema().getFieldNames(); - for (String fieldName : fieldNames) { - FieldInfo fieldInfo = new FieldInfo(); - fieldInfo.setTable(tableIdentify.getSimple()); - fieldInfo.setFieldName(fieldName); - fieldInfoList.add(fieldInfo); - } - } - } - } else if (isCommonExpression(fieldNode)) { - SqlBasicCall sqlBasicCall = (SqlBasicCall) fieldNode; - for (int i = 0; i < sqlBasicCall.getOperands().length; i++) { - SqlNode sqlNode = sqlBasicCall.getOperands()[i]; - if (sqlNode instanceof SqlLiteral) { - continue; - } - - if (sqlNode instanceof SqlDataTypeSpec) { - continue; - } - extractSelectFieldToFieldInfo(sqlNode, fromNode, fieldInfoList, localTableCache); - } - } else if (fieldNode.getKind() == AS) { - SqlNode leftNode = ((SqlBasicCall) fieldNode).getOperands()[0]; - extractSelectFieldToFieldInfo(leftNode, fromNode,fieldInfoList, localTableCache); - } else if (fieldNode.getKind() == CASE) { - SqlCase sqlCase = (SqlCase) fieldNode; - SqlNodeList whenOperands = sqlCase.getWhenOperands(); - SqlNodeList thenOperands = sqlCase.getThenOperands(); - SqlNode elseNode = sqlCase.getElseOperand(); - - for (int i = 0; i < whenOperands.size(); i++) { - SqlNode oneOperand = whenOperands.get(i); - extractSelectFieldToFieldInfo(oneOperand, fromNode, fieldInfoList, localTableCache); - } - - for (int i = 0; i < thenOperands.size(); i++) { - SqlNode oneOperand = thenOperands.get(i); - extractSelectFieldToFieldInfo(oneOperand, fromNode, fieldInfoList, localTableCache); - - } - - extractSelectFieldToFieldInfo(elseNode, fromNode, fieldInfoList, localTableCache); - } - } - - public static SqlBasicCall buildAsNodeByJoinInfo(JoinInfo joinInfo, SqlNode sqlNode0, String tableAlias) { - SqlOperator operator = new SqlAsOperator(); - - SqlParserPos sqlParserPos = new SqlParserPos(0, 0); - String newTableName = joinInfo.getNewTableName(); - - String newTableAlias = !StringUtils.isEmpty(tableAlias) ? tableAlias : joinInfo.getNewTableAlias(); - - if (null == sqlNode0) { - sqlNode0 = new SqlIdentifier(newTableName, null, sqlParserPos); - } - - SqlIdentifier sqlIdentifierAlias = new SqlIdentifier(newTableAlias, null, sqlParserPos); - SqlNode[] sqlNodes = new SqlNode[2]; - sqlNodes[0] = sqlNode0; - sqlNodes[1] = sqlIdentifierAlias; - return new SqlBasicCall(operator, sqlNodes, sqlParserPos); - } - - /** - * - * @param joinInfo - * @param sqlNode - * @param queueInfo - * @return 两个边关联后的新表表名 - */ - public static String dealSelectResultWithJoinInfo(JoinInfo joinInfo, SqlSelect sqlNode, Queue queueInfo) { - //SideJoinInfo rename - if (joinInfo.checkIsSide()) { - joinInfo.setSelectFields(sqlNode.getSelectList()); - joinInfo.setSelectNode(sqlNode); - if (joinInfo.isRightIsSideTable()) { - //Analyzing left is not a simple table - if (joinInfo.getLeftNode().getKind() == SELECT) { - queueInfo.offer(joinInfo.getLeftNode()); - } - - if(joinInfo.getLeftNode().getKind() == AS){ - SqlNode leftSqlNode = ((SqlBasicCall)joinInfo.getLeftNode()).getOperands()[0]; - if (leftSqlNode.getKind() == UNION){ - queueInfo.offer(joinInfo.getLeftNode()); - } - } - - queueInfo.offer(joinInfo); - } else { - //Determining right is not a simple table - if (joinInfo.getRightNode().getKind() == SELECT) { - queueInfo.offer(joinInfo.getLeftNode()); - } - - queueInfo.offer(joinInfo); - } - replaceFromNodeForJoin(joinInfo, sqlNode); - return joinInfo.getNewTableName(); - } - return ""; - } - - public static void replaceFromNodeForJoin(JoinInfo joinInfo, SqlSelect sqlNode) { - //Update from node - SqlBasicCall sqlBasicCall = buildAsNodeByJoinInfo(joinInfo, null, null); - String newAliasName = sqlBasicCall.operand(1).toString(); - - //替换select 中的属性为新的表名称和字段 - HashBasedTable fieldMapping = joinInfo.getTableFieldRef(); - Map leftFieldMapping = fieldMapping.row(joinInfo.getLeftTableAlias()); - Map rightFieldMapping = fieldMapping.row(joinInfo.getRightTableAlias()); - - /* for(SqlNode oneSelectNode : sqlNode.getSelectList()){ - replaceSelectFieldTable(oneSelectNode, joinInfo.getLeftTableAlias(), newAliasName, null ,leftFieldMapping); - replaceSelectFieldTable(oneSelectNode, joinInfo.getRightTableAlias(), newAliasName, null , rightFieldMapping); - }*/ - - //where中的条件属性为新的表名称和字段 - FieldReplaceUtil.replaceFieldName(sqlNode, joinInfo.getLeftTableAlias(), newAliasName, leftFieldMapping); - FieldReplaceUtil.replaceFieldName(sqlNode, joinInfo.getRightTableAlias(), newAliasName, rightFieldMapping); - sqlNode.setFrom(sqlBasicCall); - } - - - /** - * 获取节点关联的查询表 - * @param fromTable - * @param tableNameSet - */ - public static void getFromTableInfo(SqlNode fromTable, Set tableNameSet){ - SqlKind sqlKind = fromTable.getKind(); - switch (sqlKind){ - case AS: - SqlNode alias = ((SqlBasicCall) fromTable).getOperands()[1]; - tableNameSet.add(alias.toString()); - return; - case JOIN: - getFromTableInfo(((SqlJoin)fromTable).getLeft(), tableNameSet); - getFromTableInfo(((SqlJoin)fromTable).getRight(), tableNameSet); - return; - case IDENTIFIER: - tableNameSet.add(((SqlIdentifier)fromTable).getSimple()); - return; - case SELECT: - getFromTableInfo(((SqlSelect) fromTable).getFrom(), tableNameSet); - return; - default: - throw new RuntimeException("not support sqlKind:" + sqlKind); - } - } - - /** - * 替换select 中的字段信息 - * 如果mappingTable 非空则从该参数获取字段的映射 - * 如果mappingTable 为空则根据是否存在新生成字段 - * @param selectNode - * @param oldTbName - * @param newTbName - * @param fieldReplaceRef - */ - public static void replaceSelectFieldTable(SqlNode selectNode, - String oldTbName, - String newTbName, - Map fieldReplaceRef) { - if (selectNode.getKind() == AS) { - SqlNode leftNode = ((SqlBasicCall) selectNode).getOperands()[0]; - replaceSelectFieldTable(leftNode, oldTbName, newTbName, fieldReplaceRef); - - }else if(selectNode.getKind() == IDENTIFIER){ - SqlIdentifier sqlIdentifier = (SqlIdentifier) selectNode; - - if(sqlIdentifier.names.size() == 1){ - return ; - } - - String fieldTableName = sqlIdentifier.names.get(0); - if(oldTbName.equalsIgnoreCase(fieldTableName)){ - replaceOneSelectField(sqlIdentifier, newTbName, oldTbName, fieldReplaceRef); - } - - }else if(selectNode.getKind() == LITERAL || selectNode.getKind() == LITERAL_CHAIN){//字面含义 - return; - } else if (isCommonExpression(selectNode)) { - SqlBasicCall sqlBasicCall = (SqlBasicCall) selectNode; - for(int i=0; i fieldReplaceRef){ - SqlIdentifier newField = sqlIdentifier.setName(0, newTbName); - String fieldName = sqlIdentifier.names.get(1); - String fieldKey = oldTbName + "." + fieldName; - if(fieldReplaceRef.get(fieldKey) != null){ - String newFieldName = fieldReplaceRef.get(fieldKey).split("\\.")[1]; - newField = newField.setName(1, newFieldName); - } - - sqlIdentifier.assignNamesFrom(newField); - } - - /** - * 替换另外join 表的指定表名为新关联处理的表名称 - * @param condition - * @param oldTabFieldRefNew - */ - public static void replaceJoinFieldRefTableName(SqlNode condition, Map oldTabFieldRefNew){ - if (null == condition || condition.getKind() == LITERAL) { - return; - } - SqlKind joinKind = condition.getKind(); - if(isCommonExpression(condition) || joinKind == EQUALS) { - SqlBasicCall sqlBasicCall = (SqlBasicCall) condition; - for(int i=0; i refTableMap, String tableName){ - String targetTableName = null; - String preTableName; - - do { - preTableName = targetTableName == null ? tableName : targetTableName; - targetTableName = refTableMap.get(preTableName); - } while (targetTableName != null); - - return preTableName; - } - - public static String getTargetRefField(Map refFieldMap, String currFieldName){ - String targetFieldName = null; - String preFieldName; - - do { - preFieldName = targetFieldName == null ? currFieldName : targetFieldName; - targetFieldName = refFieldMap.get(preFieldName); - } while (targetFieldName != null); - - return preFieldName; - } - - public static void replaceWhereCondition(SqlNode parentWhere, String oldTbName, String newTbName, Map fieldReplaceRef){ - - if(parentWhere == null){ - return; - } - - SqlKind kind = parentWhere.getKind(); - if(kind == AND){ - replaceWhereCondition(((SqlBasicCall) parentWhere).getOperands()[0], oldTbName, newTbName, fieldReplaceRef); - replaceWhereCondition(((SqlBasicCall) parentWhere).getOperands()[1], oldTbName, newTbName, fieldReplaceRef); - - } else { - replaceConditionNode(parentWhere, oldTbName, newTbName, fieldReplaceRef); - } - } - - private static void replaceConditionNode(SqlNode selectNode, String oldTbName, String newTbName, Map fieldReplaceRef) { - if(selectNode.getKind() == IDENTIFIER){ - SqlIdentifier sqlIdentifier = (SqlIdentifier) selectNode; - - if(sqlIdentifier.names.size() == 1){ - return; - } - - String tableName = sqlIdentifier.names.asList().get(0); - String tableField = sqlIdentifier.names.asList().get(1); - String fieldKey = tableName + "." + tableField; - - if(tableName.equalsIgnoreCase(oldTbName)){ - - /* - * ****Before replace:***** - * fieldKey: b.department - * fieldReplaceRef : b.department -> a_b_0.department0 - * oldFieldRef: a_b_0.department0 - * oldTbName: b - * oldFieldName: department - * ****After replace:***** - * newTbName: a_b_0 - * newFieldName: department0 - */ - String oldFieldRef = fieldReplaceRef.get(fieldKey); - String newFieldName = (oldFieldRef != null && !StringUtils.substringAfter(oldFieldRef, ".").isEmpty()) ? - StringUtils.substringAfter(oldFieldRef, ".") : tableField; - - SqlIdentifier newField = ((SqlIdentifier)selectNode).setName(0, newTbName); - newField = newField.setName(1, newFieldName); - ((SqlIdentifier)selectNode).assignNamesFrom(newField); - } - return; - }else if(selectNode.getKind() == LITERAL || selectNode.getKind() == LITERAL_CHAIN){//字面含义 - return; - } else if (isCommonExpression(selectNode)) { - SqlBasicCall sqlBasicCall = (SqlBasicCall) selectNode; - for(int i=0; i replaceConditionNode(sqlNode, oldTbName, newTbName, fieldReplaceRef)); - sqlCase.getThenOperands().getList().forEach(sqlNode -> replaceConditionNode(sqlNode, oldTbName, newTbName, fieldReplaceRef)); - replaceConditionNode(sqlCase.getElseOperand(), oldTbName, newTbName, fieldReplaceRef); - } else { - throw new RuntimeException(String.format("not support node kind of %s to replace name now.", selectNode.getKind())); - } - } - - /** - * 获取条件中关联的表信息 - * @param selectNode - * @param fieldInfos - */ - public static void getConditionRefTable(SqlNode selectNode, Set fieldInfos) { - if (selectNode.getKind() == IDENTIFIER) { - SqlIdentifier sqlIdentifier = (SqlIdentifier) selectNode; - - fieldInfos.add(sqlIdentifier.toString()); - return; - } else if (selectNode.getKind() == LITERAL || selectNode.getKind() == LITERAL_CHAIN) {//字面含义 - return; - } else if (isCommonExpression(selectNode) || selectNode.getKind() == POSITION) { - SqlBasicCall sqlBasicCall = (SqlBasicCall) selectNode; - for (int i = 0; i < sqlBasicCall.getOperands().length; i++) { - SqlNode sqlNode = sqlBasicCall.getOperands()[i]; - if (sqlNode instanceof SqlLiteral) { - continue; - } - - if (sqlNode instanceof SqlDataTypeSpec) { - continue; - } - - getConditionRefTable(sqlNode, fieldInfos); - } - - return; - } else if (selectNode.getKind() == OTHER) { - //不处理 - return; - } else if (selectNode.getKind() == CASE) { - SqlCase sqlCase = (SqlCase) selectNode; - - sqlCase.getWhenOperands().getList().forEach(sqlNode -> getConditionRefTable(sqlNode, fieldInfos)); - sqlCase.getThenOperands().getList().forEach(sqlNode -> getConditionRefTable(sqlNode, fieldInfos)); - getConditionRefTable(sqlCase.getElseOperand(), fieldInfos); - } else { - throw new RuntimeException(String.format("not support node kind of %s to replace name now.", selectNode.getKind())); - } - } - - public static String buildTableField(String tableName, String fieldName){ - return String.format("%s.%s", tableName, fieldName); - } - - - public static String buildTableNameWithScope(String tableName, String scope){ - if(StringUtils.isEmpty(scope)){ - return tableName; - } - - return tableName + "_" + scope; - } - - /** - * add constant join fields, using in such as hbase、redis etc kv database - * @param keyMap - */ - public static void addConstant(Map keyMap, AbstractSideTableInfo sideTableInfo) { - List predicateInfos = sideTableInfo.getPredicateInfoes(); - final String name = sideTableInfo.getName(); - for (PredicateInfo info : predicateInfos) { - if (info.getOperatorName().equals("=")) { - String condition = info.getCondition(); - Matcher matcher = stringPattern.matcher(condition); - if (matcher.matches()) { - condition = condition.substring(1, condition.length() - 1); - } - keyMap.put(info.getFieldName(), condition); - } - } - } - public static String buildTableNameWithScope(String leftTableName, String leftTableAlias, String rightTableName, String scope, Set existTableNames){ - //兼容左边表是as 的情况 - String leftStr = Strings.isNullOrEmpty(leftTableName) ? leftTableAlias : leftTableName; - String newName = leftStr + "_" + rightTableName; - if (CollectionUtils.isEmpty(existTableNames)) { - return TableUtils.buildTableNameWithScope(newName, scope); - } - - if (!existTableNames.contains(newName)) { - return TableUtils.buildTableNameWithScope(newName, scope); - } - - return TableUtils.buildTableNameWithScope(newName, scope) + "_" + System.currentTimeMillis(); - } - - /** - * 判断目标查询是否是基于新构建出来的表的窗口group by - * @param sqlNode - * @param newRegisterTableList - * @return - */ - public static boolean checkIsGroupByTimeWindow(SqlNode sqlNode, Collection newRegisterTableList) { - SqlKind sqlKind = sqlNode.getKind(); - switch (sqlKind) { - case SELECT: - SqlSelect selectNode = (SqlSelect) sqlNode; - SqlNodeList groupNodeList = selectNode.getGroup(); - if ( groupNodeList == null || groupNodeList.size() == 0) { - return false; - } - - SqlNode fromNode = selectNode.getFrom(); - if (fromNode.getKind() != IDENTIFIER - && fromNode.getKind() != AS) { - return false; - } - - if(selectNode.getFrom().getKind() == AS){ - SqlNode asNode = ((SqlBasicCall) selectNode.getFrom()).getOperands()[0]; - if(asNode.getKind() != IDENTIFIER){ - return false; - } - - fromNode = asNode; - } - - String tableName = fromNode.toString(); - for (SqlNode node : groupNodeList.getList()) { - if (node.getKind() == OTHER_FUNCTION) { - String functionName = ((SqlBasicCall) node).getOperator().toString().toLowerCase(); - boolean isTimeGroupByFunction = checkIsTimeGroupByFunction(functionName); - if(isTimeGroupByFunction && newRegisterTableList.contains(tableName)){ - return true; - } - } - } - - return false; - case INSERT: - return checkIsGroupByTimeWindow(((SqlInsert) sqlNode).getSource(), newRegisterTableList); - case UNION: - SqlNode unionLeft = ((SqlBasicCall) sqlNode).getOperands()[0]; - SqlNode unionRight = ((SqlBasicCall) sqlNode).getOperands()[1]; - return checkIsGroupByTimeWindow(unionLeft, newRegisterTableList) - || checkIsGroupByTimeWindow(unionRight, newRegisterTableList); - - default: - return false; - - } - } - - /** - * 判断group by中是否包含维表,包含则需要撤回,不管嵌套多少层子查询只要有一层包含都需要撤回 - * - * @param sqlNode sql语句 - * @param newRegisterTableList 维表集合 - * @return true:需要撤回,false:和原生保持一样 - */ - public static boolean checkIsDimTableGroupBy(SqlNode sqlNode, Collection newRegisterTableList) { - // 维表集合为空 - if (newRegisterTableList == null || newRegisterTableList.size() == 0) { - return false; - } - SqlKind sqlKind = sqlNode.getKind(); - switch (sqlKind) { - case SELECT: - SqlSelect selectNode = (SqlSelect) sqlNode; - SqlNodeList groupNodeList = selectNode.getGroup(); - SqlNode fromNode = selectNode.getFrom(); - - // 1.(sub query) group by - // 2.(sub query) as alias group by - // 3.tableName group by - // 4.tableName as alias group by - // 5.others return false - - // (子查询) group by:1.(sub query) group by - if (fromNode.getKind() == SELECT) { - return checkIsDimTableGroupBy(fromNode, newRegisterTableList); - } - - // 表名 as 别名 group by、(子查询) as 别名 group by、表名 group by - if (fromNode.getKind() == AS || fromNode.getKind() == IDENTIFIER) { - SqlNode operand; - // 表名 group by:3.tableName group by - if (fromNode.getKind() == IDENTIFIER) { - operand = fromNode; - } else { - // 表名 as 别名 group by:4.tableName as alias group by - operand = ((SqlBasicCall) fromNode).getOperands()[0]; - // (子查询) as 别名 group by:2.(sub query) as alias group by - if (operand.getKind() != IDENTIFIER) { - return checkIsDimTableGroupBy(fromNode, newRegisterTableList); - } - } - - // 最里层是表名 group by,且group by字段不为空,且表名包含在维表中 - if (operand.getKind() == IDENTIFIER - && groupNodeList != null - && groupNodeList.size() != 0 - && newRegisterTableList.contains(operand.toString())) { - return checkGroupByNode(groupNodeList); - } - } - - return false; - case INSERT: - return checkIsDimTableGroupBy(((SqlInsert) sqlNode).getSource(), newRegisterTableList); - case UNION: - SqlNode unionLeft = ((SqlBasicCall) sqlNode).getOperands()[0]; - SqlNode unionRight = ((SqlBasicCall) sqlNode).getOperands()[1]; - return checkIsDimTableGroupBy(unionLeft, newRegisterTableList) - || checkIsDimTableGroupBy(unionRight, newRegisterTableList); - case AS: - SqlNode info = ((SqlBasicCall) sqlNode).getOperands()[0]; - return checkIsDimTableGroupBy(info, newRegisterTableList); - default: - return false; - } - } - - /** - * 遍历每一个group by节点,判断是否需要撤回 - * @param groupNodeList - * @return - */ - private static boolean checkGroupByNode(SqlNodeList groupNodeList) { - boolean isRetract = false; - // 判断完所有的group by字段 - for (SqlNode node : groupNodeList.getList()) { - // 判断是否有函数 - if (node.getKind() == OTHER_FUNCTION) { - String functionName = ((SqlBasicCall) node).getOperator().toString().toLowerCase(); - boolean isTimeGroupByFunction = checkIsTimeGroupByFunction(functionName); - // 只要有窗口就不需要撤回,直接返回 - if (isTimeGroupByFunction) { - return false; - } - // 非窗口需要撤回,继续迭代后面的字段 - isRetract = true; - } else { - // 其他情况需要撤回,继续迭代后面的字段 - isRetract = true; - } - } - return isRetract; - } - - public static boolean checkIsTimeGroupByFunction(String functionName ){ - return functionName.equalsIgnoreCase("tumble") - || functionName.equalsIgnoreCase("session") - || functionName.equalsIgnoreCase("hop"); - } - - private static boolean isCommonExpression(SqlNode sqlNode) { - return AGGREGATE.contains(sqlNode.getKind()) - || AVG_AGG_FUNCTIONS.contains(sqlNode.getKind()) - || COMPARISON.contains(sqlNode.getKind()) - || sqlNode.getKind() == OTHER_FUNCTION - || sqlNode.getKind() == DIVIDE - || sqlNode.getKind() == CAST - || sqlNode.getKind() == TRIM - || sqlNode.getKind() == TIMES - || sqlNode.getKind() == PLUS - || sqlNode.getKind() == NOT_IN - || sqlNode.getKind() == OR - || sqlNode.getKind() == AND - || sqlNode.getKind() == MINUS - || sqlNode.getKind() == TUMBLE - || sqlNode.getKind() == TUMBLE_START - || sqlNode.getKind() == TUMBLE_END - || sqlNode.getKind() == SESSION - || sqlNode.getKind() == SESSION_START - || sqlNode.getKind() == SESSION_END - || sqlNode.getKind() == HOP - || sqlNode.getKind() == HOP_START - || sqlNode.getKind() == HOP_END - || sqlNode.getKind() == BETWEEN - || sqlNode.getKind() == IS_NULL - || sqlNode.getKind() == IS_NOT_NULL - || sqlNode.getKind() == CONTAINS - || sqlNode.getKind() == TIMESTAMP_ADD - || sqlNode.getKind() == TIMESTAMP_DIFF - || sqlNode.getKind() == LIKE - || sqlNode.getKind() == COALESCE; - } -} diff --git a/core/src/main/java/com/dtstack/flink/sql/util/ThreadUtil.java b/core/src/main/java/com/dtstack/flink/sql/util/ThreadUtil.java deleted file mode 100644 index 101ef1f3a..000000000 --- a/core/src/main/java/com/dtstack/flink/sql/util/ThreadUtil.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.util; - -import java.util.concurrent.TimeUnit; - -/** - * @author tiezhu - * Date 2020-12-25 - * Company dtstack - */ -public class ThreadUtil { - public static final Long DEFAULT_SLEEP_TIME = 10L; - - public static void sleepSeconds(long timeout) { - try { - TimeUnit.SECONDS.sleep(timeout); - } catch (InterruptedException ie) { - throw new RuntimeException(ie); - } - } - - public static void sleepMinutes(long timeout) { - try { - TimeUnit.MINUTES.sleep(timeout); - } catch (InterruptedException ie) { - throw new RuntimeException(ie); - } - } - - public static void sleepMicroseconds(long timeout) { - try { - TimeUnit.MICROSECONDS.sleep(timeout); - } catch (InterruptedException ie) { - throw new RuntimeException(ie); - } - } - - public static void sleepMilliseconds(long timeout) { - try { - TimeUnit.MILLISECONDS.sleep(timeout); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - } -} diff --git a/core/src/main/java/com/dtstack/flink/sql/util/TypeInfoDataTypeConverter.java b/core/src/main/java/com/dtstack/flink/sql/util/TypeInfoDataTypeConverter.java deleted file mode 100644 index aa4005b8e..000000000 --- a/core/src/main/java/com/dtstack/flink/sql/util/TypeInfoDataTypeConverter.java +++ /dev/null @@ -1,407 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.util; - -import org.apache.flink.annotation.Internal; -import org.apache.flink.api.common.typeinfo.BasicArrayTypeInfo; -import org.apache.flink.api.common.typeinfo.PrimitiveArrayTypeInfo; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.common.typeinfo.Types; -import org.apache.flink.api.common.typeutils.CompositeType; -import org.apache.flink.api.java.typeutils.MapTypeInfo; -import org.apache.flink.api.java.typeutils.MultisetTypeInfo; -import org.apache.flink.api.java.typeutils.ObjectArrayTypeInfo; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.table.api.DataTypes; -import org.apache.flink.table.api.TableException; -import org.apache.flink.table.types.AtomicDataType; -import org.apache.flink.table.types.CollectionDataType; -import org.apache.flink.table.types.DataType; -import org.apache.flink.table.types.FieldsDataType; -import org.apache.flink.table.types.KeyValueDataType; -import org.apache.flink.table.types.logical.LegacyTypeInformationType; -import org.apache.flink.table.types.logical.LogicalType; -import org.apache.flink.table.types.logical.LogicalTypeRoot; -import org.apache.flink.table.types.logical.RowType; -import org.apache.flink.table.types.logical.TimestampKind; -import org.apache.flink.table.types.logical.TimestampType; -import org.apache.flink.table.types.logical.TypeInformationRawType; -import org.apache.flink.table.typeutils.TimeIndicatorTypeInfo; -import org.apache.flink.table.typeutils.TimeIntervalTypeInfo; -import org.apache.flink.types.Row; -import org.apache.flink.util.Preconditions; - -import java.sql.Timestamp; -import java.time.Instant; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.util.HashMap; -import java.util.Map; -import java.util.stream.IntStream; -import java.util.stream.Stream; - -import static org.apache.flink.table.types.logical.utils.LogicalTypeChecks.hasRoot; -import static org.apache.flink.table.types.logical.utils.LogicalTypeChecks.isRowtimeAttribute; - -/** - * Converter between {@link TypeInformation} and {@link DataType} that reflects the behavior before - * Flink 1.9. The conversion is a 1:1 mapping that allows back-and-forth conversion. Note that nullability - * constraints might get lost during the back-and-forth conversion. - * - *

This converter only exists to still support deprecated methods that take or return {@link TypeInformation}. - * Some methods will still support type information in the future, however, the future type information - * support will integrate nicer with the new type stack. - * - *

This converter reflects the old behavior that includes: - * - *

    - *
  • Use old {@code java.sql.*} time classes for time data types.
  • - * - *
  • Only support millisecond precision for timestamps or day-time intervals.
  • - * - *
  • Let variable precision and scale for decimal types pass through the planner.
  • - * - *
  • Inconsistent nullability. Most types are nullable even though type information does not support it.
  • - * - *
  • Distinction between {@link BasicArrayTypeInfo} and {@link ObjectArrayTypeInfo}.
  • - * - *
  • Let POJOs, case classes, and tuples pass through the planner.
  • - *
- * - *

Any changes here need to be applied to the legacy planner as well. - */ -@Internal -public final class TypeInfoDataTypeConverter { - - private static final Map, DataType> typeInfoDataTypeMap = new HashMap<>(); - private static final Map> dataTypeTypeInfoMap = new HashMap<>(); - static { - addMapping(Types.STRING, DataTypes.STRING().bridgedTo(String.class)); - addMapping(Types.BOOLEAN, DataTypes.BOOLEAN().bridgedTo(Boolean.class)); - addMapping(Types.BYTE, DataTypes.TINYINT().bridgedTo(Byte.class)); - addMapping(Types.SHORT, DataTypes.SMALLINT().bridgedTo(Short.class)); - addMapping(Types.INT, DataTypes.INT().bridgedTo(Integer.class)); - addMapping(Types.LONG, DataTypes.BIGINT().bridgedTo(Long.class)); - addMapping(Types.FLOAT, DataTypes.FLOAT().bridgedTo(Float.class)); - addMapping(Types.DOUBLE, DataTypes.DOUBLE().bridgedTo(Double.class)); - addMapping(Types.BIG_DEC, createLegacyType(LogicalTypeRoot.DECIMAL, Types.BIG_DEC)); - addMapping(Types.LOCAL_DATE, DataTypes.DATE().bridgedTo(LocalDate.class)); - addMapping(Types.LOCAL_TIME, DataTypes.TIME(0).bridgedTo(LocalTime.class)); - addMapping(Types.LOCAL_DATE_TIME, DataTypes.TIMESTAMP(3).bridgedTo(LocalDateTime.class)); - addMapping(Types.INSTANT, DataTypes.TIMESTAMP_WITH_LOCAL_TIME_ZONE(3).bridgedTo(Instant.class)); - addMapping(Types.SQL_DATE, DataTypes.DATE().bridgedTo(java.sql.Date.class)); - addMapping(Types.SQL_TIME, DataTypes.TIME(0).bridgedTo(java.sql.Time.class)); - addMapping(Types.SQL_TIMESTAMP, DataTypes.TIMESTAMP(3).bridgedTo(java.sql.Timestamp.class)); - addMapping( - TimeIntervalTypeInfo.INTERVAL_MONTHS, - DataTypes.INTERVAL(DataTypes.MONTH()).bridgedTo(Integer.class)); - addMapping( - TimeIntervalTypeInfo.INTERVAL_MILLIS, - DataTypes.INTERVAL(DataTypes.SECOND(3)).bridgedTo(Long.class)); - addMapping( - PrimitiveArrayTypeInfo.BOOLEAN_PRIMITIVE_ARRAY_TYPE_INFO, - DataTypes.ARRAY(DataTypes.BOOLEAN().notNull().bridgedTo(boolean.class)).bridgedTo(boolean[].class)); - addMapping( - PrimitiveArrayTypeInfo.BYTE_PRIMITIVE_ARRAY_TYPE_INFO, - DataTypes.BYTES().bridgedTo(byte[].class)); - addMapping( - PrimitiveArrayTypeInfo.SHORT_PRIMITIVE_ARRAY_TYPE_INFO, - DataTypes.ARRAY(DataTypes.SMALLINT().notNull().bridgedTo(short.class)).bridgedTo(short[].class)); - addMapping( - PrimitiveArrayTypeInfo.INT_PRIMITIVE_ARRAY_TYPE_INFO, - DataTypes.ARRAY(DataTypes.INT().notNull().bridgedTo(int.class)).bridgedTo(int[].class)); - addMapping( - PrimitiveArrayTypeInfo.LONG_PRIMITIVE_ARRAY_TYPE_INFO, - DataTypes.ARRAY(DataTypes.BIGINT().notNull().bridgedTo(long.class)).bridgedTo(long[].class)); - addMapping( - PrimitiveArrayTypeInfo.FLOAT_PRIMITIVE_ARRAY_TYPE_INFO, - DataTypes.ARRAY(DataTypes.FLOAT().notNull().bridgedTo(float.class)).bridgedTo(float[].class)); - addMapping( - PrimitiveArrayTypeInfo.DOUBLE_PRIMITIVE_ARRAY_TYPE_INFO, - DataTypes.ARRAY(DataTypes.DOUBLE().notNull().bridgedTo(double.class)).bridgedTo(double[].class)); - } - - private static void addMapping(TypeInformation typeInfo, DataType dataType) { - Preconditions.checkArgument(!typeInfoDataTypeMap.containsKey(typeInfo)); - typeInfoDataTypeMap.put(typeInfo, dataType); - dataTypeTypeInfoMap.put(dataType, typeInfo); - } - - public static DataType toDataType(TypeInformation typeInfo) { - // time indicators first as their hashCode/equals is shared with those of regular timestamps - if (typeInfo instanceof TimeIndicatorTypeInfo) { - return convertToTimeAttributeType((TimeIndicatorTypeInfo) typeInfo); - } - - final DataType foundDataType = typeInfoDataTypeMap.get(typeInfo); - if (foundDataType != null) { - return foundDataType; - } - - if (typeInfo instanceof RowTypeInfo) { - return convertToRowType((RowTypeInfo) typeInfo); - } - - else if (typeInfo instanceof ObjectArrayTypeInfo) { - return convertToArrayType( - typeInfo.getTypeClass(), - ((ObjectArrayTypeInfo) typeInfo).getComponentInfo()); - } - - else if (typeInfo instanceof BasicArrayTypeInfo) { - return createLegacyType(LogicalTypeRoot.ARRAY, typeInfo); - } - - else if (typeInfo instanceof MultisetTypeInfo) { - return convertToMultisetType(((MultisetTypeInfo) typeInfo).getElementTypeInfo()); - } - - else if (typeInfo instanceof MapTypeInfo) { - return convertToMapType((MapTypeInfo) typeInfo); - } - - else if (typeInfo instanceof CompositeType) { - return createLegacyType(LogicalTypeRoot.STRUCTURED_TYPE, typeInfo); - } - - return createLegacyType(LogicalTypeRoot.RAW, typeInfo); - } - - public static TypeInformation toLegacyTypeInfo(DataType dataType) { - // time indicators first as their hashCode/equals is shared with those of regular timestamps - if (canConvertToTimeAttributeTypeInfo(dataType)) { - return convertToTimeAttributeTypeInfo((TimestampType) dataType.getLogicalType()); - } - - // check in the map but relax the nullability constraint as every not null data type can be - // stored in the corresponding nullable type information - final TypeInformation foundTypeInfo = dataTypeTypeInfoMap.get(dataType.nullable()); - if (foundTypeInfo != null) { - return foundTypeInfo; - } - - // we are relaxing the constraint for DECIMAL, CHAR, VARCHAR, TIMESTAMP_WITHOUT_TIME_ZONE to - // support value literals in legacy planner - LogicalType logicalType = dataType.getLogicalType(); - if (hasRoot(logicalType, LogicalTypeRoot.DECIMAL)) { - return Types.BIG_DEC; - } - - else if (hasRoot(logicalType, LogicalTypeRoot.CHAR)) { - return Types.STRING; - } - - else if (hasRoot(logicalType, LogicalTypeRoot.VARCHAR)) { - return Types.STRING; - } - - // relax the precision constraint as Timestamp can store the highest precision - else if (hasRoot(logicalType, LogicalTypeRoot.TIMESTAMP_WITHOUT_TIME_ZONE) && - dataType.getConversionClass() == Timestamp.class) { - return Types.SQL_TIMESTAMP; - } - else if(hasRoot(logicalType, LogicalTypeRoot.TIMESTAMP_WITHOUT_TIME_ZONE) && - dataType.getLogicalType() instanceof TimestampType){ - return Types.SQL_TIMESTAMP; - - } - // relax the precision constraint as LocalDateTime can store the highest precision - else if (hasRoot(logicalType, LogicalTypeRoot.TIMESTAMP_WITHOUT_TIME_ZONE) && - dataType.getConversionClass() == LocalDateTime.class) { - return Types.LOCAL_DATE_TIME; - } - - // relax the precision constraint as LocalTime can store the highest precision - else if (hasRoot(logicalType, LogicalTypeRoot.TIME_WITHOUT_TIME_ZONE) && - dataType.getConversionClass() == LocalTime.class) { - return Types.LOCAL_TIME; - } - - else if (canConvertToLegacyTypeInfo(dataType)) { - return convertToLegacyTypeInfo(dataType); - } - - else if (canConvertToRowTypeInfo(dataType)) { - return convertToRowTypeInfo((FieldsDataType) dataType); - } - - // this could also match for basic array type info but this is covered by legacy type info - else if (canConvertToObjectArrayTypeInfo(dataType)) { - return convertToObjectArrayTypeInfo((CollectionDataType) dataType); - } - - else if (canConvertToMultisetTypeInfo(dataType)) { - return convertToMultisetTypeInfo((CollectionDataType) dataType); - } - - else if (canConvertToMapTypeInfo(dataType)) { - return convertToMapTypeInfo((KeyValueDataType) dataType); - } - - // makes the raw type accessible in the legacy planner - else if (canConvertToRawTypeInfo(dataType)) { - return convertToRawTypeInfo(dataType); - } - - throw new TableException( - String.format( - "Unsupported conversion from data type '%s' (conversion class: %s) to type information. Only data types " + - "that originated from type information fully support a reverse conversion.", - dataType, - dataType.getConversionClass().getName())); - } - - private static DataType createLegacyType(LogicalTypeRoot typeRoot, TypeInformation typeInfo) { - return new AtomicDataType(new LegacyTypeInformationType<>(typeRoot, typeInfo)) - .bridgedTo(typeInfo.getTypeClass()); - } - - private static DataType convertToTimeAttributeType(TimeIndicatorTypeInfo timeIndicatorTypeInfo) { - final TimestampKind kind; - if (timeIndicatorTypeInfo.isEventTime()) { - kind = TimestampKind.ROWTIME; - } else { - kind = TimestampKind.PROCTIME; - } - return new AtomicDataType(new TimestampType(true, kind, 3)) - .bridgedTo(java.sql.Timestamp.class); - } - - private static boolean canConvertToTimeAttributeTypeInfo(DataType dataType) { - return hasRoot(dataType.getLogicalType(), LogicalTypeRoot.TIMESTAMP_WITHOUT_TIME_ZONE) && - dataTypeTypeInfoMap.containsKey(dataType) && // checks precision and conversion - ((TimestampType) dataType.getLogicalType()).getKind() != TimestampKind.REGULAR; - } - - private static TypeInformation convertToTimeAttributeTypeInfo(TimestampType timestampType) { - if (isRowtimeAttribute(timestampType)) { - return TimeIndicatorTypeInfo.ROWTIME_INDICATOR; - } else { - return TimeIndicatorTypeInfo.PROCTIME_INDICATOR; - } - } - - private static DataType convertToRowType(RowTypeInfo rowTypeInfo) { - final String[] fieldNames = rowTypeInfo.getFieldNames(); - final DataTypes.Field[] fields = IntStream.range(0, rowTypeInfo.getArity()) - .mapToObj(i -> { - DataType fieldType = toDataType(rowTypeInfo.getTypeAt(i)); - - return DataTypes.FIELD( - fieldNames[i], - fieldType); - }) - .toArray(DataTypes.Field[]::new); - - return DataTypes.ROW(fields).bridgedTo(Row.class); - } - - private static boolean canConvertToRowTypeInfo(DataType dataType) { - return hasRoot(dataType.getLogicalType(), LogicalTypeRoot.ROW) && - dataType.getConversionClass().equals(Row.class) && - ((RowType) dataType.getLogicalType()).getFields().stream() - .noneMatch(f -> f.getDescription().isPresent()); - } - - private static TypeInformation convertToRowTypeInfo(FieldsDataType fieldsDataType) { - final RowType rowType = (RowType) fieldsDataType.getLogicalType(); - - final String[] fieldNames = rowType.getFields() - .stream() - .map(RowType.RowField::getName) - .toArray(String[]::new); - - final TypeInformation[] fieldTypes = Stream.of(fieldNames) - .map(name -> fieldsDataType.getFieldDataTypes().get(name)) - .map(org.apache.flink.table.types.utils.LegacyTypeInfoDataTypeConverter::toLegacyTypeInfo) - .toArray(TypeInformation[]::new); - - return Types.ROW_NAMED(fieldNames, fieldTypes); - } - - private static DataType convertToArrayType(Class arrayClass, TypeInformation elementTypeInfo) { - return DataTypes.ARRAY(toDataType(elementTypeInfo)).bridgedTo(arrayClass); - } - - private static boolean canConvertToObjectArrayTypeInfo(DataType dataType) { - return hasRoot(dataType.getLogicalType(), LogicalTypeRoot.ARRAY) && - dataType.getConversionClass().isArray(); - } - - private static TypeInformation convertToObjectArrayTypeInfo(CollectionDataType collectionDataType) { - // Types.OBJECT_ARRAY would return a basic type info for strings - return ObjectArrayTypeInfo.getInfoFor( - toLegacyTypeInfo(collectionDataType.getElementDataType())); - } - - private static DataType convertToMultisetType(TypeInformation elementTypeInfo) { - return DataTypes.MULTISET(toDataType(elementTypeInfo)).bridgedTo(Map.class); - } - - private static boolean canConvertToMultisetTypeInfo(DataType dataType) { - return hasRoot(dataType.getLogicalType(), LogicalTypeRoot.MULTISET) && - dataType.getConversionClass() == Map.class; - } - - private static TypeInformation convertToMultisetTypeInfo(CollectionDataType collectionDataType) { - return new MultisetTypeInfo<>( - toLegacyTypeInfo(collectionDataType.getElementDataType())); - } - - private static DataType convertToMapType(MapTypeInfo typeInfo) { - return DataTypes.MAP( - toDataType(typeInfo.getKeyTypeInfo()), - toDataType(typeInfo.getValueTypeInfo())) - .bridgedTo(Map.class); - } - - private static boolean canConvertToMapTypeInfo(DataType dataType) { - return hasRoot(dataType.getLogicalType(), LogicalTypeRoot.MAP) && - dataType.getConversionClass() == Map.class; - } - - private static TypeInformation convertToMapTypeInfo(KeyValueDataType dataType) { - return Types.MAP( - toLegacyTypeInfo(dataType.getKeyDataType()), - toLegacyTypeInfo(dataType.getValueDataType())); - } - - private static boolean canConvertToLegacyTypeInfo(DataType dataType) { - return dataType.getLogicalType() instanceof LegacyTypeInformationType; - } - - private static TypeInformation convertToLegacyTypeInfo(DataType dataType) { - return ((LegacyTypeInformationType) dataType.getLogicalType()).getTypeInformation(); - } - - private static boolean canConvertToRawTypeInfo(DataType dataType) { - return dataType.getLogicalType() instanceof TypeInformationRawType && - dataType.getConversionClass().equals( - ((TypeInformationRawType) dataType.getLogicalType()).getTypeInformation().getTypeClass()); - } - - private static TypeInformation convertToRawTypeInfo(DataType dataType) { - return ((TypeInformationRawType) dataType.getLogicalType()).getTypeInformation(); - } - - private TypeInfoDataTypeConverter() { - // no instantiation - } -} - diff --git a/core/src/main/java/com/dtstack/flink/sql/watermarker/AbstractCustomerWaterMarker.java b/core/src/main/java/com/dtstack/flink/sql/watermarker/AbsCustomerWaterMarker.java similarity index 82% rename from core/src/main/java/com/dtstack/flink/sql/watermarker/AbstractCustomerWaterMarker.java rename to core/src/main/java/com/dtstack/flink/sql/watermarker/AbsCustomerWaterMarker.java index 9991c7021..c9fbc0f44 100644 --- a/core/src/main/java/com/dtstack/flink/sql/watermarker/AbstractCustomerWaterMarker.java +++ b/core/src/main/java/com/dtstack/flink/sql/watermarker/AbsCustomerWaterMarker.java @@ -21,7 +21,6 @@ import com.dtstack.flink.sql.metric.EventDelayGauge; import com.dtstack.flink.sql.metric.MetricConstant; -import com.dtstack.flink.sql.util.MathUtil; import org.apache.flink.api.common.functions.IterationRuntimeContext; import org.apache.flink.api.common.functions.RichFunction; import org.apache.flink.api.common.functions.RuntimeContext; @@ -29,8 +28,6 @@ import org.apache.flink.streaming.api.functions.timestamps.BoundedOutOfOrdernessTimestampExtractor; import org.apache.flink.streaming.api.windowing.time.Time; -import java.util.TimeZone; - /** * Reason: * Date: 2018/10/18 @@ -38,7 +35,7 @@ * @author xuchao */ -public abstract class AbstractCustomerWaterMarker extends BoundedOutOfOrdernessTimestampExtractor implements RichFunction { +public abstract class AbsCustomerWaterMarker extends BoundedOutOfOrdernessTimestampExtractor implements RichFunction { private static final long serialVersionUID = 1L; @@ -49,13 +46,7 @@ public abstract class AbstractCustomerWaterMarker extends BoundedOutOfOrderne protected transient EventDelayGauge eventDelayGauge; - protected int pos; - - protected long lastTime = 0; - - protected TimeZone timezone; - - public AbstractCustomerWaterMarker(Time maxOutOfOrderness) { + public AbsCustomerWaterMarker(Time maxOutOfOrderness) { super(maxOutOfOrderness); } @@ -92,19 +83,11 @@ public IterationRuntimeContext getIterationRuntimeContext() { public void setRuntimeContext(RuntimeContext t) { this.runtimeContext = t; eventDelayGauge = new EventDelayGauge(); + t.getMetricGroup().getAllVariables().put("", fromSourceTag); t.getMetricGroup().gauge(MetricConstant.DT_EVENT_DELAY_GAUGE, eventDelayGauge); } public void setFromSourceTag(String fromSourceTag) { this.fromSourceTag = fromSourceTag; } - - protected long getExtractTimestamp(Long extractTime){ - - lastTime = extractTime + timezone.getOffset(extractTime); - - eventDelayGauge.setDelayTime(MathUtil.getIntegerVal((System.currentTimeMillis() - extractTime)/1000)); - - return lastTime; - } } diff --git a/core/src/main/java/com/dtstack/flink/sql/watermarker/CustomerWaterMarkerForLong.java b/core/src/main/java/com/dtstack/flink/sql/watermarker/CustomerWaterMarkerForLong.java index 7e852f171..00ae8501b 100644 --- a/core/src/main/java/com/dtstack/flink/sql/watermarker/CustomerWaterMarkerForLong.java +++ b/core/src/main/java/com/dtstack/flink/sql/watermarker/CustomerWaterMarkerForLong.java @@ -35,11 +35,19 @@ * @author xuchao */ -public class CustomerWaterMarkerForLong extends AbstractCustomerWaterMarker { +public class CustomerWaterMarkerForLong extends AbsCustomerWaterMarker { private static final Logger logger = LoggerFactory.getLogger(CustomerWaterMarkerForLong.class); - public CustomerWaterMarkerForLong(Time maxOutOfOrderness, int pos, String timezone) { + private static final long serialVersionUID = 1L; + + private int pos; + + private long lastTime = 0; + + private TimeZone timezone; + + public CustomerWaterMarkerForLong(Time maxOutOfOrderness, int pos,String timezone) { super(maxOutOfOrderness); this.pos = pos; this.timezone= TimeZone.getTimeZone(timezone); @@ -50,7 +58,12 @@ public long extractTimestamp(Row row) { try{ Long extractTime = MathUtil.getLongVal(row.getField(pos)); - return getExtractTimestamp(extractTime); + + lastTime = extractTime + timezone.getOffset(extractTime); + + eventDelayGauge.setDelayTime(MathUtil.getIntegerVal((System.currentTimeMillis() - extractTime)/1000)); + + return lastTime; }catch (Exception e){ logger.error("", e); } diff --git a/core/src/main/java/com/dtstack/flink/sql/watermarker/CustomerWaterMarkerForTimeStamp.java b/core/src/main/java/com/dtstack/flink/sql/watermarker/CustomerWaterMarkerForTimeStamp.java index 9287341dd..1b52b0d88 100644 --- a/core/src/main/java/com/dtstack/flink/sql/watermarker/CustomerWaterMarkerForTimeStamp.java +++ b/core/src/main/java/com/dtstack/flink/sql/watermarker/CustomerWaterMarkerForTimeStamp.java @@ -16,10 +16,11 @@ * limitations under the License. */ - + package com.dtstack.flink.sql.watermarker; +import com.dtstack.flink.sql.util.MathUtil; import org.apache.flink.streaming.api.windowing.time.Time; import org.apache.flink.types.Row; import org.slf4j.Logger; @@ -35,10 +36,18 @@ * @author xuchao */ -public class CustomerWaterMarkerForTimeStamp extends AbstractCustomerWaterMarker { +public class CustomerWaterMarkerForTimeStamp extends AbsCustomerWaterMarker { private static final Logger logger = LoggerFactory.getLogger(CustomerWaterMarkerForTimeStamp.class); + private static final long serialVersionUID = 1L; + + private int pos; + + private long lastTime = 0; + + private TimeZone timezone; + public CustomerWaterMarkerForTimeStamp(Time maxOutOfOrderness, int pos,String timezone) { super(maxOutOfOrderness); this.pos = pos; @@ -49,8 +58,14 @@ public CustomerWaterMarkerForTimeStamp(Time maxOutOfOrderness, int pos,String ti public long extractTimestamp(Row row) { try { Timestamp time = (Timestamp) row.getField(pos); + long extractTime=time.getTime(); - return getExtractTimestamp(extractTime); + + lastTime = extractTime + timezone.getOffset(extractTime); + + eventDelayGauge.setDelayTime(MathUtil.getIntegerVal((System.currentTimeMillis() - extractTime)/1000)); + + return lastTime; } catch (RuntimeException e) { logger.error("", e); } diff --git a/core/src/main/java/com/dtstack/flink/sql/watermarker/WaterMarkerAssigner.java b/core/src/main/java/com/dtstack/flink/sql/watermarker/WaterMarkerAssigner.java index cca369b53..d444c1bac 100644 --- a/core/src/main/java/com/dtstack/flink/sql/watermarker/WaterMarkerAssigner.java +++ b/core/src/main/java/com/dtstack/flink/sql/watermarker/WaterMarkerAssigner.java @@ -20,7 +20,7 @@ package com.dtstack.flink.sql.watermarker; -import com.dtstack.flink.sql.table.AbstractSourceTableInfo; +import com.dtstack.flink.sql.table.SourceTableInfo; import org.apache.flink.api.common.typeinfo.TypeInformation; import org.apache.flink.api.java.typeutils.RowTypeInfo; import com.google.common.base.Strings; @@ -28,7 +28,9 @@ import org.apache.flink.streaming.api.windowing.time.Time; import org.apache.flink.types.Row; import org.apache.flink.util.Preconditions; -import java.sql.Timestamp; + +import java.util.TimeZone; + /** * define watermarker * Date: 2018/6/29 @@ -38,17 +40,21 @@ public class WaterMarkerAssigner { - public boolean checkNeedAssignWaterMarker(AbstractSourceTableInfo tableInfo){ - return !Strings.isNullOrEmpty(tableInfo.getEventTimeField()); + public boolean checkNeedAssignWaterMarker(SourceTableInfo tableInfo){ + if(Strings.isNullOrEmpty(tableInfo.getEventTimeField())){ + return false; + } + + return true; } - public DataStream assignWaterMarker(DataStream dataStream, RowTypeInfo typeInfo, AbstractSourceTableInfo sourceTableInfo){ + public DataStream assignWaterMarker(DataStream dataStream, RowTypeInfo typeInfo, SourceTableInfo sourceTableInfo){ String eventTimeFieldName = sourceTableInfo.getEventTimeField(); int maxOutOrderness = sourceTableInfo.getMaxOutOrderness(); - String timeZone = sourceTableInfo.getTimeZone(); + String timeZone=sourceTableInfo.getTimeZone(); String[] fieldNames = typeInfo.getFieldNames(); TypeInformation[] fieldTypes = typeInfo.getFieldTypes(); @@ -69,11 +75,11 @@ public DataStream assignWaterMarker(DataStream dataStream, RowTypeInfo type TypeInformation fieldType = fieldTypes[pos]; - AbstractCustomerWaterMarker waterMarker = null; - if(fieldType.getTypeClass().isAssignableFrom(Timestamp.class)){ - waterMarker = new CustomerWaterMarkerForTimeStamp(Time.milliseconds(maxOutOrderness), pos, timeZone); - }else if(fieldType.getTypeClass().isAssignableFrom(Long.class)){ - waterMarker = new CustomerWaterMarkerForLong(Time.milliseconds(maxOutOrderness), pos, timeZone); + AbsCustomerWaterMarker waterMarker = null; + if(fieldType.getTypeClass().getTypeName().equalsIgnoreCase("java.sql.Timestamp")){ + waterMarker = new CustomerWaterMarkerForTimeStamp(Time.milliseconds(maxOutOrderness), pos,timeZone); + }else if(fieldType.getTypeClass().getTypeName().equalsIgnoreCase("java.lang.Long")){ + waterMarker = new CustomerWaterMarkerForLong(Time.milliseconds(maxOutOrderness), pos,timeZone); }else{ throw new IllegalArgumentException("not support type of " + fieldType + ", current only support(timestamp, long)."); } diff --git a/core/src/main/java/org/apache/flink/table/planner/plan/QueryOperationConverter.java b/core/src/main/java/org/apache/flink/table/planner/plan/QueryOperationConverter.java deleted file mode 100644 index 980c31d81..000000000 --- a/core/src/main/java/org/apache/flink/table/planner/plan/QueryOperationConverter.java +++ /dev/null @@ -1,662 +0,0 @@ -/* - * 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.planner.plan; - -import org.apache.flink.annotation.Internal; -import org.apache.flink.streaming.api.datastream.DataStream; -import org.apache.flink.table.api.TableException; -import org.apache.flink.table.api.TableSchema; -import org.apache.flink.table.catalog.CatalogManager; -import org.apache.flink.table.catalog.ConnectorCatalogTable; -import org.apache.flink.table.catalog.FunctionLookup; -import org.apache.flink.table.catalog.ObjectIdentifier; -import org.apache.flink.table.catalog.UnresolvedIdentifier; -import org.apache.flink.table.expressions.CallExpression; -import org.apache.flink.table.expressions.Expression; -import org.apache.flink.table.expressions.ExpressionDefaultVisitor; -import org.apache.flink.table.expressions.FieldReferenceExpression; -import org.apache.flink.table.expressions.ResolvedExpression; -import org.apache.flink.table.expressions.ValueLiteralExpression; -import org.apache.flink.table.expressions.resolver.LookupCallResolver; -import org.apache.flink.table.functions.BuiltInFunctionDefinitions; -import org.apache.flink.table.functions.FunctionDefinition; -import org.apache.flink.table.functions.FunctionIdentifier; -import org.apache.flink.table.functions.TableFunction; -import org.apache.flink.table.operations.AggregateQueryOperation; -import org.apache.flink.table.operations.CalculatedQueryOperation; -import org.apache.flink.table.operations.CatalogQueryOperation; -import org.apache.flink.table.operations.DistinctQueryOperation; -import org.apache.flink.table.operations.FilterQueryOperation; -import org.apache.flink.table.operations.JavaDataStreamQueryOperation; -import org.apache.flink.table.operations.JoinQueryOperation; -import org.apache.flink.table.operations.JoinQueryOperation.JoinType; -import org.apache.flink.table.operations.ProjectQueryOperation; -import org.apache.flink.table.operations.QueryOperation; -import org.apache.flink.table.operations.QueryOperationVisitor; -import org.apache.flink.table.operations.ScalaDataStreamQueryOperation; -import org.apache.flink.table.operations.SetQueryOperation; -import org.apache.flink.table.operations.SortQueryOperation; -import org.apache.flink.table.operations.TableSourceQueryOperation; -import org.apache.flink.table.operations.WindowAggregateQueryOperation; -import org.apache.flink.table.operations.WindowAggregateQueryOperation.ResolvedGroupWindow; -import org.apache.flink.table.operations.utils.QueryOperationDefaultVisitor; -import org.apache.flink.table.planner.calcite.FlinkContext; -import org.apache.flink.table.planner.calcite.FlinkRelBuilder; -import org.apache.flink.table.planner.calcite.FlinkTypeFactory; -import org.apache.flink.table.planner.expressions.PlannerProctimeAttribute; -import org.apache.flink.table.planner.expressions.PlannerRowtimeAttribute; -import org.apache.flink.table.planner.expressions.PlannerWindowEnd; -import org.apache.flink.table.planner.expressions.PlannerWindowReference; -import org.apache.flink.table.planner.expressions.PlannerWindowStart; -import org.apache.flink.table.planner.expressions.RexNodeExpression; -import org.apache.flink.table.planner.expressions.SqlAggFunctionVisitor; -import org.apache.flink.table.planner.expressions.converter.ExpressionConverter; -import org.apache.flink.table.planner.functions.utils.TableSqlFunction; -import org.apache.flink.table.planner.operations.DataStreamQueryOperation; -import org.apache.flink.table.planner.operations.PlannerQueryOperation; -import org.apache.flink.table.planner.operations.RichTableSourceQueryOperation; -import org.apache.flink.table.planner.plan.logical.LogicalWindow; -import org.apache.flink.table.planner.plan.logical.SessionGroupWindow; -import org.apache.flink.table.planner.plan.logical.SlidingGroupWindow; -import org.apache.flink.table.planner.plan.logical.TumblingGroupWindow; -import org.apache.flink.table.planner.plan.schema.DataStreamTable; -import org.apache.flink.table.planner.plan.schema.DataStreamTable$; -import org.apache.flink.table.planner.plan.schema.TableSourceTable; -import org.apache.flink.table.planner.plan.schema.TypedFlinkTableFunction; -import org.apache.flink.table.planner.plan.stats.FlinkStatistic; -import org.apache.flink.table.planner.sources.TableSourceUtil; -import org.apache.flink.table.sources.LookupableTableSource; -import org.apache.flink.table.sources.StreamTableSource; -import org.apache.flink.table.sources.TableSource; -import org.apache.flink.table.types.DataType; -import org.apache.flink.util.Preconditions; - -import org.apache.calcite.rel.RelNode; -import org.apache.calcite.rel.core.CorrelationId; -import org.apache.calcite.rel.core.JoinRelType; -import org.apache.calcite.rel.logical.LogicalTableFunctionScan; -import org.apache.calcite.rel.logical.LogicalTableScan; -import org.apache.calcite.rel.type.RelDataType; -import org.apache.calcite.rex.RexNode; -import org.apache.calcite.sql.SqlAggFunction; -import org.apache.calcite.tools.RelBuilder; -import org.apache.calcite.tools.RelBuilder.AggCall; -import org.apache.calcite.tools.RelBuilder.GroupKey; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Optional; -import java.util.Set; -import java.util.stream.Collectors; - -import scala.Some; - -import static java.util.Arrays.asList; -import static java.util.stream.Collectors.toList; -import static org.apache.flink.table.expressions.ExpressionUtils.extractValue; -import static org.apache.flink.table.expressions.utils.ApiExpressionUtils.isFunctionOfKind; -import static org.apache.flink.table.functions.BuiltInFunctionDefinitions.AS; -import static org.apache.flink.table.functions.FunctionKind.AGGREGATE; -import static org.apache.flink.table.functions.FunctionKind.TABLE_AGGREGATE; -import static org.apache.flink.table.types.utils.TypeConversions.fromDataToLogicalType; -import static org.apache.flink.table.types.utils.TypeConversions.fromLegacyInfoToDataType; - -/** - * Converter from Flink's specific relational representation: {@link QueryOperation} to Calcite's specific relational - * representation: {@link RelNode}. - */ -@Internal -public class QueryOperationConverter extends QueryOperationDefaultVisitor { - - private final FlinkRelBuilder relBuilder; - private final SingleRelVisitor singleRelVisitor = new SingleRelVisitor(); - private final LookupCallResolver callResolver; - private final ExpressionConverter expressionConverter; - private final AggregateVisitor aggregateVisitor = new AggregateVisitor(); - private final TableAggregateVisitor tableAggregateVisitor = new TableAggregateVisitor(); - private final JoinExpressionVisitor joinExpressionVisitor = new JoinExpressionVisitor(); - private static boolean isAccRetract = false; - private static boolean producesUpdates = false; - - public QueryOperationConverter(FlinkRelBuilder relBuilder, FunctionLookup functionCatalog) { - this.relBuilder = relBuilder; - this.callResolver = new LookupCallResolver(functionCatalog); - this.expressionConverter = new ExpressionConverter(relBuilder); - } - - public static void setAccRetract(boolean isAccRetract){ - QueryOperationConverter.isAccRetract = isAccRetract; - } - - public static void setProducesUpdates(boolean producesUpdates){ - QueryOperationConverter.producesUpdates = producesUpdates; - } - - @Override - public RelNode defaultMethod(QueryOperation other) { - other.getChildren().forEach(child -> relBuilder.push(child.accept(this))); - return other.accept(singleRelVisitor); - } - - private class SingleRelVisitor implements QueryOperationVisitor { - - @Override - public RelNode visit(ProjectQueryOperation projection) { - List rexNodes = convertToRexNodes(projection.getProjectList()); - - return relBuilder.project(rexNodes, asList(projection.getTableSchema().getFieldNames()), true).build(); - } - - @Override - public RelNode visit(AggregateQueryOperation aggregate) { - List aggregations = aggregate.getAggregateExpressions() - .stream() - .map(this::getAggCall) - .collect(toList()); - - List groupings = convertToRexNodes(aggregate.getGroupingExpressions()); - GroupKey groupKey = relBuilder.groupKey(groupings); - return relBuilder.aggregate(groupKey, aggregations).build(); - } - - @Override - public RelNode visit(WindowAggregateQueryOperation windowAggregate) { - List aggregations = windowAggregate.getAggregateExpressions() - .stream() - .map(this::getAggCall) - .collect(toList()); - - List groupings = convertToRexNodes(windowAggregate.getGroupingExpressions()); - LogicalWindow logicalWindow = toLogicalWindow(windowAggregate.getGroupWindow()); - PlannerWindowReference windowReference = logicalWindow.aliasAttribute(); - List windowProperties = windowAggregate - .getWindowPropertiesExpressions() - .stream() - .map(expr -> convertToWindowProperty(expr.accept(callResolver), windowReference)) - .collect(toList()); - GroupKey groupKey = relBuilder.groupKey(groupings); - return relBuilder.windowAggregate(logicalWindow, groupKey, windowProperties, aggregations).build(); - } - - private FlinkRelBuilder.PlannerNamedWindowProperty convertToWindowProperty(Expression expression, - PlannerWindowReference windowReference) { - Preconditions.checkArgument(expression instanceof CallExpression, "This should never happened"); - CallExpression aliasExpr = (CallExpression) expression; - Preconditions.checkArgument( - BuiltInFunctionDefinitions.AS == aliasExpr.getFunctionDefinition(), - "This should never happened"); - String name = ((ValueLiteralExpression) aliasExpr.getChildren().get(1)).getValueAs(String.class) - .orElseThrow( - () -> new TableException("Invalid literal.")); - Expression windowPropertyExpr = aliasExpr.getChildren().get(0); - Preconditions.checkArgument(windowPropertyExpr instanceof CallExpression, "This should never happened"); - CallExpression windowPropertyCallExpr = (CallExpression) windowPropertyExpr; - FunctionDefinition fd = windowPropertyCallExpr.getFunctionDefinition(); - if (BuiltInFunctionDefinitions.WINDOW_START == fd) { - return new FlinkRelBuilder.PlannerNamedWindowProperty(name, new PlannerWindowStart(windowReference)); - } else if (BuiltInFunctionDefinitions.WINDOW_END == fd) { - return new FlinkRelBuilder.PlannerNamedWindowProperty(name, new PlannerWindowEnd(windowReference)); - } else if (BuiltInFunctionDefinitions.PROCTIME == fd) { - return new FlinkRelBuilder.PlannerNamedWindowProperty(name, new PlannerProctimeAttribute(windowReference)); - } else if (BuiltInFunctionDefinitions.ROWTIME == fd) { - return new FlinkRelBuilder.PlannerNamedWindowProperty(name, new PlannerRowtimeAttribute(windowReference)); - } else { - throw new TableException("Invalid literal."); - } - } - - /** - * Get the {@link AggCall} correspond to the aggregate or table aggregate expression. - */ - private AggCall getAggCall(Expression aggregateExpression) { - if (isFunctionOfKind(aggregateExpression, TABLE_AGGREGATE)) { - return aggregateExpression.accept(tableAggregateVisitor); - } else { - return aggregateExpression.accept(aggregateVisitor); - } - } - - @Override - public RelNode visit(JoinQueryOperation join) { - final Set corSet; - if (join.isCorrelated()) { - corSet = Collections.singleton(relBuilder.peek().getCluster().createCorrel()); - } else { - corSet = Collections.emptySet(); - } - - return relBuilder.join( - convertJoinType(join.getJoinType()), - join.getCondition().accept(joinExpressionVisitor), - corSet) - .build(); - } - - @Override - public RelNode visit(SetQueryOperation setOperation) { - switch (setOperation.getType()) { - case INTERSECT: - relBuilder.intersect(setOperation.isAll()); - break; - case MINUS: - relBuilder.minus(setOperation.isAll()); - break; - case UNION: - relBuilder.union(setOperation.isAll()); - break; - } - return relBuilder.build(); - } - - @Override - public RelNode visit(FilterQueryOperation filter) { - RexNode rexNode = convertExprToRexNode(filter.getCondition()); - return relBuilder.filter(rexNode).build(); - } - - @Override - public RelNode visit(DistinctQueryOperation distinct) { - return relBuilder.distinct().build(); - } - - @Override - public RelNode visit(SortQueryOperation sort) { - List rexNodes = convertToRexNodes(sort.getOrder()); - return relBuilder.sortLimit(sort.getOffset(), sort.getFetch(), rexNodes) - .build(); - } - - @Override - public RelNode visit(CalculatedQueryOperation calculatedTable) { - DataType resultType = fromLegacyInfoToDataType(calculatedTable.getResultType()); - TableFunction tableFunction = calculatedTable.getTableFunction(); - String[] fieldNames = calculatedTable.getTableSchema().getFieldNames(); - - TypedFlinkTableFunction function = new TypedFlinkTableFunction( - tableFunction, fieldNames, resultType); - - FlinkTypeFactory typeFactory = relBuilder.getTypeFactory(); - - TableSqlFunction sqlFunction = new TableSqlFunction( - FunctionIdentifier.of(tableFunction.functionIdentifier()), - tableFunction.toString(), - tableFunction, - resultType, - typeFactory, - function, - scala.Option.empty()); - - List parameters = convertToRexNodes(calculatedTable.getParameters()); - - return LogicalTableFunctionScan.create( - relBuilder.peek().getCluster(), - Collections.emptyList(), - relBuilder.call(sqlFunction, parameters), - function.getElementType(null), - function.getRowType(typeFactory, null, null), - null); - } - - @Override - public RelNode visit(CatalogQueryOperation catalogTable) { - ObjectIdentifier objectIdentifier = catalogTable.getTableIdentifier(); - return relBuilder.scan( - objectIdentifier.getCatalogName(), - objectIdentifier.getDatabaseName(), - objectIdentifier.getObjectName() - ).build(); - } - - @Override - public RelNode visit(QueryOperation other) { - if (other instanceof PlannerQueryOperation) { - return ((PlannerQueryOperation) other).getCalciteTree(); - } else if (other instanceof DataStreamQueryOperation) { - return convertToDataStreamScan((DataStreamQueryOperation) other); - } else if (other instanceof JavaDataStreamQueryOperation) { - JavaDataStreamQueryOperation dataStreamQueryOperation = (JavaDataStreamQueryOperation) other; - return convertToDataStreamScan( - dataStreamQueryOperation.getDataStream(), - dataStreamQueryOperation.getFieldIndices(), - dataStreamQueryOperation.getTableSchema(), - dataStreamQueryOperation.getIdentifier()); - } else if (other instanceof ScalaDataStreamQueryOperation) { - ScalaDataStreamQueryOperation dataStreamQueryOperation = (ScalaDataStreamQueryOperation) other; - return convertToDataStreamScan( - dataStreamQueryOperation.getDataStream(), - dataStreamQueryOperation.getFieldIndices(), - dataStreamQueryOperation.getTableSchema(), - dataStreamQueryOperation.getIdentifier()); - } - - throw new TableException("Unknown table operation: " + other); - } - - @Override - public RelNode visit(TableSourceQueryOperation tableSourceOperation) { - TableSource tableSource = tableSourceOperation.getTableSource(); - boolean isBatch; - if (tableSource instanceof LookupableTableSource) { - isBatch = tableSourceOperation.isBatch(); - } else if (tableSource instanceof StreamTableSource) { - isBatch = ((StreamTableSource) tableSource).isBounded(); - } else { - throw new TableException(String.format("%s is not supported.", tableSource.getClass().getSimpleName())); - } - - FlinkStatistic statistic; - ObjectIdentifier tableIdentifier; - if (tableSourceOperation instanceof RichTableSourceQueryOperation && - ((RichTableSourceQueryOperation) tableSourceOperation).getIdentifier() != null) { - tableIdentifier = ((RichTableSourceQueryOperation) tableSourceOperation).getIdentifier(); - statistic = ((RichTableSourceQueryOperation) tableSourceOperation).getStatistic(); - } else { - statistic = FlinkStatistic.UNKNOWN(); - // TableSourceScan requires a unique name of a Table for computing a digest. - // We are using the identity hash of the TableSource object. - String refId = "Unregistered_TableSource_" + System.identityHashCode(tableSource); - CatalogManager catalogManager = relBuilder.getCluster().getPlanner().getContext() - .unwrap(FlinkContext.class).getCatalogManager(); - tableIdentifier = catalogManager.qualifyIdentifier(UnresolvedIdentifier.of(refId)); - } - - RelDataType rowType = TableSourceUtil.getSourceRowType(relBuilder.getTypeFactory(), - tableSourceOperation.getTableSchema(), - scala.Option.apply(tableSource), - !isBatch); - TableSourceTable tableSourceTable = new TableSourceTable<>( - relBuilder.getRelOptSchema(), - tableIdentifier, - rowType, - statistic, - tableSource, - !isBatch, - ConnectorCatalogTable.source(tableSource, isBatch)); - return LogicalTableScan.create(relBuilder.getCluster(), tableSourceTable); - } - - private RelNode convertToDataStreamScan(DataStreamQueryOperation operation) { - List names; - ObjectIdentifier identifier = operation.getIdentifier(); - if (identifier != null) { - names = Arrays.asList( - identifier.getCatalogName(), - identifier.getDatabaseName(), - identifier.getObjectName()); - } else { - String refId = String.format("Unregistered_DataStream_%s", operation.getDataStream().getId()); - names = Collections.singletonList(refId); - } - - final RelDataType rowType = DataStreamTable$.MODULE$ - .getRowType(relBuilder.getTypeFactory(), - operation.getDataStream(), - operation.getTableSchema().getFieldNames(), - operation.getFieldIndices(), - scala.Option.apply(operation.getFieldNullables())); - DataStreamTable dataStreamTable = new DataStreamTable<>( - relBuilder.getRelOptSchema(), - names, - rowType, - operation.getDataStream(), - operation.isProducesUpdates(), - operation.isAccRetract(), - operation.getFieldIndices(), - operation.getTableSchema().getFieldNames(), - operation.getStatistic(), - scala.Option.apply(operation.getFieldNullables())); - return LogicalTableScan.create(relBuilder.getCluster(), dataStreamTable); - } - - private RelNode convertToDataStreamScan( - DataStream dataStream, - int[] fieldIndices, - TableSchema tableSchema, - Optional identifier) { - List names; - if (identifier.isPresent()) { - names = Arrays.asList( - identifier.get().getCatalogName(), - identifier.get().getDatabaseName(), - identifier.get().getObjectName()); - } else { - String refId = String.format("Unregistered_DataStream_%s", dataStream.getId()); - names = Collections.singletonList(refId); - } - final RelDataType rowType = DataStreamTable$.MODULE$ - .getRowType(relBuilder.getTypeFactory(), - dataStream, - tableSchema.getFieldNames(), - fieldIndices, - scala.Option.empty()); - DataStreamTable dataStreamTable = new DataStreamTable<>( - relBuilder.getRelOptSchema(), - names, - rowType, - dataStream, - producesUpdates, - false, - fieldIndices, - tableSchema.getFieldNames(), - FlinkStatistic.UNKNOWN(), - scala.Option.empty()); - return LogicalTableScan.create(relBuilder.getCluster(), dataStreamTable); - } - - private List convertToRexNodes(List expressions) { - return expressions - .stream() - .map(QueryOperationConverter.this::convertExprToRexNode) - .collect(toList()); - } - - private LogicalWindow toLogicalWindow(ResolvedGroupWindow window) { - DataType windowType = window.getTimeAttribute().getOutputDataType(); - PlannerWindowReference windowReference = new PlannerWindowReference(window.getAlias(), - new Some<>(fromDataToLogicalType(windowType))); - switch (window.getType()) { - case SLIDE: - return new SlidingGroupWindow( - windowReference, - window.getTimeAttribute(), - window.getSize().orElseThrow(() -> new TableException("missed size parameters!")), - window.getSlide().orElseThrow(() -> new TableException("missed slide parameters!")) - ); - case SESSION: - return new SessionGroupWindow( - windowReference, - window.getTimeAttribute(), - window.getGap().orElseThrow(() -> new TableException("missed gap parameters!")) - ); - case TUMBLE: - return new TumblingGroupWindow( - windowReference, - window.getTimeAttribute(), - window.getSize().orElseThrow(() -> new TableException("missed size parameters!")) - ); - default: - throw new TableException("Unknown window type"); - } - } - - private JoinRelType convertJoinType(JoinType joinType) { - switch (joinType) { - case INNER: - return JoinRelType.INNER; - case LEFT_OUTER: - return JoinRelType.LEFT; - case RIGHT_OUTER: - return JoinRelType.RIGHT; - case FULL_OUTER: - return JoinRelType.FULL; - default: - throw new TableException("Unknown join type: " + joinType); - } - } - } - - private class JoinExpressionVisitor extends ExpressionDefaultVisitor { - - private static final int numberOfJoinInputs = 2; - - @Override - public RexNode visit(CallExpression callExpression) { - final List newChildren = callExpression.getChildren().stream().map(expr -> { - RexNode convertedNode = expr.accept(this); - return new RexNodeExpression(convertedNode, ((ResolvedExpression) expr).getOutputDataType()); - }).collect(Collectors.toList()); - - CallExpression newCall; - if (callExpression.getFunctionIdentifier().isPresent()) { - newCall = new CallExpression( - callExpression.getFunctionIdentifier().get(), callExpression.getFunctionDefinition(), newChildren, - callExpression.getOutputDataType()); - } else { - newCall = new CallExpression( - callExpression.getFunctionDefinition(), newChildren, callExpression.getOutputDataType()); - } - return convertExprToRexNode(newCall); - } - - @Override - public RexNode visit(FieldReferenceExpression fieldReference) { - return relBuilder.field(numberOfJoinInputs, fieldReference.getInputIndex(), fieldReference.getFieldIndex()); - } - - @Override - protected RexNode defaultMethod(Expression expression) { - return convertExprToRexNode(expression); - } - } - - private class AggregateVisitor extends ExpressionDefaultVisitor { - - @Override - public AggCall visit(CallExpression unresolvedCall) { - if (unresolvedCall.getFunctionDefinition() == AS) { - String aggregateName = extractValue(unresolvedCall.getChildren().get(1), String.class) - .orElseThrow(() -> new TableException("Unexpected name.")); - - Expression aggregate = unresolvedCall.getChildren().get(0); - if (isFunctionOfKind(aggregate, AGGREGATE)) { - return aggregate.accept(callResolver).accept( - new AggCallVisitor(relBuilder, expressionConverter, aggregateName, false)); - } - } - throw new TableException("Expected named aggregate. Got: " + unresolvedCall); - } - - @Override - protected AggCall defaultMethod(Expression expression) { - throw new TableException("Unexpected expression: " + expression); - } - - private class AggCallVisitor extends ExpressionDefaultVisitor { - - private final RelBuilder relBuilder; - private final SqlAggFunctionVisitor sqlAggFunctionVisitor; - private final ExpressionConverter expressionConverter; - private final String name; - private final boolean isDistinct; - - public AggCallVisitor(RelBuilder relBuilder, ExpressionConverter expressionConverter, String name, - boolean isDistinct) { - this.relBuilder = relBuilder; - this.sqlAggFunctionVisitor = new SqlAggFunctionVisitor((FlinkTypeFactory) relBuilder.getTypeFactory()); - this.expressionConverter = expressionConverter; - this.name = name; - this.isDistinct = isDistinct; - } - - @Override - public RelBuilder.AggCall visit(CallExpression call) { - FunctionDefinition def = call.getFunctionDefinition(); - if (BuiltInFunctionDefinitions.DISTINCT == def) { - Expression innerAgg = call.getChildren().get(0); - return innerAgg.accept(new AggCallVisitor(relBuilder, expressionConverter, name, true)); - } else { - SqlAggFunction sqlAggFunction = call.accept(sqlAggFunctionVisitor); - return relBuilder.aggregateCall( - sqlAggFunction, - isDistinct, - false, - null, - name, - call.getChildren().stream().map(expr -> expr.accept(expressionConverter)) - .collect(Collectors.toList())); - } - } - - @Override - protected RelBuilder.AggCall defaultMethod(Expression expression) { - throw new TableException("Unexpected expression: " + expression); - } - } - } - - private class TableAggregateVisitor extends ExpressionDefaultVisitor { - @Override - public AggCall visit(CallExpression call) { - if (isFunctionOfKind(call, TABLE_AGGREGATE)) { - return call.accept(new TableAggCallVisitor(relBuilder, expressionConverter)); - } - return defaultMethod(call); - } - - @Override - protected AggCall defaultMethod(Expression expression) { - throw new TableException("Expected table aggregate. Got: " + expression); - } - - private class TableAggCallVisitor extends ExpressionDefaultVisitor { - - private final RelBuilder relBuilder; - private final SqlAggFunctionVisitor sqlAggFunctionVisitor; - private final ExpressionConverter expressionConverter; - - public TableAggCallVisitor(RelBuilder relBuilder, ExpressionConverter expressionConverter) { - this.relBuilder = relBuilder; - this.sqlAggFunctionVisitor = new SqlAggFunctionVisitor((FlinkTypeFactory) relBuilder.getTypeFactory()); - this.expressionConverter = expressionConverter; - } - - @Override - public RelBuilder.AggCall visit(CallExpression call) { - SqlAggFunction sqlAggFunction = call.accept(sqlAggFunctionVisitor); - return relBuilder.aggregateCall( - sqlAggFunction, - false, - false, - null, - sqlAggFunction.toString(), - call.getChildren().stream().map(expr -> expr.accept(expressionConverter)).collect(toList())); - } - - @Override - protected RelBuilder.AggCall defaultMethod(Expression expression) { - throw new TableException("Expected table aggregate. Got: " + expression); - } - } - } - - private RexNode convertExprToRexNode(Expression expr) { - return expr.accept(callResolver).accept(expressionConverter); - } -} diff --git a/core/src/test/java/com/dtstack/flink/sql/TestGetPlan.java b/core/src/test/java/com/dtstack/flink/sql/TestGetPlan.java deleted file mode 100644 index 33315dfbe..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/TestGetPlan.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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 com.dtstack.flink.sql; - -import com.dtstack.flink.sql.classloader.DtClassLoader; -import com.dtstack.flink.sql.exec.ApiResult; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ObjectNode; -import org.junit.Assert; -import org.junit.Test; - -import java.io.File; -import java.lang.reflect.Method; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; - -/** - * Date: 2020/2/17 - * Company: www.dtstack.com - * @author maqi - */ -public class TestGetPlan { - - private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); - - // @Test - public void testGetExecutionPlan() throws Exception { - List urls = new ArrayList(); - urls.addAll(getJarUrl("/Users/maqi/tmp/flink/flink-1.8.1/lib")); - - ClassLoader parentClassLoader = Thread.currentThread().getContextClassLoader(); - DtClassLoader childClassLoader = new DtClassLoader(urls.toArray(new URL[urls.size()]), parentClassLoader); - Class aClass = childClassLoader.loadClass("com.dtstack.flink.sql.GetPlan"); - - String[] params = { - "-mode", - "local", - "-sql", - "%0d%0aCREATE+TABLE+MyTable(%0d%0a++++id+INT%2c%0d%0a++++channel+VARCHAR%2c%0d%0a++++pv+varchar%2c%0d%0a++++xctime+varchar%2c%0d%0a++++name+varchar%0d%0a+)WITH(%0d%0a++++type+%3d%27kafka11%27%2c%0d%0a++++bootstrapServers+%3d%27172.16.8.107%3a9092%27%2c%0d%0a++++zookeeperQuorum+%3d%27172.16.8.107%3a2181%2fkafka%27%2c%0d%0a++++offsetReset+%3d%27latest%27%2c%0d%0a++++topic+%3d%27mqTest02%27%2c%0d%0a++++timezone%3d%27Asia%2fShanghai%27%2c%0d%0a++++topicIsPattern+%3d%27false%27%2c%0d%0a++++parallelism+%3d%271%27%0d%0a+)%3b%0d%0a%0d%0a%0d%0aCREATE+TABLE+MyTable2(%0d%0a++++id2+INT%2c%0d%0a++++channel2+VARCHAR%2c%0d%0a++++pv2+varchar%2c%0d%0a++++xctime2+varchar%2c%0d%0a++++name2+varchar%0d%0a+)WITH(%0d%0a++++type+%3d%27kafka11%27%2c%0d%0a++++bootstrapServers+%3d%27172.16.8.107%3a9092%27%2c%0d%0a++++zookeeperQuorum+%3d%27172.16.8.107%3a2181%2fkafka%27%2c%0d%0a++++offsetReset+%3d%27latest%27%2c%0d%0a++++topic+%3d%27mqTest03%27%2c%0d%0a++++timezone%3d%27Asia%2fShanghai%27%2c%0d%0a++++topicIsPattern+%3d%27false%27%2c%0d%0a++++parallelism+%3d%271%27%0d%0a+)%3b%0d%0a%0d%0a%0d%0aCREATE+TABLE+sideTableA(%0d%0a++++id1+INT%2c%0d%0a++++channel1+varchar%2c%0d%0a++++time_info+varchar%2c%0d%0a++++name1+varchar%2c%0d%0a++++PRIMARY+KEY(channel1)+%2c%0d%0a++++PERIOD+FOR+SYSTEM_TIME%0d%0a+)WITH(%0d%0a++++type+%3d%27mysql%27%2c%0d%0a++++url+%3d%27jdbc%3amysql%3a%2f%2f172.16.8.109%3a3306%2ftest%27%2c%0d%0a++++userName+%3d%27dtstack%27%2c%0d%0a++++password+%3d%27abc123%27%2c%0d%0a++++tableName+%3d%27dimA%27%2c%0d%0a++++parallelism+%3d%271%27%2c%0d%0a++++cache+%3d+%27LRU%27%0d%0a%0d%0a+)%3b%0d%0a%0d%0a+CREATE+TABLE+sideTableB(%0d%0a++++id+INT%2c%0d%0a++++channel1+varchar%2c%0d%0a++++address+varchar%2c%0d%0a++++PRIMARY+KEY(channel1)%2c%0d%0a++++PERIOD+FOR+SYSTEM_TIME%0d%0a+)WITH(%0d%0a++++type+%3d%27mysql%27%2c%0d%0a++++url+%3d%27jdbc%3amysql%3a%2f%2f172.16.8.109%3a3306%2ftest%27%2c%0d%0a++++userName+%3d%27dtstack%27%2c%0d%0a++++password+%3d%27abc123%27%2c%0d%0a++++tableName+%3d%27dimB%27%2c%0d%0a++++parallelism+%3d%271%27%2c%0d%0a++++cache+%3d+%27LRU%27%2c%0d%0a++++asyncTimeout+%3d+%271000000%27%0d%0a+)%3b%0d%0a%0d%0aCREATE+TABLE+MyResult(%0d%0a++++xctime+VARCHAR%2c%0d%0a++++name+VARCHAR%2c%0d%0a++++time_info+VARCHAR%2c%0d%0a++++address+VARCHAR%0d%0a+)WITH(%0d%0a+++++type+%3d%27mysql%27%2c%0d%0a++++url+%3d%27jdbc%3amysql%3a%2f%2f172.16.8.109%3a3306%2ftest%27%2c%0d%0a++++userName+%3d%27dtstack%27%2c%0d%0a++++password+%3d%27abc123%27%2c%0d%0a++++tableName+%3d%27dimC%27%2c%0d%0a++++parallelism+%3d%271%27%2c%0d%0a+)%3b%0d%0a%0d%0ainsert+%0d%0ainto%0d%0a++MyResult%0d%0a++++select%0d%0a++++++++t1.xctime+as+xctime%2c%0d%0a++++++++t1.name+as+name%2c%0d%0a++++++++t3.channel1+as+time_info%2c%0d%0a++++++++t3.address+as+address+++++%0d%0a++++from%0d%0a++++++++MyTable+as+t1%0d%0a++++left+join%0d%0a++++++++--MyTable2+m2+%0d%0a++++++++sideTableA+m2+++++++++++++++++++++++++++%0d%0a++++++++on++t1.channel+%3d+m2.channel1%0d%0a++++left+join+sideTableB+t3%0d%0a++++++++on+t1.channel+%3d+t3.channel1%0d%0a%0d%0a%0d%0a", - "-localSqlPluginPath", - "/Users/maqi/code/dtstack/dt-center-flinkStreamSQL/plugins", - "-name","test"}; - - Method getExecutionPlan = aClass.getMethod("getExecutionPlan", String[].class); - String jsonStr = (String) getExecutionPlan.invoke(aClass.newInstance(), (Object)params); - - ObjectNode jsonNodes = OBJECT_MAPPER.readValue(jsonStr, ObjectNode.class); - Assert.assertEquals(jsonNodes.get("code").asLong(), ApiResult.SUCCESS.longValue()); - } - - - public static List getJarUrl(String directory) { - File flinkLibDir = new File(directory); - return Arrays.stream(flinkLibDir.listFiles(((dir1, name) -> name.endsWith(".jar")))).map(file -> { - try { - return file.toURI().toURL(); - } catch (MalformedURLException e) { - throw new RuntimeException(e); - } - - }).collect(Collectors.toList()); - } -} diff --git a/core/src/test/java/com/dtstack/flink/sql/classloader/ClassLoaderManagerTest.java b/core/src/test/java/com/dtstack/flink/sql/classloader/ClassLoaderManagerTest.java deleted file mode 100644 index 239706c87..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/classloader/ClassLoaderManagerTest.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.dtstack.flink.sql.classloader; - -import com.dtstack.flink.sql.util.PluginUtil; -import com.google.common.collect.Lists; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -import java.net.URL; - -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyString; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -@RunWith(PowerMockRunner.class) -@PrepareForTest({ClassLoaderManager.class, PluginUtil.class}) -public class ClassLoaderManagerTest { - - @Test - public void testNewInstance() throws Exception { - String jarPath = "./test.jar"; - DtClassLoader classLoader = mock(DtClassLoader.class); - ClassLoaderSupplier classLoaderSupplier = mock(ClassLoaderSupplier.class); - when(classLoaderSupplier.get(any())).thenReturn(classLoader); - - - PowerMockito.mockStatic(PluginUtil.class); - when(PluginUtil.getPluginJarUrls(anyString())).thenReturn(new URL[1]); - ClassLoaderManager.newInstance(jarPath, classLoaderSupplier); - - } - - // @Test - public void testNewInstanceWithList() throws Exception { - URL jarUrl = new URL("file:./test.jar"); - DtClassLoader classLoader = mock(DtClassLoader.class); - ClassLoaderSupplier classLoaderSupplier = mock(ClassLoaderSupplier.class); - when(classLoaderSupplier.get(any())).thenReturn(classLoader); - - - PowerMockito.mockStatic(PluginUtil.class); - when(PluginUtil.getPluginJarUrls(anyString())).thenReturn(new URL[1]); - ClassLoaderManager.newInstance(Lists.newArrayList(jarUrl), classLoaderSupplier); - - } -} diff --git a/core/src/test/java/com/dtstack/flink/sql/classloader/ClassLoaderSupplierCallBackTest.java b/core/src/test/java/com/dtstack/flink/sql/classloader/ClassLoaderSupplierCallBackTest.java deleted file mode 100644 index 4f42ad214..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/classloader/ClassLoaderSupplierCallBackTest.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.dtstack.flink.sql.classloader; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.modules.junit4.PowerMockRunner; - -import java.net.URL; - -import static org.mockito.Mockito.mock; - -@RunWith(PowerMockRunner.class) -public class ClassLoaderSupplierCallBackTest { - - @Test - public void testCallBackAndRest() throws Exception { - ClassLoaderSupplier classLoaderSupplier = mock(ClassLoaderSupplier.class); - URL[] urls = new URL[1]; - ClassLoaderSupplierCallBack.callbackAndReset(classLoaderSupplier, new DtClassLoader(urls)); - } - -} diff --git a/core/src/test/java/com/dtstack/flink/sql/classloader/DtClassLoaderTest.java b/core/src/test/java/com/dtstack/flink/sql/classloader/DtClassLoaderTest.java deleted file mode 100644 index 21f9ecb6e..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/classloader/DtClassLoaderTest.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.dtstack.flink.sql.classloader; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.modules.junit4.PowerMockRunner; - -import java.net.URL; - -@RunWith(PowerMockRunner.class) -public class DtClassLoaderTest { - - @Test(expected = ClassNotFoundException.class) - public void testLoadClass() throws Exception { - URL[] urls = new URL[1]; - urls[0] = new URL("file:./test.jar"); - DtClassLoader dtClassLoader = new DtClassLoader(urls); - dtClassLoader.loadClass("test"); - } - - @Test - public void testGetResource() throws Exception { - URL[] urls = new URL[1]; - urls[0] = new URL("file:./test.jar"); - DtClassLoader dtClassLoader = new DtClassLoader(urls, Thread.currentThread().getContextClassLoader()); - dtClassLoader.getResource("test"); - } - - @Test - public void testAddURL() throws Exception { - URL[] urls = new URL[1]; - urls[0] = new URL("file:./test.jar"); - DtClassLoader dtClassLoader = new DtClassLoader(urls); - dtClassLoader.addURL(urls[0]); - } - - @Test - public void testGetResources() throws Exception { - URL[] urls = new URL[1]; - urls[0] = new URL("file:./test.jar"); - DtClassLoader dtClassLoader = new DtClassLoader(urls, Thread.currentThread().getContextClassLoader()); - dtClassLoader.getResources("test"); - } - - @Test - public void testFindResources() throws Exception { - URL[] urls = new URL[1]; - urls[0] = new URL("file:./test.jar"); - DtClassLoader dtClassLoader = new DtClassLoader(urls, Thread.currentThread().getContextClassLoader()); - dtClassLoader.findResources("test"); - } -} diff --git a/core/src/test/java/com/dtstack/flink/sql/dirtyManager/TestDirtyDataManager.java b/core/src/test/java/com/dtstack/flink/sql/dirtyManager/TestDirtyDataManager.java deleted file mode 100644 index ec08bb9d3..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/dirtyManager/TestDirtyDataManager.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.dtstack.flink.sql.dirtyManager; - -import com.dtstack.flink.sql.dirtyManager.manager.DirtyDataManager; - -import java.util.HashMap; -import java.util.Map; - -/** - * @author tiezhu - * Company dtstack - * Date 2020/8/28 星期五 - */ -public class TestDirtyDataManager { - -} diff --git a/core/src/test/java/com/dtstack/flink/sql/environment/MyLocalStreamEnvironmentTest.java b/core/src/test/java/com/dtstack/flink/sql/environment/MyLocalStreamEnvironmentTest.java deleted file mode 100644 index c7c9e6014..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/environment/MyLocalStreamEnvironmentTest.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.dtstack.flink.sql.environment; - -import org.apache.flink.configuration.Configuration; -import org.apache.flink.runtime.jobgraph.JobGraph; -import org.apache.flink.runtime.minicluster.MiniCluster; -import org.apache.flink.streaming.api.graph.StreamGraph; -import org.apache.flink.streaming.api.graph.StreamGraphGenerator; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.api.support.membermodification.MemberMatcher; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -import java.net.URI; -import java.util.concurrent.CompletableFuture; - -import static org.mockito.Mockito.anyObject; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -@RunWith(PowerMockRunner.class) -@PrepareForTest({StreamGraphGenerator.class, MiniCluster.class, MyLocalStreamEnvironment.class}) -public class MyLocalStreamEnvironmentTest { - - @Test - public void testExecute() throws Exception { - MyLocalStreamEnvironment myLocalStreamEnvironment = new MyLocalStreamEnvironment(); - - StreamGraph streamGraph = mock(StreamGraph.class); - JobGraph jobGraph = mock(JobGraph.class); - when(jobGraph.getJobConfiguration()).thenReturn(new Configuration()); - when(jobGraph.getMaximumParallelism()).thenReturn(1); - when(streamGraph.getJobGraph()).thenReturn(jobGraph); - - MiniCluster miniCluster = mock(MiniCluster.class); - PowerMockito.suppress(MemberMatcher.methods(MiniCluster.class, "start")); - PowerMockito.whenNew(MiniCluster.class).withArguments(anyObject()).thenReturn(miniCluster); - CompletableFuture future = mock(CompletableFuture.class); - when(miniCluster.getRestAddress()).thenReturn(future); - URI uri = new URI("http://localhost:8080"); - when(future.get()).thenReturn(uri); - when(miniCluster.executeJobBlocking(anyObject())).thenReturn(null); - myLocalStreamEnvironment.execute(streamGraph); - } -} diff --git a/core/src/test/java/com/dtstack/flink/sql/exec/ApiResultTest.java b/core/src/test/java/com/dtstack/flink/sql/exec/ApiResultTest.java deleted file mode 100644 index 811b6b8a9..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/exec/ApiResultTest.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.dtstack.flink.sql.exec; - -import org.junit.Test; - -public class ApiResultTest { - - @Test - public void createSuccessResultJsonStr(){ - ApiResult.createSuccessResultJsonStr("ss", 12L); - } - @Test - public void createErrorResultJsonStr(){ - ApiResult.createErrorResultJsonStr("ss"); - } - - -} diff --git a/core/src/test/java/com/dtstack/flink/sql/exec/ExecuteProcessHelperTest.java b/core/src/test/java/com/dtstack/flink/sql/exec/ExecuteProcessHelperTest.java deleted file mode 100644 index bebd71b50..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/exec/ExecuteProcessHelperTest.java +++ /dev/null @@ -1,195 +0,0 @@ -package com.dtstack.flink.sql.exec; - -import com.dtstack.flink.sql.enums.ClusterMode; -import com.dtstack.flink.sql.enums.EPluginLoadMode; -import com.dtstack.flink.sql.parser.SqlParser; -import com.dtstack.flink.sql.parser.SqlTree; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.sink.StreamSinkFactory; -import com.dtstack.flink.sql.source.StreamSourceFactory; -import com.dtstack.flink.sql.table.AbstractSourceTableInfo; -import com.dtstack.flink.sql.table.AbstractTargetTableInfo; -import com.dtstack.flink.sql.util.PluginUtil; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.common.typeinfo.Types; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.streaming.api.datastream.DataStream; -import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator; -import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; -import org.apache.flink.table.api.Table; -import org.apache.flink.table.api.TableSchema; -import org.apache.flink.table.api.java.StreamTableEnvironment; -import org.apache.flink.table.sinks.TableSink; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -import java.io.IOException; -import java.net.URL; -import java.util.HashMap; -import java.util.Map; -import java.util.Properties; -import java.util.Set; - -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyObject; -import static org.mockito.Mockito.anyString; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -@RunWith(PowerMockRunner.class) -@PrepareForTest({SqlParser.class, PluginUtil.class, StreamSourceFactory.class, StreamSinkFactory.class}) -public class ExecuteProcessHelperTest { - - private Map dirtyMap; - - @Before - public void setUp() { - dirtyMap = new HashMap<>(); - dirtyMap.put("type", "console"); - // 多少条数据打印一次 - dirtyMap.put("printLimit", "100"); - dirtyMap.put("url", "jdbc:mysql://localhost:3306/tiezhu"); - dirtyMap.put("userName", "root"); - dirtyMap.put("password", "abc123"); - dirtyMap.put("isCreateTable", "false"); - // 多少条数据写入一次 - dirtyMap.put("batchSize", "1"); - dirtyMap.put("tableName", "dirtyData"); - } - - @Test - public void parseParams() throws Exception { - String[] sql = new String[]{"-mode", "yarnPer", "-sql", "/Users/maqi/tmp/json/group_tmp4.txt", "-name", "PluginLoadModeTest", - "-localSqlPluginPath", "/Users/maqi/code/dtstack/dt-center-flinkStreamSQL/plugins", - "-remoteSqlPluginPath", "/Users/maqi/code/dtstack/dt-center-flinkStreamSQL/plugins", - "-flinkconf", "/Users/maqi/tmp/flink-1.8.1/conf", - "-confProp", "{\"sql.checkpoint.cleanup.mode\":\"false\",\"sql.checkpoint.interval\":10000,\"time.characteristic\":\"EventTime\"}", - "-yarnconf", "/Users/maqi/tmp/hadoop", "-flinkJarPath", "/Users/maqi/tmp/flink-1.8.1/lib", "-queue", "c", "-pluginLoadMode", "shipfile"}; - - ExecuteProcessHelper.parseParams(sql); - } - - @Test - public void checkRemoteSqlPluginPath() { - ExecuteProcessHelper.checkRemoteSqlPluginPath(null, EPluginLoadMode.SHIPFILE.name(), ClusterMode.local.name()); - - } - - // @Test - public void getStreamExecution() throws Exception { - String[] sql = new String[]{"-mode", "yarnPer", "-sql", "/Users/maqi/tmp/json/group_tmp4.txt", "-name", "PluginLoadModeTest", - "-localSqlPluginPath", "/Users/maqi/code/dtstack/dt-center-flinkStreamSQL/plugins", - "-remoteSqlPluginPath", "/Users/maqi/code/dtstack/dt-center-flinkStreamSQL/plugins", - "-flinkconf", "/Users/maqi/tmp/flink-1.8.1/conf", - "-confProp", "{\"sql.checkpoint.cleanup.mode\":\"false\",\"sql.checkpoint.interval\":10000,\"time.characteristic\":\"EventTime\"}", - "-yarnconf", "/Users/maqi/tmp/hadoop", "-flinkJarPath", "/Users/maqi/tmp/flink-1.8.1/lib", "-queue", "c", "-pluginLoadMode", "shipfile"}; - ParamsInfo paramsInfo = ExecuteProcessHelper.parseParams(sql); - PowerMockito.mockStatic(SqlParser.class); - SqlTree sqlTree = mock(SqlTree.class); - when(SqlParser.parseSql(anyString(), anyString())).thenReturn(sqlTree); - when(sqlTree.getFunctionList()).thenReturn(Lists.newArrayList()); - ExecuteProcessHelper.getStreamExecution(paramsInfo); - - } - - @Test - public void getExternalJarUrls() throws IOException { - ExecuteProcessHelper.getExternalJarUrls("[\"/test\"]"); - } - - // @Test - public void registerTable() throws Exception { - SqlTree sqlTree = mock(SqlTree.class); - StreamExecutionEnvironment env = mock(StreamExecutionEnvironment.class); - StreamTableEnvironment tableEnv = mock(StreamTableEnvironment.class); - Table table = mock(Table.class); - TableSchema tableSchema = mock(TableSchema.class); - DataStream dataStream = mock(DataStream.class); - when(tableEnv.sqlQuery(anyString())).thenReturn(table); - when(tableEnv.fromDataStream(anyObject(), anyObject())).thenReturn(table); - - when(tableEnv.toRetractStream(any(Table.class), any(RowTypeInfo.class))).thenReturn(dataStream); - SingleOutputStreamOperator singleOutputStreamOperator = mock(SingleOutputStreamOperator.class); - when(dataStream.map(anyObject())).thenReturn(singleOutputStreamOperator); - when(singleOutputStreamOperator.returns(any(RowTypeInfo.class))).thenReturn(singleOutputStreamOperator); - - - when(table.getSchema()).thenReturn(tableSchema); - when(tableSchema.getFieldTypes()).thenReturn(new TypeInformation[]{Types.STRING}); - when(tableSchema.getFieldNames()).thenReturn(new String[]{"a"}); - String localSqlPluginPath = "/"; - String remoteSqlPluginPath = "/"; - String pluginLoadMode = "shipfile"; - Map sideTableMap = Maps.newHashMap(); - Map registerTableCache = Maps.newHashMap(); - PowerMockito.mockStatic(PluginUtil.class); - - PowerMockito.mockStatic(StreamSourceFactory.class); - when(StreamSourceFactory.getStreamSource(anyObject(), anyObject(), anyObject(), anyString(), anyString())).thenReturn(table); - - TableSink tableSink = mock(TableSink.class); - PowerMockito.mockStatic(StreamSinkFactory.class); - when(StreamSinkFactory.getTableSink(anyObject(), anyString(), anyString())).thenReturn(tableSink); - - - Map tableMap = Maps.newHashMap(); - - AbstractSourceTableInfo sourceTableInfo = mock(AbstractSourceTableInfo.class); - when(sourceTableInfo.getAdaptName()).thenReturn("a"); - when(sourceTableInfo.getAdaptSelectSql()).thenReturn("s"); - when(sourceTableInfo.getType()).thenReturn("kafka"); - - when(PluginUtil.buildSourceAndSinkPathByLoadMode(anyString(), anyString(), anyString(), anyString(), anyString())).thenReturn(new URL("file://a")); - - AbstractSideTableInfo sideTableInfo = mock(AbstractSideTableInfo.class); - when(sideTableInfo.getCacheType()).thenReturn("all"); - when(sideTableInfo.getName()).thenReturn("sideTable"); - when(sideTableInfo.getType()).thenReturn("redis"); - when(PluginUtil.buildSidePathByLoadMode(anyString(), anyString(), anyString(), anyString(), anyString(), anyString())).thenReturn(new URL("file://a")); - - AbstractTargetTableInfo targetTableInfo = mock(AbstractTargetTableInfo.class); - when(targetTableInfo.getName()).thenReturn("sinkTable"); - when(targetTableInfo.getType()).thenReturn("kafka"); - when(targetTableInfo.getFieldClasses()).thenReturn(new Class[]{String.class}); - when(targetTableInfo.getFields()).thenReturn(new String[]{"a"}); - - - tableMap.put("source", sourceTableInfo); - tableMap.put("side", sideTableInfo); - tableMap.put("target", targetTableInfo); - when(sqlTree.getTableInfoMap()).thenReturn(tableMap); - - // SqlTree sqlTree - // , StreamExecutionEnvironment env - // , StreamTableEnvironment tableEnv - // , String localSqlPluginPath - // , String remoteSqlPluginPath - // , String pluginLoadMode - // , Map dirtyProperties - // , Map sideTableMap - // , Map registerTableCache - ExecuteProcessHelper.registerTable(sqlTree, env, tableEnv, localSqlPluginPath, remoteSqlPluginPath, pluginLoadMode, dirtyMap, sideTableMap, registerTableCache); - } - - @Test - public void registerPluginUrlToCachedFile() throws Exception { - StreamExecutionEnvironment executionEnvironment = ExecuteProcessHelper.getStreamExeEnv(new Properties(), "local"); - Set classPathSet = Sets.newHashSet(); - classPathSet.add(new URL("file://")); - ExecuteProcessHelper.registerPluginUrlToCachedFile(executionEnvironment, classPathSet); - } - - @Test - public void getStreamExeEnv() throws Exception { - ExecuteProcessHelper.getStreamExeEnv(new Properties(), "local"); - } - - -} diff --git a/core/src/test/java/com/dtstack/flink/sql/exec/FlinkSQLExecTest.java b/core/src/test/java/com/dtstack/flink/sql/exec/FlinkSQLExecTest.java deleted file mode 100644 index aa21a65b5..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/exec/FlinkSQLExecTest.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.dtstack.flink.sql.exec; - -import org.apache.flink.table.api.Table; -import org.apache.flink.table.api.java.StreamTableEnvironment; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -import static org.mockito.Mockito.mock; - - -@RunWith(PowerMockRunner.class) -@PrepareForTest({FlinkSQLExec.class, Table.class}) -public class FlinkSQLExecTest { - - - @Test - public void sqlUpdate() throws Exception { - String stmt = "insert into a select fieldA from b"; - StreamTableEnvironment tableEnv = mock(StreamTableEnvironment.class); - - - } - - - - @Test - public void ignoreCase() throws NoSuchMethodException { -// Method method = FlinkSQLExec.class.getDeclaredMethod("ignoreCase",String.class, String.class); -// String[] queryFieldNames = new String[1]; -// queryFieldNames[0] = "a"; -// String[] sinkFieldNames = new String[1]; -// sinkFieldNames[0] = "a"; -// FlinkSQLExec.ignoreCase(queryFieldNames, sinkFieldNames); - } - -} diff --git a/core/src/test/java/com/dtstack/flink/sql/exec/PraramsInfoTest.java b/core/src/test/java/com/dtstack/flink/sql/exec/PraramsInfoTest.java deleted file mode 100644 index bda2bada6..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/exec/PraramsInfoTest.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.dtstack.flink.sql.exec; - -import com.google.common.collect.Lists; -import org.junit.Test; - -import java.util.Properties; - -public class PraramsInfoTest { - - @Test - public void paramInfo(){ - ParamsInfo paramsInfo = ParamsInfo.builder() - .setConfProp(new Properties()) - .setDeployMode("local") - .setName("test") - .setJarUrlList(Lists.newArrayList()) - .setLocalSqlPluginPath(".") - .setRemoteSqlPluginPath(".") - .setPluginLoadMode("classpath") - .setSql("select a from b") - .build(); - System.out.println(paramsInfo.toString()); - - } -} diff --git a/core/src/test/java/com/dtstack/flink/sql/factory/DTFactoryTest.java b/core/src/test/java/com/dtstack/flink/sql/factory/DTFactoryTest.java deleted file mode 100644 index a8dbd4e72..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/factory/DTFactoryTest.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.dtstack.flink.sql.factory; - -import org.junit.Test; - -public class DTFactoryTest { - - @Test - public void testFactory(){ - DTThreadFactory dtThreadFactory = new DTThreadFactory("test"); - dtThreadFactory.newThread(new Runnable() { - @Override - public void run() { - System.out.println("run.."); - } - }); - } -} diff --git a/core/src/test/java/com/dtstack/flink/sql/function/FunctionManagerTest.java b/core/src/test/java/com/dtstack/flink/sql/function/FunctionManagerTest.java deleted file mode 100644 index 2759f1f80..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/function/FunctionManagerTest.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.dtstack.flink.sql.function; - -import org.apache.flink.table.api.java.StreamTableEnvironment; -import org.apache.flink.table.functions.ScalarFunction; -import org.junit.Test; - -import static org.mockito.Mockito.mock; - -public class FunctionManagerTest extends ScalarFunction { - - @Test - public void registerUDF(){ - StreamTableEnvironment tableEnvironment = mock(StreamTableEnvironment.class); - - FunctionManager.registerUDF("SCALA", "com.dtstack.flink.sql.function.FunctionManagerTest", "getResultType", tableEnvironment, Thread.currentThread().getContextClassLoader()); - FunctionManager.registerUDF("AGGREGATE", "org.apache.flink.table.planner.functions.aggfunctions.LastValueAggFunction", "resultTypeConvert", tableEnvironment, Thread.currentThread().getContextClassLoader()); - try{ - FunctionManager.registerUDF("TABLE", " org.apache.flink.table.plan.util.ObjectExplodeTableFunc", "collectArray", tableEnvironment, Thread.currentThread().getContextClassLoader()); - }catch (Exception e){ - - } - } - - @Test - public void transformTypes(){ - Class[] fieldTypes = new Class[1]; - fieldTypes[0] = String.class; - FunctionManager.transformTypes(fieldTypes); - } - -} diff --git a/core/src/test/java/com/dtstack/flink/sql/option/OptionParseTest.java b/core/src/test/java/com/dtstack/flink/sql/option/OptionParseTest.java deleted file mode 100644 index 1ccc89ad3..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/option/OptionParseTest.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.dtstack.flink.sql.option; - -import org.junit.Test; - -public class OptionParseTest { - - @Test - public void testOption() throws Exception { - String[] sql = new String[]{"-mode", "yarnPer", "-sql", "/Users/maqi/tmp/json/group_tmp4.txt", "-name", "PluginLoadModeTest", - "-localSqlPluginPath", "/Users/maqi/code/dtstack/dt-center-flinkStreamSQL/plugins", - "-remoteSqlPluginPath", "/Users/maqi/code/dtstack/dt-center-flinkStreamSQL/plugins", - "-flinkconf", "/Users/maqi/tmp/flink-1.8.1/conf", - "-confProp", "{\"sql.checkpoint.cleanup.mode\":\"false\",\"sql.checkpoint.interval\":10000,\"time.characteristic\":\"EventTime\"}", - "-yarnconf", "/Users/maqi/tmp/hadoop", "-flinkJarPath", "/Users/maqi/tmp/flink-1.8.1/lib", "-queue", "c", "-pluginLoadMode", "shipfile"}; - OptionParser optionParser = new OptionParser(sql); - } -} diff --git a/core/src/test/java/com/dtstack/flink/sql/outputformat/AbstractDtRichOutputFormatTest.java b/core/src/test/java/com/dtstack/flink/sql/outputformat/AbstractDtRichOutputFormatTest.java deleted file mode 100644 index e5cfce5a4..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/outputformat/AbstractDtRichOutputFormatTest.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.dtstack.flink.sql.outputformat; - -import org.apache.flink.api.common.functions.RuntimeContext; -import org.apache.flink.configuration.Configuration; -import org.apache.flink.metrics.MetricGroup; -import org.junit.Test; - -import java.io.IOException; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class AbstractDtRichOutputFormatTest { - - @Test - public void initMetric(){ - AbstractDtRichOutputFormat richOutputFormat = new AbstractDtRichOutputFormat() { - @Override - public void configure(Configuration parameters) { - - } - - @Override - public void open(int taskNumber, int numTasks) throws IOException { - - } - - @Override - public void writeRecord(Object record) throws IOException { - - } - - @Override - public void close() throws IOException { - - } - }; - RuntimeContext runtimeContext = mock(RuntimeContext.class); - richOutputFormat.setRuntimeContext(runtimeContext); - MetricGroup metricGroup = mock(MetricGroup.class); - when(runtimeContext.getMetricGroup()).thenReturn(metricGroup); - richOutputFormat.initMetric(); - } -} diff --git a/core/src/test/java/com/dtstack/flink/sql/parse/CreateFuncParserTest.java b/core/src/test/java/com/dtstack/flink/sql/parse/CreateFuncParserTest.java deleted file mode 100644 index 472f3819d..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/parse/CreateFuncParserTest.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.dtstack.flink.sql.parse; - -import com.dtstack.flink.sql.parser.CreateFuncParser; -import com.dtstack.flink.sql.parser.SqlTree; -import org.junit.Test; - -public class CreateFuncParserTest { - - @Test - public void parseSql(){ - String sql = "create table function with xxxx"; - - CreateFuncParser parser = CreateFuncParser.newInstance(); - parser.verify(sql); - - parser.parseSql(sql, new SqlTree()); - } - -} \ No newline at end of file diff --git a/core/src/test/java/com/dtstack/flink/sql/parse/CreateTableParserTest.java b/core/src/test/java/com/dtstack/flink/sql/parse/CreateTableParserTest.java deleted file mode 100644 index 46d2524ab..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/parse/CreateTableParserTest.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.dtstack.flink.sql.parse; - -import com.dtstack.flink.sql.parser.CreateTableParser; -import com.dtstack.flink.sql.parser.SqlTree; -import org.junit.Test; - -public class CreateTableParserTest { - - @Test - public void parseSql(){ - String sql = "CREATE TABLE MyResult(\n" + - " id varchar,\n" + - " name varchar,\n" + - " address varchar,\n" + - " message varchar,\n" + - " info varchar\n" + - ")WITH(\n" + - " type = 'console'\n" + - ");"; - CreateTableParser parser = CreateTableParser.newInstance(); - parser.verify(sql); - parser.parseSql(sql, new SqlTree()); - } - -} diff --git a/core/src/test/java/com/dtstack/flink/sql/parse/CreateTmpTableParserTest.java b/core/src/test/java/com/dtstack/flink/sql/parse/CreateTmpTableParserTest.java deleted file mode 100644 index 4798a7977..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/parse/CreateTmpTableParserTest.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.dtstack.flink.sql.parse; - -import com.dtstack.flink.sql.parser.CreateTmpTableParser; -import com.dtstack.flink.sql.parser.FlinkPlanner; -import com.dtstack.flink.sql.parser.SqlTree; -import org.apache.calcite.sql.SqlKind; -import org.apache.calcite.sql.SqlNode; -import org.apache.flink.table.planner.calcite.CalciteParser; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -import static org.mockito.Mockito.anyString; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -@RunWith(PowerMockRunner.class) -@PrepareForTest({FlinkPlanner.class, SqlKind.class}) -public class CreateTmpTableParserTest { - - @Test - public void parseSql(){ - String sql = "create view test as select a, b from tablea"; - CreateTmpTableParser parser = CreateTmpTableParser.newInstance(); - parser.verify(sql); - - PowerMockito.mockStatic(FlinkPlanner.class); - FlinkPlanner flinkPlanner = mock(FlinkPlanner.class); - CalciteParser calciteParser = mock(CalciteParser.class); - when(flinkPlanner.getParser()).thenReturn(calciteParser); - - SqlNode sqlNode = mock(SqlNode.class); - when(calciteParser.parse(anyString())).thenReturn(sqlNode); - - SqlKind sqlKind = mock(SqlKind.class); - when(sqlNode.getKind()).thenReturn(sqlKind); - - parser.parseSql(sql, new SqlTree()); - } -} diff --git a/core/src/test/java/com/dtstack/flink/sql/parse/InsertSqlParserTest.java b/core/src/test/java/com/dtstack/flink/sql/parse/InsertSqlParserTest.java deleted file mode 100644 index bf1907670..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/parse/InsertSqlParserTest.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.dtstack.flink.sql.parse; - -import com.dtstack.flink.sql.parser.FlinkPlanner; -import com.dtstack.flink.sql.parser.InsertSqlParser; -import com.dtstack.flink.sql.parser.SqlTree; -import org.apache.calcite.sql.SqlKind; -import org.apache.calcite.sql.SqlNode; -import org.apache.flink.table.planner.calcite.CalciteParser; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - - -@RunWith(PowerMockRunner.class) -@PrepareForTest({FlinkPlanner.class, SqlKind.class}) -public class InsertSqlParserTest { - - @Test - public void parseSql() throws Exception { - String sql = "insert into MyResult\n" + - " select\n" + - " t1.id AS id,\n" + - " t1.name AS name,\n" + - " t1.address AS address,\n" + - " t2.message AS message,\n" + - " t3.message as info\n" + - " from MyTable t1 \n" + - " join MyRedis t2\n" + - " on t1.id = t2.id\n" + - " join redisSide t3\n" + - " on t1.id = t3.id"; - InsertSqlParser parser = InsertSqlParser.newInstance(); - parser.verify(sql); - - PowerMockito.mockStatic(FlinkPlanner.class); - FlinkPlanner flinkPlanner = mock(FlinkPlanner.class); - CalciteParser calciteParser = mock(CalciteParser.class); - when(flinkPlanner.getParser()).thenReturn(calciteParser); - - SqlNode sqlNode = mock(SqlNode.class); - when(calciteParser.parse(anyString())).thenReturn(sqlNode); - - SqlKind sqlKind = mock(SqlKind.class); - when(sqlNode.getKind()).thenReturn(sqlKind); - - parser.parseSql(sql, new SqlTree()); - } -} diff --git a/core/src/test/java/com/dtstack/flink/sql/side/AbstractSideTableInfoTest.java b/core/src/test/java/com/dtstack/flink/sql/side/AbstractSideTableInfoTest.java deleted file mode 100644 index 13c4211b6..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/side/AbstractSideTableInfoTest.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.dtstack.flink.sql.side; - -import org.junit.Test; - -public class AbstractSideTableInfoTest { - - @Test - public void getRowTypeInfo(){ - AbstractSideTableInfo sideTableInfo = new AbstractSideTableInfo() { - @Override - public boolean check() { - return false; - } - }; - Class[] fieldClasses = new Class[1]; - fieldClasses[0] = String.class; - sideTableInfo.setFieldClasses(fieldClasses); - - String[] fields = new String[1]; - fields[0] = "a"; - - sideTableInfo.setFields(fields); - sideTableInfo.getRowTypeInfo(); - } -} diff --git a/core/src/test/java/com/dtstack/flink/sql/side/BaseAllReqRowTest.java b/core/src/test/java/com/dtstack/flink/sql/side/BaseAllReqRowTest.java deleted file mode 100644 index 56d11aced..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/side/BaseAllReqRowTest.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.dtstack.flink.sql.side; - -import org.apache.flink.configuration.Configuration; -import org.apache.flink.table.dataformat.BaseRow; -import org.apache.flink.types.Row; -import org.apache.flink.util.Collector; -import org.junit.Test; -import org.mockito.Mockito; - -import java.sql.SQLException; - -public class BaseAllReqRowTest { - - @Test - public void testBaseAllReqRow() throws Exception { - BaseSideInfo sideInfo = Mockito.mock(BaseSideInfo.class); - AbstractSideTableInfo sideTableInfo = Mockito.mock(AbstractSideTableInfo.class); - - Mockito.when(sideInfo.getSideTableInfo()).thenReturn(sideTableInfo); - Mockito.when(sideTableInfo.getCacheTimeout()).thenReturn(10L); - BaseAllReqRow baseAllReqRow = new BaseAllReqRow(sideInfo) { - @Override - public void flatMap(BaseRow value, Collector out) throws Exception { - - } - - @Override - protected void initCache() throws SQLException { - - } - - @Override - protected void reloadCache() { - - } - }; - - Configuration configuration = Mockito.mock(Configuration.class); - baseAllReqRow.open(configuration); - BaseRow value = Mockito.mock(BaseRow.class); - Collector out = Mockito.mock(Collector.class); - baseAllReqRow.sendOutputRow(value, null, out); - baseAllReqRow.close(); - } - -} diff --git a/core/src/test/java/com/dtstack/flink/sql/side/BaseAsyncReqRowTest.java b/core/src/test/java/com/dtstack/flink/sql/side/BaseAsyncReqRowTest.java deleted file mode 100644 index 6b3b1945e..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/side/BaseAsyncReqRowTest.java +++ /dev/null @@ -1,96 +0,0 @@ -package com.dtstack.flink.sql.side; - -import com.dtstack.flink.sql.enums.ECacheContentType; -import com.dtstack.flink.sql.metric.MetricConstant; -import com.dtstack.flink.sql.side.cache.AbstractSideCache; -import com.dtstack.flink.sql.side.cache.CacheObj; -import com.google.common.collect.Lists; -import org.apache.flink.configuration.Configuration; -import org.apache.flink.metrics.Counter; -import org.apache.flink.metrics.MetricGroup; -import org.apache.flink.streaming.api.functions.async.ResultFuture; -import org.apache.flink.streaming.api.operators.StreamingRuntimeContext; -import org.apache.flink.streaming.runtime.tasks.ProcessingTimeService; -import org.apache.flink.table.dataformat.BaseRow; -import org.apache.flink.table.dataformat.GenericRow; -import org.apache.flink.types.Row; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -import java.util.Map; - -import static org.mockito.Mockito.anyString; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class BaseAsyncReqRowTest { - - private BaseAsyncReqRow asyncReqRow; - - @Before - public void init() throws Exception { - BaseSideInfo sideInfo = mock(BaseSideInfo.class); - AbstractSideCache sideCache = mock(AbstractSideCache.class); - when(sideInfo.getSideCache()).thenReturn(sideCache); - when(sideCache.getFromCache(anyString())).thenReturn(CacheObj.buildCacheObj(ECacheContentType.SingleLine, "1")); - AbstractSideTableInfo sideTableInfo = mock(AbstractSideTableInfo.class); - when(sideInfo.getSideTableInfo()).thenReturn(sideTableInfo); - when(sideTableInfo.getCacheType()).thenReturn("lru"); - - when(sideInfo.getEqualValIndex()).thenReturn(Lists.newArrayList(0)); - when(sideInfo.getEqualFieldList()).thenReturn(Lists.newArrayList("key")); - - asyncReqRow = new BaseAsyncReqRow(sideInfo) { - @Override - public BaseRow fillData(BaseRow input, Object sideInput) { - return null; - } - - @Override - public void handleAsyncInvoke(Map inputParams, BaseRow input, ResultFuture resultFuture) throws Exception { - - } - - @Override - public String buildCacheKey(Map inputParams) { - return "key"; - } - }; - - StreamingRuntimeContext runtimeContext = mock(StreamingRuntimeContext.class); - MetricGroup metricGroup = mock(MetricGroup.class); - when(runtimeContext.getMetricGroup()).thenReturn(metricGroup); - Counter counter = mock(Counter.class); - when(metricGroup.counter(MetricConstant.DT_NUM_SIDE_PARSE_ERROR_RECORDS)).thenReturn(counter); - - ProcessingTimeService processingTimeService = mock(ProcessingTimeService.class); - when(runtimeContext.getProcessingTimeService()).thenReturn(processingTimeService); - when(processingTimeService.getCurrentProcessingTime()).thenReturn(System.currentTimeMillis()); - - - asyncReqRow.setRuntimeContext(runtimeContext); - - } - - // @Test - public void testAllMethod() throws Exception { - Configuration configuration = Mockito.mock(Configuration.class); - asyncReqRow.open(configuration); - GenericRow input = new GenericRow(1); - input.setField(0, "a"); - ResultFuture resultFuture = mock(ResultFuture.class); - asyncReqRow.dealMissKey(input, resultFuture); - - asyncReqRow.dealCacheData("key", CacheObj.buildCacheObj(ECacheContentType.SingleLine, "a") ); - asyncReqRow.getFromCache("key"); - - asyncReqRow.timeout(input, resultFuture); - - - asyncReqRow.asyncInvoke(input, resultFuture); - asyncReqRow.dealFillDataError(input, resultFuture, new RuntimeException("")); - - } - -} diff --git a/core/src/test/java/com/dtstack/flink/sql/side/BaseSideInfoTest.java b/core/src/test/java/com/dtstack/flink/sql/side/BaseSideInfoTest.java deleted file mode 100644 index 583289e74..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/side/BaseSideInfoTest.java +++ /dev/null @@ -1,98 +0,0 @@ -package com.dtstack.flink.sql.side; - -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import org.apache.calcite.sql.JoinType; -import org.apache.calcite.sql.SqlBasicCall; -import org.apache.calcite.sql.SqlIdentifier; -import org.apache.calcite.sql.SqlKind; -import org.apache.calcite.sql.SqlNode; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.junit.Before; -import org.junit.Test; - -import java.util.List; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class BaseSideInfoTest { - - private BaseSideInfo sideInfo; - - private AbstractSideTableInfo sideTableInfo; - - @Before - public void init(){ - - RowTypeInfo rowTypeInfo = mock(RowTypeInfo.class); - when(rowTypeInfo.getFieldNames()).thenReturn(new String[]{"a"}); - JoinInfo joinInfo = mock(JoinInfo.class); - when(joinInfo.getSideTableName()).thenReturn("a"); - when(joinInfo.getNonSideTable()).thenReturn("b"); - - FieldInfo fieldInfo = new FieldInfo(); - fieldInfo.setTable("a"); - fieldInfo.setFieldName("a"); - - List outFieldInfoList = Lists.newArrayList(fieldInfo); - sideTableInfo = mock(AbstractSideTableInfo.class); - when(sideTableInfo.getFieldList()).thenReturn(Lists.newArrayList("a")); - when(sideTableInfo.getFieldTypes()).thenReturn(new String[]{"string"}); - - when(sideTableInfo.getPhysicalFields()).thenReturn(Maps.newHashMap()); - sideInfo = new BaseSideInfo(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo) { - @Override - public void buildEqualInfo(JoinInfo joinInfo, AbstractSideTableInfo sideTableInfo) { - - } - }; - - } - - @Test - public void dealOneEqualCon(){ - SqlBasicCall sqlNode = mock(SqlBasicCall.class); - when(sqlNode.getKind()).thenReturn(SqlKind.NOT_EQUALS); - - - SqlIdentifier sqlIdentifier1 = mock(SqlIdentifier.class); - when(sqlIdentifier1.getSimple()).thenReturn("a"); - - SqlIdentifier sqlIdentifier2 = mock(SqlIdentifier.class); - when(sqlIdentifier2.getSimple()).thenReturn("b"); - - when(sqlIdentifier1.getComponent(0)).thenReturn(sqlIdentifier1); - when(sqlIdentifier1.getComponent(1)).thenReturn(sqlIdentifier2); - when(sqlIdentifier2.getComponent(0)).thenReturn(sqlIdentifier2); - when(sqlIdentifier2.getComponent(1)).thenReturn(sqlIdentifier1); - when(sqlNode.getOperands()).thenReturn(new SqlNode[]{sqlIdentifier1, sqlIdentifier2}); - - sideInfo.dealOneEqualCon(sqlNode, "a"); - - try { - sideInfo.dealOneEqualCon(sqlNode, "b"); - } catch (Exception e){ - - } - - sideInfo.setSideCache(null); - sideInfo.setSideTableInfo(null); - sideInfo.setEqualFieldList(null); - sideInfo.setEqualValIndex(null); - sideInfo.setInFieldIndex(null); - sideInfo.setJoinType(JoinType.LEFT); - sideInfo.setSqlCondition(""); - sideInfo.setSideSelectFields(""); - sideInfo.setOutFieldInfoList(null); - sideInfo.setSideFieldNameIndex(null); - sideInfo.setSideSelectFieldsType(null); - sideInfo.setRowTypeInfo(null); - sideInfo.setSideSelectFields(""); - } - - - - - -} diff --git a/core/src/test/java/com/dtstack/flink/sql/side/JoinNodeDealerTest.java b/core/src/test/java/com/dtstack/flink/sql/side/JoinNodeDealerTest.java deleted file mode 100644 index 0785191d1..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/side/JoinNodeDealerTest.java +++ /dev/null @@ -1,483 +0,0 @@ -package com.dtstack.flink.sql.side; - -import com.dtstack.flink.sql.parser.FlinkPlanner; -import com.dtstack.flink.sql.util.TableUtils; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Queues; -import com.google.common.collect.Sets; -import org.apache.calcite.sql.JoinConditionType; -import org.apache.calcite.sql.JoinType; -import org.apache.calcite.sql.SqlBasicCall; -import org.apache.calcite.sql.SqlIdentifier; -import org.apache.calcite.sql.SqlJoin; -import org.apache.calcite.sql.SqlKind; -import org.apache.calcite.sql.SqlLiteral; -import org.apache.calcite.sql.SqlNode; -import org.apache.calcite.sql.SqlNodeList; -import org.apache.calcite.sql.fun.SqlCase; -import org.apache.calcite.sql.parser.SqlParserPos; -import org.apache.calcite.sql.type.SqlTypeName; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.calcite.shaded.com.google.common.collect.ImmutableList; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -import java.lang.reflect.Method; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Queue; -import java.util.Set; - -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -@RunWith(PowerMockRunner.class) -@PrepareForTest({JoinNodeDealer.class, SqlJoin.class, TableUtils.class, FlinkPlanner.class}) -public class JoinNodeDealerTest { - - private JoinNodeDealer joinNodeDealer; - - private SideSQLParser sideSQLParser; - - @Before - public void init(){ - sideSQLParser = mock(SideSQLParser.class); - joinNodeDealer = new JoinNodeDealer(sideSQLParser); - } - - @Test - public void dealJoinNode(){ - SqlParserPos pos = mock(SqlParserPos.class); - SqlNode left = mock(SqlNode.class); - SqlLiteral natural = mock(SqlLiteral.class); - when(natural.getTypeName()).thenReturn(SqlTypeName.BOOLEAN); - SqlLiteral joinType = mock(SqlLiteral.class); - when(joinType.symbolValue(JoinType.class)).thenReturn(JoinType.LEFT); - SqlNode right = mock(SqlNode.class); - when(right.getKind()).thenReturn(SqlKind.IDENTIFIER); - when(right.toString()).thenReturn("a"); - SqlLiteral conditionType = mock(SqlLiteral.class); - when(conditionType.symbolValue(JoinConditionType.class)).thenReturn(JoinConditionType.ON); - - SqlNode condition = mock(SqlNode.class); - SqlJoin joinNode = new SqlJoin(pos, left, natural, joinType, right, conditionType, condition); - Set sideTableSet = Sets.newHashSet(); - Queue queueInfo = Queues.newLinkedBlockingQueue(); - SqlNode parentWhere = mock(SqlNode.class); - SqlNodeList parentSelectList = mock(SqlNodeList.class); - SqlNodeList parentGroupByList = mock(SqlNodeList.class); - Set> joinFieldSet = Sets.newHashSet(); - Map tableRef = Maps.newHashMap(); - Map fieldRef = Maps.newHashMap(); - String scope = "1"; - - joinNodeDealer.dealJoinNode(joinNode, sideTableSet, queueInfo, parentWhere, parentSelectList, parentGroupByList, joinFieldSet, tableRef, fieldRef, scope, Sets.newHashSet()); - } - - @Test - public void extractJoinNeedSelectField(){ - - SqlIdentifier leftNode = mock(SqlIdentifier.class); - when(leftNode.getKind()).thenReturn(SqlKind.IDENTIFIER); - when(leftNode.getSimple()).thenReturn("a"); - when(leftNode.toString()).thenReturn("a.b"); - leftNode.names = ImmutableList.copyOf(Lists.newArrayList("a", "b")); - - SqlBasicCall parentOther = mock(SqlBasicCall.class); - when(parentOther.getKind()).thenReturn(SqlKind.OTHER); - - SqlBasicCall parentWhere = mock(SqlBasicCall.class); - when(parentWhere.getKind()).thenReturn(SqlKind.AND); - when(parentWhere.getOperands()).thenReturn(Lists.newArrayList(parentOther, parentOther).toArray(new SqlBasicCall[2])); - - SqlNodeList parentSelectList = mock(SqlNodeList.class); - when(parentSelectList.getList()).thenReturn(Lists.newArrayList(leftNode)); - - SqlNodeList parentGroupByList = mock(SqlNodeList.class); - when(parentGroupByList.getList()).thenReturn(Lists.newArrayList(leftNode)); - Map tableRef = Maps.newHashMap(); - Set> joinFieldSet = Sets.newHashSet(); - Map fieldRef = Maps.newHashMap(); - JoinInfo tableInfo = mock(JoinInfo.class); - when(tableInfo.getNewTableAlias()).thenReturn("a"); - joinNodeDealer.extractJoinNeedSelectField(leftNode, leftNode, parentWhere, parentSelectList, parentGroupByList, tableRef, joinFieldSet, fieldRef, tableInfo); - } - - @Test - public void extractField(){ - SqlIdentifier sqlNode = mock(SqlIdentifier.class); - when(sqlNode.getKind()).thenReturn(SqlKind.IDENTIFIER); - when(sqlNode.getSimple()).thenReturn("a"); - sqlNode.names = ImmutableList.copyOf(Lists.newArrayList("a", "b")); - - SqlBasicCall parentOther = mock(SqlBasicCall.class); - when(parentOther.getKind()).thenReturn(SqlKind.OTHER); - - SqlBasicCall parentWhere = mock(SqlBasicCall.class); - when(parentWhere.getKind()).thenReturn(SqlKind.AND); - when(parentWhere.getOperands()).thenReturn(Lists.newArrayList(parentOther, parentOther).toArray(new SqlBasicCall[2])); - - SqlNodeList parentSelectList = mock(SqlNodeList.class); - when(parentSelectList.getList()).thenReturn(Lists.newArrayList(sqlNode)); - - SqlNodeList parentGroupByList = mock(SqlNodeList.class); - when(parentGroupByList.getList()).thenReturn(Lists.newArrayList(sqlNode)); - Map tableRef = Maps.newHashMap(); - Set> joinFieldSet = Sets.newHashSet(); - joinNodeDealer.extractField(sqlNode, parentWhere, parentSelectList, parentGroupByList, tableRef, joinFieldSet); - } - - @Test - public void dealNestJoin() throws Exception { - Method method = JoinNodeDealer.class.getDeclaredMethod("dealNestJoin" - , SqlJoin.class - , Set.class - , Queue.class - , SqlNode.class - , SqlNodeList.class - , SqlNodeList.class - , Set.class - , Map.class - , Map.class - , String.class - , Set.class); - method.setAccessible(true); - SqlParserPos pos = mock(SqlParserPos.class); - SqlLiteral natural = mock(SqlLiteral.class); - when(natural.getTypeName()).thenReturn(SqlTypeName.BOOLEAN); - SqlLiteral joinType = mock(SqlLiteral.class); - when(joinType.symbolValue(JoinType.class)).thenReturn(JoinType.LEFT); - SqlNode right = mock(SqlNode.class); - when(right.getKind()).thenReturn(SqlKind.IDENTIFIER); - when(right.toString()).thenReturn("a"); - SqlLiteral conditionType = mock(SqlLiteral.class); - when(conditionType.symbolValue(JoinConditionType.class)).thenReturn(JoinConditionType.ON); - - SqlNode condition = mock(SqlNode.class); - - SqlNode joinLeft = mock(SqlNode.class); - when(joinLeft.getKind()).thenReturn(SqlKind.IDENTIFIER); - when(joinLeft.toString()).thenReturn("a"); - SqlNode joinRight = mock(SqlNode.class); - when(joinRight.getKind()).thenReturn(SqlKind.IDENTIFIER); - when(joinRight.toString()).thenReturn("a"); - SqlJoin left = new SqlJoin(pos, joinLeft, natural, joinType, joinRight, conditionType, condition); - - SqlJoin joinNode = new SqlJoin(pos, left, natural, joinType, right, conditionType, condition); - Set sideTableSet = Sets.newHashSet(); - Queue queueInfo = Queues.newLinkedBlockingQueue(); - SqlNode parentWhere = mock(SqlNode.class); - SqlNodeList parentSelectList = mock(SqlNodeList.class); - SqlNodeList parentGroupByList = mock(SqlNodeList.class); - Set> joinFieldSet = Sets.newHashSet(); - Map tableRef = Maps.newHashMap(); - Map fieldRef = Maps.newHashMap(); - String scope = "1"; - method.invoke(joinNodeDealer, joinNode, sideTableSet, queueInfo, parentWhere, parentSelectList, parentGroupByList, - joinFieldSet, tableRef, fieldRef, scope ,new HashSet<>()); - } - - @Test - public void addSideInfoToExeQueue(){ - Queue queueInfo = Queues.newLinkedBlockingQueue(); - JoinInfo joinInfo = mock(JoinInfo.class); - SqlJoin joinNode = mock(SqlJoin.class); - SqlNodeList parentSelectList = mock(SqlNodeList.class); - SqlNodeList parentGroupByList = mock(SqlNodeList.class); - SqlNode parentWhere = mock(SqlNode.class); - Map tableRef = Maps.newHashMap(); - - when(joinInfo.isRightIsSideTable()).thenReturn(false); - joinNodeDealer.addSideInfoToExeQueue(queueInfo, joinInfo, joinNode, parentSelectList, parentGroupByList, parentWhere, tableRef, null); - - when(joinInfo.isRightIsSideTable()).thenReturn(true); - SqlBasicCall buildAs = mock(SqlBasicCall.class); - PowerMockito.mockStatic(TableUtils.class); - when(TableUtils.buildAsNodeByJoinInfo(joinInfo, null, null)).thenReturn(buildAs); - SqlIdentifier leftJoinNode = mock(SqlIdentifier.class); - when(joinInfo.getLeftNode()).thenReturn(leftJoinNode); - - SqlNode sqlNode = mock(SqlNode.class); - when(sqlNode.toString()).thenReturn("q"); - when(buildAs.getOperands()).thenReturn(Lists.newArrayList(sqlNode, sqlNode).toArray(new SqlNode[2])); - when(leftJoinNode.getKind()).thenReturn(SqlKind.IDENTIFIER); - when(leftJoinNode.getSimple()).thenReturn("q"); - leftJoinNode.names = ImmutableList.copyOf(Lists.newArrayList("a", "b")); - joinNodeDealer.addSideInfoToExeQueue(queueInfo, joinInfo, joinNode, parentSelectList, parentGroupByList, parentWhere, tableRef, null); - - } - - @Test - public void replaceSelectAndWhereField(){ - - SqlNode sqlNode = mock(SqlNode.class); - when(sqlNode.toString()).thenReturn("q"); - SqlBasicCall buildAs = mock(SqlBasicCall.class); - when(buildAs.getOperands()).thenReturn(Lists.newArrayList(sqlNode, sqlNode).toArray(new SqlNode[2])); - - SqlIdentifier leftJoinNode = mock(SqlIdentifier.class); - when(leftJoinNode.getKind()).thenReturn(SqlKind.IDENTIFIER); - when(leftJoinNode.getSimple()).thenReturn("q"); - leftJoinNode.names = ImmutableList.copyOf(Lists.newArrayList("a", "b")); - SqlNodeList parentSelectList = mock(SqlNodeList.class); - when(parentSelectList.getList()).thenReturn(Lists.newArrayList(leftJoinNode)); - SqlNodeList parentGroupByList = mock(SqlNodeList.class); - when(parentGroupByList.getList()).thenReturn(Lists.newArrayList(leftJoinNode)); - SqlNode parentWhere = null; - joinNodeDealer.replaceSelectAndWhereField(buildAs, leftJoinNode, Maps.newHashMap(), null, parentGroupByList, null, null); - } - - // @Test - public void extractTemporaryQuery() throws Exception { - Method method = JoinNodeDealer.class.getDeclaredMethod("extractTemporaryQuery", SqlNode.class, String.class, SqlBasicCall.class, - SqlNodeList.class, Queue.class, Set.class, Map.class, Map.class); - method.setAccessible(true); - - SqlIdentifier node = mock(SqlIdentifier.class); - when(node.getKind()).thenReturn(SqlKind.IDENTIFIER); - when(node.getSimple()).thenReturn("a"); - when(node.toString()).thenReturn("a.b"); - node.names = ImmutableList.copyOf(Lists.newArrayList("a", "b")); - - SqlBasicCall parentWhere = mock(SqlBasicCall.class); - when(parentWhere.getKind()).thenReturn(SqlKind.OTHER); - - SqlBasicCall sqlBasicCall = mock(SqlBasicCall.class); - when(sqlBasicCall.getKind()).thenReturn(SqlKind.AND); - when(sqlBasicCall.getOperands()).thenReturn(Lists.newArrayList(parentWhere, parentWhere).toArray(new SqlBasicCall[2])); - - - SqlNodeList parentSelectList = mock(SqlNodeList.class); - when(parentSelectList.getList()).thenReturn(Lists.newArrayList(node)); - - - String tableAlias = "a"; - Queue queueInfo = Queues.newLinkedBlockingQueue(); - Set> joinFieldSet = Sets.newHashSet(); - Map tableRef = Maps.newHashMap(); - Map fieldRef = Maps.newHashMap(); - - - method.invoke(joinNodeDealer, node, tableAlias, sqlBasicCall, parentSelectList, queueInfo, joinFieldSet, tableRef, fieldRef); - - } - - @Test - public void extractSelectFields() throws Exception { - Method method = JoinNodeDealer.class.getDeclaredMethod("extractSelectFields", SqlNodeList.class, Set.class, Map.class); - method.setAccessible(true); - - SqlIdentifier sqlNode = mock(SqlIdentifier.class); - when(sqlNode.getKind()).thenReturn(SqlKind.IDENTIFIER); - sqlNode.names = ImmutableList.copyOf(Lists.newArrayList("a", "b")); - SqlNodeList sqlNodeList = mock(SqlNodeList.class); - when(sqlNodeList.getList()).thenReturn(Lists.newArrayList(sqlNode)); - method.invoke(joinNodeDealer, sqlNodeList, Sets.newHashSet(), Maps.newHashMap()); - } - - @Test - public void extractSelectFieldFromJoinCondition() throws Exception { - Method method = JoinNodeDealer.class.getDeclaredMethod("extractSelectFieldFromJoinCondition", Set.class, Set.class, Map.class); - method.setAccessible(true); - Tuple2 tuple2 = new Tuple2("a", "b"); - Map map = Maps.newHashMap(); - map.put("a", "b"); - method.invoke(joinNodeDealer, Sets.newHashSet(tuple2), Sets.newHashSet("a"), map); - - } - - @Test - public void extractFieldFromGroupByList() throws Exception { - Method method = JoinNodeDealer.class.getDeclaredMethod("extractFieldFromGroupByList", SqlNodeList.class, Set.class, Map.class); - method.setAccessible(true); - method.invoke(joinNodeDealer, null, Sets.newHashSet(), Maps.newHashMap()); - - - SqlIdentifier sqlNode = mock(SqlIdentifier.class); - when(sqlNode.getKind()).thenReturn(SqlKind.IDENTIFIER); - sqlNode.names = ImmutableList.copyOf(Lists.newArrayList("a", "b")); - SqlNodeList sqlNodeList = mock(SqlNodeList.class); - when(sqlNodeList.getList()).thenReturn(Lists.newArrayList(sqlNode)); - method.invoke(joinNodeDealer, sqlNodeList, Sets.newHashSet(), Maps.newHashMap()); - } - - @Test - public void extractJoinField() throws Exception { - Method method = JoinNodeDealer.class.getDeclaredMethod("extractJoinField", SqlNode.class, Set.class); - method.setAccessible(true); - method.invoke(joinNodeDealer, null, Sets.newHashSet()); - - SqlIdentifier sqlNode = mock(SqlIdentifier.class); - when(sqlNode.getKind()).thenReturn(SqlKind.IDENTIFIER); - sqlNode.names = ImmutableList.copyOf(Lists.newArrayList("a", "b")); - SqlBasicCall sqlBasicCall = mock(SqlBasicCall.class); - when(sqlBasicCall.getKind()).thenReturn(SqlKind.LIKE); - when(sqlBasicCall.getOperands()).thenReturn(Lists.newArrayList(sqlNode).toArray(new SqlNode[1])); - method.invoke(joinNodeDealer, sqlBasicCall, Sets.newHashSet()); - } - - @Test - public void extractSelectField() throws Exception { - Method method = JoinNodeDealer.class.getDeclaredMethod("extractSelectField", SqlNode.class, Set.class, Set.class, Map.class); - method.setAccessible(true); - SqlIdentifier sqlNode = mock(SqlIdentifier.class); - when(sqlNode.getKind()).thenReturn(SqlKind.IDENTIFIER); - sqlNode.names = ImmutableList.copyOf(Lists.newArrayList("a", "b")); - method.invoke(joinNodeDealer,sqlNode, Sets.newHashSet(), Sets.newHashSet("a"), Maps.newHashMap()); - - SqlBasicCall sqlBasicCallAs = mock(SqlBasicCall.class); - when(sqlBasicCallAs.getKind()).thenReturn(SqlKind.AS); - when(sqlBasicCallAs.getOperands()).thenReturn(Lists.newArrayList(sqlNode).toArray(new SqlIdentifier[1])); - method.invoke(joinNodeDealer, sqlBasicCallAs, Sets.newHashSet(), Sets.newHashSet(), Maps.newHashMap()); - - - SqlBasicCall sqlBasicCallLike = mock(SqlBasicCall.class); - when(sqlBasicCallAs.getKind()).thenReturn(SqlKind.LIKE); - when(sqlBasicCallAs.getOperands()).thenReturn(Lists.newArrayList(sqlNode).toArray(new SqlIdentifier[1])); - method.invoke(joinNodeDealer, sqlBasicCallLike, Sets.newHashSet(), Sets.newHashSet(), Maps.newHashMap()); - - SqlCase sqlCase = mock(SqlCase.class); - when(sqlCase.getKind()).thenReturn(SqlKind.CAST); - SqlNodeList sqlNodeList = mock(SqlNodeList.class); - when(sqlNodeList.size()).thenReturn(1); - when(sqlNodeList.get(anyInt())).thenReturn(sqlNode); - when(sqlCase.getWhenOperands()).thenReturn(sqlNodeList); - when(sqlCase.getThenOperands()).thenReturn(sqlNodeList); - when(sqlCase.getElseOperand()).thenReturn(sqlNode); - method.invoke(joinNodeDealer, sqlBasicCallLike, Sets.newHashSet(), Sets.newHashSet(), Maps.newHashMap()); - } - - // @Test - public void parseRightNode() throws Exception { - Method method = JoinNodeDealer.class.getDeclaredMethod("parseRightNode" - , SqlNode.class - , Set.class - , Queue.class - , SqlNode.class - , SqlNodeList.class - , SqlNodeList.class - , String.class - , Set.class); - method.setAccessible(true); - - SqlNode sqlNode = mock(SqlNode.class); - when(sqlNode.getKind()).thenReturn(SqlKind.IDENTIFIER); - when(sqlNode.toString()).thenReturn("a"); - method.invoke(joinNodeDealer, sqlNode, null, null, null, null, null, null, null); - - AliasInfo aliasInfo = mock(AliasInfo.class); - when(aliasInfo.getName()).thenReturn("a"); - when(aliasInfo.getAlias()).thenReturn("b"); - when(sideSQLParser.parseSql(sqlNode, null, null, null, null, null, null, Sets.newHashSet())).thenReturn(aliasInfo); - when(sqlNode.getKind()).thenReturn(SqlKind.SELECT); - method.invoke(joinNodeDealer, sqlNode, null, null, null, null, null, null, null); - - } - - @Test - public void buildCondition(){ - joinNodeDealer.buildCondition(Lists.newArrayList()); - SqlBasicCall sqlBasicCall = mock(SqlBasicCall.class); - when(sqlBasicCall.toString()).thenReturn("a"); - joinNodeDealer.buildCondition(Lists.newArrayList(sqlBasicCall)); - } - - @Test - public void buildSelectNode(){ - try { - joinNodeDealer.buildSelectNode(null, null); - } catch (Exception e){ - - } - joinNodeDealer.buildSelectNode(Sets.newHashSet("a.b"), Sets.newHashSet("c.d")); - } - - @Test - public void checkIsSideTable() throws Exception { - Method method = JoinNodeDealer.class.getDeclaredMethod("checkIsSideTable", String.class, Set.class); - method.setAccessible(true); - - method.invoke(joinNodeDealer, "a", Sets.newHashSet()); - method.invoke(joinNodeDealer, "a", Sets.newHashSet("a")); - } - - @Test - public void buildAsSqlNode() throws Exception { - Method method = JoinNodeDealer.class.getDeclaredMethod("buildAsSqlNode", String.class, SqlNode.class); - method.setAccessible(true); - - SqlNode sqlNode = mock(SqlNode.class); - method.invoke(joinNodeDealer, "a", sqlNode); - } - - @Test - public void extractWhereCondition() throws Exception { - Method method = JoinNodeDealer.class.getDeclaredMethod("extractWhereCondition", Set.class, SqlBasicCall.class, Set.class); - method.setAccessible(true); - method.invoke(joinNodeDealer, null, null, null); - - SqlBasicCall parentWhere = mock(SqlBasicCall.class); - when(parentWhere.getKind()).thenReturn(SqlKind.OTHER); - method.invoke(joinNodeDealer, Sets.newHashSet(), parentWhere, Sets.newHashSet()); - - - SqlBasicCall sqlBasicCall = mock(SqlBasicCall.class); - when(sqlBasicCall.getKind()).thenReturn(SqlKind.AND); - when(sqlBasicCall.getOperands()).thenReturn(Lists.newArrayList(parentWhere, parentWhere).toArray(new SqlBasicCall[2])); - method.invoke(joinNodeDealer, Sets.newHashSet(), sqlBasicCall, Sets.newHashSet()); - } - - @Test - public void checkAndRemoveWhereCondition() throws Exception { - Method method = JoinNodeDealer.class.getDeclaredMethod("checkAndRemoveWhereCondition", Set.class, SqlBasicCall.class, List.class); - method.setAccessible(true); - - method.invoke(joinNodeDealer, null, null, null); - SqlBasicCall parentWhere = mock(SqlBasicCall.class); - when(parentWhere.getKind()).thenReturn(SqlKind.OTHER); - method.invoke(joinNodeDealer, Sets.newHashSet(), parentWhere, Lists.newArrayList()); - - SqlBasicCall sqlBasicCall = mock(SqlBasicCall.class); - when(sqlBasicCall.getKind()).thenReturn(SqlKind.AND); - when(sqlBasicCall.getOperands()).thenReturn(Lists.newArrayList(parentWhere, parentWhere).toArray(new SqlBasicCall[2])); - method.invoke(joinNodeDealer, Sets.newHashSet(), sqlBasicCall, Lists.newArrayList()); - } - - @Test - public void removeWhereConditionNode(){ - SqlBasicCall sqlBasicCall = mock(SqlBasicCall.class); - when(sqlBasicCall.getOperands()).thenReturn(Lists.newArrayList(sqlBasicCall).toArray(new SqlNode[1])); - joinNodeDealer.removeWhereConditionNode(sqlBasicCall, 0); - } - - @Test - public void buildEmptyCondition(){ - joinNodeDealer.buildEmptyCondition(); - } - - @Test - public void checkAndReplaceJoinCondition() throws Exception { - Method method = JoinNodeDealer.class.getDeclaredMethod("checkAndReplaceJoinCondition", SqlNode.class, Map.class); - method.setAccessible(true); - SqlBasicCall sqlBasicCall = mock(SqlBasicCall.class); - when(sqlBasicCall.getKind()).thenReturn(SqlKind.EQUALS); - SqlIdentifier sqlIdentifier = mock(SqlIdentifier.class); - when(sqlIdentifier.getKind()).thenReturn(SqlKind.IDENTIFIER); - sqlIdentifier.names = ImmutableList.copyOf(Lists.newArrayList("a", "b")); - when(sqlBasicCall.getOperands()).thenReturn(Lists.newArrayList(sqlIdentifier).toArray(new SqlNode[1])); - method.invoke(joinNodeDealer, sqlBasicCall, Maps.newHashMap()); - } - - @Test - public void buildTmpTableFieldRefOriField(){ - joinNodeDealer.buildTmpTableFieldRefOriField(Sets.newHashSet("a.b"), "x"); - } -} diff --git a/core/src/test/java/com/dtstack/flink/sql/side/SidePredicatesParserTest.java b/core/src/test/java/com/dtstack/flink/sql/side/SidePredicatesParserTest.java deleted file mode 100644 index aac873167..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/side/SidePredicatesParserTest.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.dtstack.flink.sql.side; - -import com.google.common.collect.Lists; -import org.apache.calcite.sql.SqlBasicCall; -import org.apache.calcite.sql.SqlCharStringLiteral; -import org.apache.calcite.sql.SqlIdentifier; -import org.apache.calcite.sql.SqlKind; -import org.apache.calcite.sql.SqlNode; -import org.apache.calcite.util.NlsString; -import org.apache.flink.calcite.shaded.com.google.common.collect.ImmutableList; -import org.junit.Assert; -import org.junit.Test; - -import java.lang.reflect.Method; -import java.util.List; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class SidePredicatesParserTest { - - private SidePredicatesParser sidePredicatesParser = new SidePredicatesParser(); - - @Test - public void testFillPredicateInfoToList() throws Exception { - Method method = SidePredicatesParser.class.getDeclaredMethod("fillPredicateInfoToList", SqlBasicCall.class, List.class, String.class, SqlKind.class, int.class, int.class); - method.setAccessible(true); - SqlBasicCall sqlBasicCall = mock(SqlBasicCall.class); - SqlIdentifier sqlNode = mock(SqlIdentifier.class); - when(sqlNode.getKind()).thenReturn(SqlKind.IDENTIFIER); - when(sqlNode.toString()).thenReturn("2"); - sqlNode.names = ImmutableList.copyOf(Lists.newArrayList("a", "b")); - when(sqlBasicCall.getOperands()).thenReturn(new SqlNode[]{sqlNode}); - - method.invoke(sidePredicatesParser, sqlBasicCall, Lists.newArrayList(), "a", SqlKind.IN, 0, 0); - } - - @Test - public void testRemoveCoding() throws Exception { - Method method = SidePredicatesParser.class.getDeclaredMethod("removeCoding", SqlCharStringLiteral.class); - method.setAccessible(true); - SqlCharStringLiteral stringLiteral = mock(SqlCharStringLiteral.class); - when(stringLiteral.getNlsString()).thenReturn(new NlsString("甲", "UTF16", null)); - - String val = (String) method.invoke(sidePredicatesParser, stringLiteral); - Assert.assertEquals("'甲'", val); - } - -} diff --git a/core/src/test/java/com/dtstack/flink/sql/side/SideSQLParserTest.java b/core/src/test/java/com/dtstack/flink/sql/side/SideSQLParserTest.java deleted file mode 100644 index 59c786a83..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/side/SideSQLParserTest.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.dtstack.flink.sql.side; - -public class SideSQLParserTest { -} diff --git a/core/src/test/java/com/dtstack/flink/sql/side/SideSqlExecTest.java b/core/src/test/java/com/dtstack/flink/sql/side/SideSqlExecTest.java index b3fd658f0..3bab778ae 100644 --- a/core/src/test/java/com/dtstack/flink/sql/side/SideSqlExecTest.java +++ b/core/src/test/java/com/dtstack/flink/sql/side/SideSqlExecTest.java @@ -1,298 +1,474 @@ +/* + * 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 com.dtstack.flink.sql.side; -import com.dtstack.flink.sql.exec.FlinkSQLExec; -import com.dtstack.flink.sql.parser.CreateTmpTableParser; -import com.dtstack.flink.sql.side.operator.SideWithAllCacheOperator; -import com.dtstack.flink.sql.util.ParseUtils; -import com.dtstack.flink.sql.util.TableUtils; -import com.google.common.collect.HashBasedTable; +import com.dtstack.flink.sql.Main; +import com.dtstack.flink.sql.parser.SqlParser; +import com.dtstack.flink.sql.parser.SqlTree; +import com.google.common.base.Charsets; import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Queues; -import jdk.nashorn.internal.runtime.regexp.joni.constants.StringType; -import org.apache.calcite.sql.SqlBasicCall; -import org.apache.calcite.sql.SqlIdentifier; -import org.apache.calcite.sql.SqlKind; -import org.apache.calcite.sql.SqlNode; -import org.apache.calcite.sql.SqlSelect; -import org.apache.calcite.sql.SqlWithItem; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.common.typeinfo.Types; -import org.apache.flink.api.dag.Transformation; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.streaming.api.datastream.DataStream; -import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator; -import org.apache.flink.table.api.StreamQueryConfig; -import org.apache.flink.table.api.Table; -import org.apache.flink.table.api.TableSchema; -import org.apache.flink.table.api.java.StreamTableEnvironment; -import org.apache.flink.table.runtime.typeutils.BaseRowTypeInfo; -import org.apache.flink.table.types.logical.LogicalType; -import org.apache.flink.table.types.logical.VarCharType; -import org.apache.flink.types.Row; -import org.junit.Before; import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import java.lang.reflect.Method; +import java.net.URLEncoder; import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Queue; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.anyList; -import static org.mockito.Mockito.anyMap; -import static org.mockito.Mockito.anySet; -import static org.mockito.Mockito.anyString; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.powermock.api.support.membermodification.MemberMatcher.method; -import static org.powermock.api.support.membermodification.MemberModifier.suppress; +/** + * Reason: + * Date: 2018/7/24 + * Company: www.dtstack.com + * + * @author xuchao + */ -@RunWith(PowerMockRunner.class) -@PrepareForTest({SideSqlExec.class - , FlinkSQLExec.class - , TableUtils.class - , ParseUtils.class - , SideWithAllCacheOperator.class - , SingleOutputStreamOperator.class}) public class SideSqlExecTest { - private SideSqlExec sideSqlExec; - - @Before - public void init() { - sideSqlExec = new SideSqlExec(); - sideSqlExec.setLocalSqlPluginPath(""); - sideSqlExec.setPluginLoadMode("2"); - } - - // @Test - public void exec() throws Exception { - String sql = ""; - Map sideTableMap = Maps.newHashMap(); - StreamTableEnvironment tableEnv = mock(StreamTableEnvironment.class); - Map tableCache = Maps.newHashMap(); - StreamQueryConfig queryConfig = mock(StreamQueryConfig.class); - CreateTmpTableParser.SqlParserResult createView = mock(CreateTmpTableParser.SqlParserResult.class); - String scope = "1"; - - Queue queue = Queues.newLinkedBlockingQueue(); - - - SideSQLParser sideSQLParser = mock(SideSQLParser.class); - PowerMockito.whenNew(SideSQLParser.class).withAnyArguments().thenReturn(sideSQLParser); - when(sideSQLParser.getExeQueue(anyString(), anySet(), anyString())).thenReturn(queue); - - // - SqlNode sqlNodeInsert = mock(SqlNode.class); - when(sqlNodeInsert.getKind()).thenReturn(SqlKind.INSERT); - when(sqlNodeInsert.toString()).thenReturn("a"); - suppress(method(FlinkSQLExec.class, "sqlUpdate")); - queue.add(sqlNodeInsert); - - SqlWithItem sqlNodeItem = mock(SqlWithItem.class); - when(sqlNodeItem.getKind()).thenReturn(SqlKind.WITH_ITEM); - - SqlIdentifier sqlIdentifier = mock(SqlIdentifier.class); - sqlNodeItem.name = sqlIdentifier; - when(sqlIdentifier.toString()).thenReturn("a"); - sqlNodeItem.query = sqlIdentifier; - queue.add(sqlNodeItem); - - SqlNode sqlNodeSelect = mock(SqlNode.class); - when(sqlNodeSelect.getKind()).thenReturn(SqlKind.SELECT); - when(sqlNodeSelect.toString()).thenReturn("a"); - when(createView.getTableName()).thenReturn("a"); - queue.add(sqlNodeSelect); - sideSqlExec.exec(sql, sideTableMap, tableEnv, tableCache, createView, scope); - } - - @Test - public void parseAsQuery() throws Exception { - Method method = SideSqlExec.class.getDeclaredMethod("parseAsQuery", SqlBasicCall.class, Map.class); - method.setAccessible(true); - - SqlBasicCall sqlBasicCall = mock(SqlBasicCall.class); - Map tableCache = Maps.newHashMap(); - - SqlSelect sqlSelect = mock(SqlSelect.class); - when(sqlBasicCall.getOperands()).thenReturn(Lists.newArrayList(sqlSelect, sqlSelect).toArray(new SqlNode[2])); - method.invoke(sideSqlExec, sqlBasicCall, tableCache); - - FieldInfo fieldInfo = mock(FieldInfo.class); - when(fieldInfo.getFieldName()).thenReturn("a"); - when(fieldInfo.getTable()).thenReturn("t"); - - when(sqlBasicCall.getKind()).thenReturn(SqlKind.SELECT); - PowerMockito.mockStatic(TableUtils.class); - when(TableUtils.parserSelectField(any(), anyMap())).thenReturn(Lists.newArrayList(fieldInfo)); - - PowerMockito.mockStatic(ParseUtils.class); - when(ParseUtils.dealDuplicateFieldName(anyMap(), anyString())).thenReturn("a"); - method.invoke(sideSqlExec, sqlBasicCall, tableCache); + public void testRunSideSql() throws Exception { + //String runParam = "-sql CREATE+TABLE+MyTable(channel+STRING%2c+pv+INT%2c+xctime+bigint%2c+timeLeng+as+CHARACTER_LENGTH(channel)%2c++WATERMARK+FOR+xctime+AS+withOffset(xctime%2c+1000))+WITH+(+type%3d%27kafka09%27%2c+bootstrapServers%3d%27172.16.8.198%3a9092%27%2c+offsetReset%3d%27latest%27%2ctopic%3d%27nbTest1%27)%3bCREATE+TABLE+MyResult(channel+STRING%2c+pv+INT)+WITH+(+type%3d%27mysql%27%2c+url%3d%27jdbc%3amysql%3a%2f%2f172.16.8.104%3a3306%2ftest%3fcharset%3dutf8%27%2cuserName%3d%27dtstack%27%2cpassword%3d%27abc123%27%2c+tableName%3d%27pv%27)%3bcreate+table+sideTable(channel+String%2c+count+int%2c+PERIOD+FOR+SYSTEM_TIME)+WITH+(+type%3d%27mysql%27%2c+url%3d%27jdbc%3amysql%3a%2f%2f172.16.8.104%3a3306%2ftest%3fcharset%3dutf8%27%2cuserName%3d%27dtstack%27%2cpassword%3d%27abc123%27%2c+tableName%3d%27pv%27)%3binsert+into+MyResult+select+a.channel%2cb.pv+from+MyTable+a+join+sideTable+b+on+a.channel%3db.channel%3b -name xc -localSqlPluginPath D:\\gitspace\\flink-sql-plugin\\plugins -mode local -remoteSqlPluginPath /opt/dtstack/flinkplugin -confProp %7b%22time.characteristic%22%3a%22EventTime%22%7d -addjar %5b%22D%3a%5c%5cgitspace%5c%5crdos-execution-engine%5c%5c..%5c%5ctmp140%5c%5cflink14Test-1.0-SNAPSHOT.jar%22%5d"; + + List paramList = Lists.newArrayList(); + paramList.add("-sql"); +// String sql = "CREATE TABLE MyTable(channel STRING, pv INT, xctime bigint, timeLeng as CHARACTER_LENGTH(channel), WATERMARK FOR xctime AS withOffset(xctime, 1000)) WITH ( type='kafka09', bootstrapServers='172.16.8.198:9092', offsetReset='latest',topic='nbTest1');" + +// "CREATE TABLE MyResult(channel STRING, pv INT) WITH ( type='mysql', url='jdbc:mysql://172.16.8.104:3306/test?charset=utf8',userName='dtstack',password='abc123', tableName='pv');" + +// "create table sideTable(channel String, xccount int, PRIMARY KEY (channel),PERIOD FOR SYSTEM_TIME) WITH ( type='mysql', url='jdbc:mysql://172.16.8.104:3306/test?charset=utf8',userName='dtstack',password='abc123', tableName='sidetest');" + +// "insert into MyResult select a.channel,b.xccount from MyTable a join sideTable b on a.channel=b.channel where b.channel = 'xc' and a.pv=10"; + + //String insetSql = "insert into MyResult select a.channel,b.xccount from MyTable a join sideTable b on a.channel=b.channel where b.channel = 'xc' and a.pv=10;"; + //String insetSql = "insert into MyResult select a.channel,b.xccount from (select * from MyTable) a left join sideTable b on a.channel=b.channel where a.channel = 'xc1' and a.pv=10;"; + //String insetSql = "insert into MyResult select * from sideTable"; + //sql = sql + insetSql; + //String sql = "create scala function xchashcode with com.xc.udf.MyHashCode;CREATE TABLE MyTable ( channel STRING, pv INT, xctime bigint, timeLeng AS CHARACTER_LENGTH(channel),WATERMARK FOR xctime AS withOffset( xctime , 10000 )) WITH (type = 'kafka09',bootstrapServers = '172.16.8.198:9092',zookeeperConnect = '172.16.8.198:2181/kafka', offsetReset = 'latest',topic = 'nbTest1',parallelism = '1');CREATE TABLE MyResult ( channel VARCHAR, pv bigint) WITH (type = 'mysql',url = 'jdbc:mysql://172.16.8.104:3306/test?charset=utf8',userName = 'dtstack',password = 'abc123',tableName = 'pv',parallelism = '1');insert into MyResult select channel, count(channel) from MyTable GROUP BY channel ;"; + //String sql = "create scala function xchashcode with com.xc.udf.MyHashCode;CREATE TABLE MyTable ( channel STRING, pv INT, xctime bigint, timeLeng AS CHARACTER_LENGTH(channel),WATERMARK FOR xctime AS withOffset( xctime , 10000 )) WITH (type = 'kafka09',bootstrapServers = '172.16.8.198:9092',zookeeperConnect = '172.16.8.198:2181/kafka', offsetReset = 'latest',topic = 'nbTest1',parallelism = '1');CREATE TABLE MyResult ( channel VARCHAR, pv bigint) WITH (type = 'mysql',url = 'jdbc:mysql://172.16.8.104:3306/test?charset=utf8',userName = 'dtstack',password = 'abc123',tableName = 'pv',parallelism = '1');insert into MyResult select channel, count(channel) from MyTable GROUP BY TUMBLE(rowtime, INTERVAL '3' SECOND), channel ;"; +// String sql = "CREATE TABLE MyTable(channel STRING, pv INT, xctime bigint, timeLeng as CHARACTER_LENGTH(channel), WATERMARK FOR xctime AS withOffset(xctime, 100)) WITH ( type='kafka09', bootstrapServers='172.16.8.198:9092', offsetReset='latest',topic='nbTest1');\n" + +// "CREATE TABLE MyResult(cf:channel STRING, cf:pv BIGINT) WITH ( type='hbase', zookeeperQuorum='rdos1:2181', zookeeperParent = '/hbase', tableName='tb1', rowkey='cf:channel');\n" + +// "insert into MyResult select channel from MyTable group by channel"; + //String sql ="CREATE TABLE student_1 ( id_1 varchar, name_1 varchar, sex_1 varchar) WITH (type = 'kafka09',bootstrapServers = '172.16.8.198:9092',zookeeperQuorum = '172.16.8.198:2181/kafka', offsetReset = 'latest',topic = 'test',parallelism = '1');CREATE TABLE sum_1 ( id_1 VARCHAR, sex_1 VARCHAR, name_1 VARCHAR, mark_1 INT) WITH (type = 'mysql',url = 'jdbc:mysql://172.16.8.104:3306/test?charset=utf8',userName = 'dtstack',password = 'abc123',tableName = 'sum_1',parallelism = '1');CREATE TABLE score_1 ( id_1 VARCHAR, name_1 VARCHAR, mark_1 INT,PRIMARY KEY (id_1) , PERIOD FOR SYSTEM_TIME ) WITH (type = 'mysql',url = 'jdbc:mysql://172.16.8.104:3306/test?charset=utf8',userName = 'dtstack',password = 'abc123',tableName = 'score_1',cache = 'LRU',cacheSize = '10000',cacheTTLMs = '60000',parallelism = '1');insert into sum_1 select a.id_1, a.sex_1, a.name_1, b.mark_1 from student_1 a inner join score_1 b on a.id=b.id_1;"; + //String sql = "CREATE TABLE MyTable ( channel STRING, pv INT, xctime bigint) WITH (type = 'kafka09',bootstrapServers = '172.16.8.198:9092',zookeeperQuorum = '172.16.8.198:2181/kafka', offsetReset = 'latest',topic = 'nbTest1',parallelism = '1');CREATE TABLE MyResult ( aa INT, bb INT) WITH (type = 'elasticsearch',address = '172.16.10.47:9500',cluster='es_47_menghan',estype = 'type1',index = 'xc_es_test',id = '0,1',parallelism = '1');insert into MyResult select pv,pv from MyTable;"; + + String sql = "CREATE TABLE bal_cur_batch_s30_pb_tranflow_input (trf_flowno varchar, trf_batno varchar, trf_cstno varchar, trf_bsncode varchar, trf_transtype varchar, trf_payacc varchar, trf_paysubacc varchar, trf_payname varchar, trf_rcvacc varchar, trf_rcvsubacc varchar, trf_rcvname varchar, trf_rcvbank varchar, trf_comitrno varchar, trf_crytype varchar, trf_subtime varchar, trf_tranamet varchar, trf_fee1 varchar, trf_fee2 varchar, trf_fee3 varchar, trf_userrem varchar, trf_hostflwno varchar, trf_hostsendtime varchar, trf_hosterror varchar, trf_lastupdtime varchar, trf_stt varchar, trf_schl_flowno varchar, trf_logontype varchar, trf_reccity varchar, trf_recprovice varchar, trf_channel varchar, trf_hosterrormsg varchar, trf_ext1 varchar, trf_ext2 varchar, trf_security varchar, cast(current_timestamp as varchar) as currTime) WITH (type = 'kafka09',bootstrapServers = 'kudu1:9092',zookeeperQuorum = '172.16.8.107:2181/kafka', offsetReset = 'latest',topic = 'tranflow_input',parallelism = '1');CREATE TABLE resultbank ( run_date VARCHAR, run_time VARCHAR, trf_flowno VARCHAR, trf_payname VARCHAR, trf_payacc VARCHAR, trf_tranamet VARCHAR, trf_subtime VARCHAR, trf_rcvbank VARCHAR,PRIMARY KEY (run_date,run_time,trf_flowno) ) WITH (type = 'mysql',url = 'jdbc:mysql://172.16.8.104:3306/bank_test?charset=utf8',userName = 'dtstack',password = 'abc123',tableName = 'resultbank',parallelism = '1');CREATE TABLE bal_cur_batch_rds_report_lrlct_trans_cur_input ( run_date VARCHAR, run_time VARCHAR, trf_flowno VARCHAR, trf_payname VARCHAR, trf_payacc VARCHAR, trf_subtime VARCHAR, trf_rcvbank VARCHAR,PRIMARY KEY (run_date,trf_flowno) , PERIOD FOR SYSTEM_TIME ) WITH (type = 'mysql',url = 'jdbc:mysql://172.16.8.104:3306/bank_test?charset=utf8',userName = 'dtstack',password = 'abc123',tableName = 'rds_report_lrlc_trans_cur',cache = 'LRU',cacheSize = '10000',cacheTTLMs = '60000',parallelism = '1');CREATE TABLE bal_cur_batch_t03_deposit_acct_base_info_cur_input ( data_dt VARCHAR, card_id VARCHAR, sub_acct_id VARCHAR, acct_org varchar, acct_stat_cd VARCHAR, core_cust_id VARCHAR, cust_rm VARCHAR, cust_scale_cd VARCHAR, item_id VARCHAR,PRIMARY KEY (card_id) , PERIOD FOR SYSTEM_TIME ) WITH (type = 'mysql',url = 'jdbc:mysql://172.16.8.104:3306/bank_test?charset=utf8',userName = 'dtstack',password = 'abc123',tableName = 't03_deposit_acct_base_info',cache = 'LRU',cacheSize = '10000',cacheTTLMs = '60000',parallelism = '1');CREATE TABLE bal_cur_batch_t04_org_cur_cur_input ( org_id VARCHAR, org_nm VARCHAR, org_short_nm VARCHAR, up_lvl_org_id VARCHAR, org_lvl VARCHAR, org_sort VARCHAR, org_cur VARCHAR,PRIMARY KEY (org_id) , PERIOD FOR SYSTEM_TIME ) WITH (type = 'mysql',url = 'jdbc:mysql://172.16.8.104:3306/bank_test?charset=utf8',userName = 'dtstack',password = 'abc123',tableName = 't04_org_cur',cache = 'LRU',cacheSize = '10000',cacheTTLMs = '60000',parallelism = '1');CREATE TABLE max_deposit_acct_base ( max_data_dt varchar, PRIMARY KEY (max_data_dt) , PERIOD FOR SYSTEM_TIME ) WITH (type = 'mysql',url = 'jdbc:mysql://172.16.8.104:3306/bank_test?charset=utf8',userName = 'dtstack',password = 'abc123',tableName = 'max_deposit_acct_base',cache = 'LRU',cacheSize = '10000',cacheTTLMs = '60000',parallelism = '1');\n" + + "INSERT \n" + + "INTO resultbank select d.run_date,\n" + + " d.run_time,\n" + + " d.trf_flowno,\n" + + " d.trf_payname,\n" + + " d.trf_payacc,\n" + + " d.trf_tranamet,\n" + + " d.trf_rcvbank,\n" + + " d.org_nm \n" + + " from\n" + + " (\n" + + " select\n" + + " cast(current_timestamp as varchar) as run_date,\n" + + " SUBSTRING(cast(current_timestamp as varchar) from 1 for 16) as run_time,\n" + + " b.trf_flowno,\n" + + " b.trf_payname,\n" + + " b.trf_payacc,\n" + + " b.trf_tranamet,\n" + + " b.trf_rcvbank,\n" + + " b.data_dt,\n" + + " t3.org_nm \n" + + " from\n" + + " ( select\n" + + " a.trf_flowno,\n" + + " a.currTime,\n" + + " a.trf_payname,\n" + + " a.trf_tranamet,\n" + + " a.trf_rcvbank,\n" + + " a.trf_payacc,\n" + + " a.trf_subtime,\n" + + " a.trf_bsncode,\n" + + " t2.acct_org,\n" + + " t2.data_dt,\n" + + " current_timestamp as nowtime\n" + + " from\n" + + " (select\n" + + " t1.trf_flowno,\n" + + " t1.currTime,\n" + + " t1.trf_payname,\n" + + " t1.trf_tranamet,\n" + + " t1.trf_rcvbank,\n" + + " t1.trf_subtime,\n" + + " t1.trf_payacc,\n" + + " t1.trf_bsncode\n" + + " from\n" + + " bal_cur_batch_s30_pb_tranflow_input t1 \n" + + " join\n" + + " bal_cur_batch_rds_report_lrlct_trans_cur_input x \n" + + " on t1.trf_flowno = x.trf_flowno \n" + + " and x.run_date = t1.currTime ) as a \n" + + " join\n" + + " bal_cur_batch_t03_deposit_acct_base_info_cur_input t2 \n" + + " on a.trf_payacc = t2.card_id \n" + + " ) as b \n" + + " join\n" + + " bal_cur_batch_t04_org_cur_cur_input t3 \n" + + " on b.acct_org = t3.org_id\n" + + " where \n" + + " b.trf_bsncode in('002002', '002003', '002011')\n" + + " and b.trf_flowno is null \n" + + " and substring(b.trf_subtime from 1 for 8) = DATE_FORMAT(b.nowtime, '%Y%m%d')\n" + + " and cast(b.trf_tranamet as decimal) >= 100000000\n" + + " ) as d\n" + + " join max_deposit_acct_base maxdep\n" + + " on d.data_dt = maxdep.max_data_dt\n"; + test(sql); } @Test - public void buildOutRowTypeInfo() { - FieldInfo fieldInfo = mock(FieldInfo.class); - when(fieldInfo.getTable()).thenReturn("t"); - when(fieldInfo.getFieldName()).thenReturn("a"); - when(fieldInfo.getTypeInformation()).thenReturn(Types.STRING); - when(fieldInfo.getLogicalType()).thenReturn(new VarCharType()); - List sideJoinFieldInfo = Lists.newArrayList(fieldInfo); - HashBasedTable mappingTable = HashBasedTable.create(); - mappingTable.put("t", "a", "n"); - sideSqlExec.buildOutRowTypeInfo(sideJoinFieldInfo, mappingTable); + public void testRunHbaseSideTable() throws Exception { + String sql = "CREATE TABLE MyTable ( name string, channel STRING, pv INT, xctime bigint, CHARACTER_LENGTH(channel) AS timeLeng) " + + "WITH (type = 'kafka09',bootstrapServers = '172.16.8.198:9092',zookeeperQuorum = '172.16.8.198:2181/kafka', " + + "offsetReset = 'latest',topic = 'nbTest1',parallelism = '1');" + + "CREATE TABLE MyResult ( channel VARCHAR, pv VARCHAR) WITH (type = 'mysql'," + + "url = 'jdbc:mysql://172.16.8.104:3306/test?charset=utf8',userName = 'dtstack',password = 'abc123',tableName = 'pv2'," + + "parallelism = '1');CREATE TABLE workerinfo ( cast(logtime as TIMESTAMP) AS rtime, cast(logtime) AS rtime) " + + "WITH (type = 'hbase',zookeeperQuorum = 'rdos1:2181',tableName = 'workerinfo',rowKey = 'ce,de'," + + "parallelism = '1',zookeeperParent = '/hbase');CREATE TABLE sideTable " + + "( cf:name String as name, cf:info String as info,PRIMARY KEY (name) , PERIOD FOR SYSTEM_TIME ) WITH " + + "(type = 'hbase',zookeeperQuorum = 'rdos1:2181',zookeeperParent = '/hbase',tableName = 'workerinfo',cache = 'LRU'," + + "cacheSize = '10000',cacheTTLMs = '60000',parallelism = '1');" + + "insert \n" + + "into\n" + + " MyResult\n" + + " select d.channel,d.info\n" + + " from\n" + + " (\n" + + " select\n" + + " *\n" + + " from\n" + + " MyTable a \n" + + " join\n" + + " sideTable b \n" + + " on a.channel=b.name \n" + + " where\n" + + " a.channel = 'xc2' \n" + + " and a.pv=10\n" + + " ) as d\n"; + + test(sql); } @Test - public void getTableFromCache() throws Exception { - Method method = SideSqlExec.class.getDeclaredMethod("getTableFromCache", Map.class, String.class, String.class); - method.setAccessible(true); - Map localTableCache = Maps.newHashMap(); - try { - method.invoke(sideSqlExec, localTableCache, "a", "b"); - } catch (Exception e) { - - } - Table table = mock(Table.class); - localTableCache.put("a", table); - method.invoke(sideSqlExec, localTableCache, "a", "b"); + public void testMysqlAllCache() throws Exception { + String sql = "CREATE TABLE MyTable(\n" + + " channel STRING,\n" + + " pv INT,\n" + + " xctime bigint,\n" + + " CHARACTER_LENGTH(channel) as timeLeng,\n" + + " WATERMARK FOR xctime AS withOffset(xctime,1000)\n" + + " )WITH(\n" + + " type='kafka09',\n" + + " bootstrapServers='172.16.8.198:9092',\n" + + " offsetReset='latest',\n" + + " topic='nbTest1'\n" + + " );\n" + + "CREATE TABLE MyResult(\n" + + " channel STRING,\n" + + " pv INT\n" + + " )WITH(\n" + + " type='mysql',\n" + + " url='jdbc:mysql://172.16.8.104:3306/test?charset=utf8',\n" + + " userName='dtstack',\n" + + " password='abc123',\n" + + " tableName='pv'\n" + + " );\n" + + "create table sideTable(\n" + + " channel String,\n" + + " xccount int,\n" + + " PRIMARY KEY(channel),\n" + + " PERIOD FOR SYSTEM_TIME\n" + + " )WITH(\n" + + " type='mysql',\n" + + " url='jdbc:mysql://172.16.8.104:3306/test?charset=utf8',\n" + + " userName='dtstack',\n" + + " password='abc123',\n" + + " tableName='sidetest',\n" + + " cache = 'ALL'\n" + + " );\n" + + "insert \n" + + "into\n" + + " MyResult\n" + + " select\n" + + " a.channel,\n" + + " b.xccount \n" + + " from\n" + + " MyTable a \n" + + " join\n" + + " sideTable b \n" + + " on a.channel=b.channel \n" + + " where\n" + + " b.channel = 'xc' \n" + + " and a.pv=10"; + + test(sql); } - @Test - public void getConditionFields() { - SqlBasicCall conditionNode = mock(SqlBasicCall.class); - String specifyTableName = "a"; - AbstractSideTableInfo sideTableInfo = mock(AbstractSideTableInfo.class); - try { - sideSqlExec.getConditionFields(conditionNode, specifyTableName, sideTableInfo); - - } catch (Exception e) { - - } - when(conditionNode.getKind()).thenReturn(SqlKind.EQUALS); - - SqlIdentifier sqlIdentifier = mock(SqlIdentifier.class); - when(conditionNode.getOperands()).thenReturn(Lists.newArrayList(sqlIdentifier, sqlIdentifier).toArray(new SqlNode[2])); - when(sqlIdentifier.getComponent(anyInt())).thenReturn(sqlIdentifier); - when(sqlIdentifier.getSimple()).thenReturn("a"); - - when(sideTableInfo.getPhysicalFields()).thenReturn(Maps.newHashMap()); - sideSqlExec.getConditionFields(conditionNode, specifyTableName, sideTableInfo); - - try { - specifyTableName = "x"; - sideSqlExec.getConditionFields(conditionNode, specifyTableName, sideTableInfo); - - } catch (Exception e) { - - } + public void test(String sql) throws Exception { + List paramList = Lists.newArrayList(); + paramList.add("-sql"); + String exeSql = URLEncoder.encode(sql, Charsets.UTF_8.name()); + paramList.add(exeSql); + paramList.add("-name"); + paramList.add("xc"); + paramList.add("-localSqlPluginPath"); + paramList.add("D:\\soucecode\\flinkStreamSQL\\plugins"); + paramList.add("-mode"); + paramList.add("local"); + paramList.add("-addjar"); + paramList.add(URLEncoder.encode("[\"D:\\\\soucecode\\\\rdos-execution-engine\\\\..\\\\tmp140\\\\flink14Test-1.0-SNAPSHOT.jar\"]", Charsets.UTF_8.name())); + paramList.add("-remoteSqlPluginPath"); + paramList.add("/opt/dtstack/flinkplugin"); + paramList.add("-confProp"); + String conf = "{\"time.characteristic\":\"EventTime\",\"sql.checkpoint.interval\":10000}"; + String confEncode = URLEncoder.encode(conf, Charsets.UTF_8.name()); + paramList.add(confEncode); + + String[] params = new String[paramList.size()]; + paramList.toArray(params); + Main.main(params); } - // @Test - public void dealAsSourceTable() throws Exception { - Method method = SideSqlExec.class.getDeclaredMethod("dealAsSourceTable", StreamTableEnvironment.class, SqlNode.class, Map.class); - method.setAccessible(true); - StreamTableEnvironment tableEnv = mock(StreamTableEnvironment.class); - SqlBasicCall sqlNode = mock(SqlBasicCall.class); - Map tableCache = Maps.newHashMap(); - - Table table = mock(Table.class); - when(tableEnv.sqlQuery(anyString())).thenReturn(table); - - when(sqlNode.getKind()).thenReturn(SqlKind.AS); - SqlBasicCall sqlBasicCall = mock(SqlBasicCall.class); - when(sqlBasicCall.toString()).thenReturn("a"); - - when(sqlNode.getOperands()).thenReturn(Lists.newArrayList(sqlBasicCall, sqlBasicCall).toArray(new SqlNode[2])); - - method.invoke(sideSqlExec, tableEnv, sqlNode, tableCache); + @Test + public void testParseSql() throws Exception { + String sql = "CREATE TABLE bal_cur_batch_s30_pb_tranflow_input (trf_flowno varchar, trf_batno varchar, trf_cstno varchar, trf_bsncode varchar, trf_transtype varchar, trf_payacc varchar, trf_paysubacc varchar, trf_payname varchar, trf_rcvacc varchar, trf_rcvsubacc varchar, trf_rcvname varchar, trf_rcvbank varchar, trf_comitrno varchar, trf_crytype varchar, trf_subtime varchar, trf_tranamet varchar, trf_fee1 varchar, trf_fee2 varchar, trf_fee3 varchar, trf_userrem varchar, trf_hostflwno varchar, trf_hostsendtime varchar, trf_hosterror varchar, trf_lastupdtime varchar, trf_stt varchar, trf_schl_flowno varchar, trf_logontype varchar, trf_reccity varchar, trf_recprovice varchar, trf_channel varchar, trf_hosterrormsg varchar, trf_ext1 varchar, trf_ext2 varchar, trf_security varchar, cast(current_timestamp as varchar) as currTime) WITH (type = 'kafka09',bootstrapServers = 'kudu1:9092',zookeeperQuorum = '172.16.8.107:2181/kafka', offsetReset = 'latest',topic = 'tranflow_input',parallelism = '1');CREATE TABLE resultbank ( run_date VARCHAR, run_time VARCHAR, trf_flowno VARCHAR, trf_payname VARCHAR, trf_payacc VARCHAR, trf_tranamet VARCHAR, trf_subtime VARCHAR, trf_rcvbank VARCHAR,PRIMARY KEY (run_date,run_time,trf_flowno) ) WITH (type = 'mysql',url = 'jdbc:mysql://172.16.8.104:3306/bank_test?charset=utf8',userName = 'dtstack',password = 'abc123',tableName = 'resultbank',parallelism = '1');CREATE TABLE bal_cur_batch_rds_report_lrlct_trans_cur_input ( run_date VARCHAR, run_time VARCHAR, trf_flowno VARCHAR, trf_payname VARCHAR, trf_payacc VARCHAR, trf_subtime VARCHAR, trf_rcvbank VARCHAR,PRIMARY KEY (run_date,trf_flowno) , PERIOD FOR SYSTEM_TIME ) WITH (type = 'mysql',url = 'jdbc:mysql://172.16.8.104:3306/bank_test?charset=utf8',userName = 'dtstack',password = 'abc123',tableName = 'rds_report_lrlc_trans_cur',cache = 'LRU',cacheSize = '10000',cacheTTLMs = '60000',parallelism = '1');CREATE TABLE bal_cur_batch_t03_deposit_acct_base_info_cur_input ( data_dt VARCHAR, card_id VARCHAR, sub_acct_id VARCHAR, acct_org varchar, acct_stat_cd VARCHAR, core_cust_id VARCHAR, cust_rm VARCHAR, cust_scale_cd VARCHAR, item_id VARCHAR,PRIMARY KEY (card_id) , PERIOD FOR SYSTEM_TIME ) WITH (type = 'mysql',url = 'jdbc:mysql://172.16.8.104:3306/bank_test?charset=utf8',userName = 'dtstack',password = 'abc123',tableName = 't03_deposit_acct_base_info',cache = 'LRU',cacheSize = '10000',cacheTTLMs = '60000',parallelism = '1');CREATE TABLE bal_cur_batch_t04_org_cur_cur_input ( org_id VARCHAR, org_nm VARCHAR, org_short_nm VARCHAR, up_lvl_org_id VARCHAR, org_lvl VARCHAR, org_sort VARCHAR, org_cur VARCHAR,PRIMARY KEY (org_id) , PERIOD FOR SYSTEM_TIME ) WITH (type = 'mysql',url = 'jdbc:mysql://172.16.8.104:3306/bank_test?charset=utf8',userName = 'dtstack',password = 'abc123',tableName = 't04_org_cur',cache = 'LRU',cacheSize = '10000',cacheTTLMs = '60000',parallelism = '1');CREATE TABLE max_deposit_acct_base ( max_data_dt varchar, PRIMARY KEY (max_data_dt) , PERIOD FOR SYSTEM_TIME ) WITH (type = 'mysql',url = 'jdbc:mysql://172.16.8.104:3306/bank_test?charset=utf8',userName = 'dtstack',password = 'abc123',tableName = 'max_deposit_acct_base',cache = 'LRU',cacheSize = '10000',cacheTTLMs = '60000',parallelism = '1');\n" + + "INSERT \n" + + "INTO resultbank select d.run_date,\n" + + " d.run_time,\n" + + " d.trf_flowno,\n" + + " d.trf_payname,\n" + + " d.trf_payacc,\n" + + " d.trf_tranamet,\n" + + " d.trf_rcvbank,\n" + + " d.org_nm \n" + + " from\n" + + " (\n" + + " select\n" + + " cast(current_timestamp as varchar) as run_date,\n" + + " SUBSTRING(cast(current_timestamp as varchar) from 1 for 16) as run_time,\n" + + " b.trf_flowno,\n" + + " b.trf_payname,\n" + + " b.trf_payacc,\n" + + " b.trf_tranamet,\n" + + " b.trf_rcvbank,\n" + + " b.data_dt,\n" + + " t3.org_nm \n" + + " from\n" + + " ( select\n" + + " a.trf_flowno,\n" + + " a.currTime,\n" + + " a.trf_payname,\n" + + " a.trf_tranamet,\n" + + " a.trf_rcvbank,\n" + + " a.trf_payacc,\n" + + " a.trf_subtime,\n" + + " a.trf_bsncode,\n" + + " t2.acct_org,\n" + + " t2.data_dt,\n" + + " current_timestamp as nowtime\n" + + " from\n" + + " (select\n" + + " t1.trf_flowno,\n" + + " t1.currTime,\n" + + " t1.trf_payname,\n" + + " t1.trf_tranamet,\n" + + " t1.trf_rcvbank,\n" + + " t1.trf_subtime,\n" + + " t1.trf_payacc,\n" + + " t1.trf_bsncode\n" + + " from\n" + + " bal_cur_batch_s30_pb_tranflow_input t1 \n" + + " join\n" + + " bal_cur_batch_rds_report_lrlct_trans_cur_input x \n" + + " on t1.trf_flowno = x.trf_flowno \n" + + " and x.run_date = t1.currTime ) as a \n" + + " join\n" + + " bal_cur_batch_t03_deposit_acct_base_info_cur_input t2 \n" + + " on a.trf_payacc = t2.card_id \n" + + " ) as b \n" + + " join\n" + + " bal_cur_batch_t04_org_cur_cur_input t3 \n" + + " on b.acct_org = t3.org_id\n" + + " where \n" + + " b.trf_bsncode in('002002', '002003', '002011')\n" + + " and b.trf_flowno is null \n" + + " and substring(b.trf_subtime from 1 for 8) = DATE_FORMAT(b.nowtime, '%Y%m%d')\n" + + " and cast(b.trf_tranamet as decimal) >= 100000000\n" + + " ) as d\n" + + " join max_deposit_acct_base maxdep\n" + + " on d.data_dt = maxdep.max_data_dt\n"; +// sql = URLDecoder.decode(sql, org.apache.commons.io.Charsets.UTF_8.name()); + String localSqlPluginPath = "D:\\soucecode\\flinkStreamSQL\\plugins"; + SqlParser.setLocalSqlPluginRoot(localSqlPluginPath); + SqlTree sqlTree = SqlParser.parseSql(sql); + System.out.println("1111"); } - // @Test - public void joinFun() throws Exception { - JoinInfo joinInfo = mock(JoinInfo.class); - Map localTableCache = Maps.newHashMap(); - Map sideTableMap = Maps.newHashMap(); - StreamTableEnvironment tableEnv = mock(StreamTableEnvironment.class); - Method method = SideSqlExec.class.getDeclaredMethod("joinFun", Object.class, Map.class, Map.class, StreamTableEnvironment.class); - method.setAccessible(true); - - - SqlBasicCall conditionNode = mock(SqlBasicCall.class); - when(conditionNode.getKind()).thenReturn(SqlKind.EQUALS); - SqlIdentifier sqlIdentifier = mock(SqlIdentifier.class); - when(conditionNode.getOperands()).thenReturn(Lists.newArrayList(sqlIdentifier, sqlIdentifier).toArray(new SqlNode[2])); - when(sqlIdentifier.getComponent(anyInt())).thenReturn(sqlIdentifier); - when(sqlIdentifier.getSimple()).thenReturn("a"); - - when(joinInfo.getLeftTableAlias()).thenReturn("a"); - when(joinInfo.getLeftTableName()).thenReturn("tablea"); - when(joinInfo.getRightTableAlias()).thenReturn("b"); - when(joinInfo.getRightTableName()).thenReturn("tableb"); - when(joinInfo.getTableFieldRef()).thenReturn(HashBasedTable.create()); - when(joinInfo.getCondition()).thenReturn(conditionNode); - - AbstractSideTableInfo sideTableInfo = mock(AbstractSideTableInfo.class); - sideTableMap.put("b", sideTableInfo); - when(sideTableInfo.getRowTypeInfo()).thenReturn(new RowTypeInfo(new TypeInformation[]{Types.STRING}, new String[]{"a"})); - when(sideTableInfo.getBaseRowTypeInfo()).thenReturn(new BaseRowTypeInfo(new LogicalType[]{new VarCharType()}, new String[]{"a"})); - when(sideTableInfo.isPartitionedJoin()).thenReturn(true); - when(sideTableInfo.getCacheType()).thenReturn("ALL"); - when(sideTableInfo.getType()).thenReturn("kafka"); - - - Table table = mock(Table.class); - localTableCache.put("a", table); - - - DataStream dsOut = mock(DataStream.class); - PowerMockito.mockStatic(SideWithAllCacheOperator.class); - when(SideWithAllCacheOperator.getSideJoinDataStream(any(), anyString(), anyString(), any(), any(), anyList(), any(), anyString())).thenReturn(dsOut); - Transformation streamTransformation = mock(Transformation.class); - when(dsOut.getTransformation()).thenReturn(streamTransformation); - - when(table.getSchema()).thenReturn(new TableSchema(new String[]{"a"}, new TypeInformation[]{Types.STRING})); - - - SingleOutputStreamOperator dataStream = mock(SingleOutputStreamOperator.class); - when(tableEnv.toRetractStream(table, Row.class)).thenReturn(dataStream); - when(dataStream.filter(any())).thenReturn(dataStream); - when(dataStream.map(any())).thenReturn(dataStream); - - method.invoke(sideSqlExec, joinInfo, localTableCache, sideTableMap, tableEnv); + @Test + public void testParseSql2() throws Exception { + String sql = "CREATE TABLE MyTable(\n" + + " name varchar,\n" + + " channel varchar\n" + + " )WITH(\n" + + " type ='kafka10',\n" + + " bootstrapServers ='172.21.32.1:9092',\n" + + " zookeeperQuorum ='172.21.32.1:2181/kafka',\n" + + " offsetReset ='earliest',\n" + + " topic ='test1',\n" + + " parallelism ='3'\n" + + " );\n" + + " \n" + + " CREATE TABLE MyResult(\n" + + " name varchar,\n" + + " channel varchar\n" + + " )WITH(\n" + + " type ='mysql',\n" + + " url ='jdbc:mysql://127.0.0.1:3306/test?charset=utf8&useSSL=false',\n" + + " userName ='root',\n" + + " password ='123456',\n" + + " tableName ='pv',\n" + + " parallelism ='3'\n" + + " );\n" + + " \n" + + "insert into MyResult\n" + + "select a.name,a.channel from MyTable a"; + test2(sql); } - // @Test - public void projectedTypeInfo() throws Exception { - Method method = SideSqlExec.class.getDeclaredMethod("projectedTypeInfo", int[].class, TableSchema.class); - method.setAccessible(true); - TableSchema schema = mock(TableSchema.class); - when(schema.getFieldNames()).thenReturn(new String[]{"a"}); - when(schema.getFieldTypes()).thenReturn(new TypeInformation[]{Types.STRING}); - method.invoke(sideSqlExec, new int[]{0}, schema); + @Test + public void testParseMongo() throws Exception { + String sql = "CREATE TABLE MyTable(\n" + + " name varchar,\n" + + " channel varchar\n" + + " )WITH(\n" + + " type ='kafka10',\n" + + " bootstrapServers ='172.21.32.1:9092',\n" + + " zookeeperQuorum ='172.21.32.1:2181/kafka',\n" + + " offsetReset ='earliest',\n" + + " topic ='test',\n" + + " parallelism ='3'\n" + + " );\n" + + " \n" + + " CREATE TABLE MyResult(\n" + + " name varchar,\n" + + " channel varchar,\n" + + "\txccount int\n" + + " )WITH(\n" + + " type ='mongo',\n" + + " address ='172.21.32.1:27017,172.21.32.1:27017',\n" + + " database ='test',\n" + + " tableName ='pv',\n" + + " parallelism ='3'\n" + + " );\n" + + " \n" + + "create table sideTable(\n" + + " channel varchar,\n" + + " xccount int,\n" + + " PRIMARY KEY(channel),\n" + + " PERIOD FOR SYSTEM_TIME\n" + + " )WITH(\n" + + " type='mysql',\n" + + " url='jdbc:mysql://127.0.0.1:3306/test?charset=utf8&useSSL=true',\n" + + " userName='root',\n" + + " password='123456',\n" + + " tableName='sidetest',\n" + + " cache ='NONE',\n" + + " cacheSize ='10000',\n" + + " cacheTTLMs ='60000',\n" + + " parallelism ='1',\n" + + " partitionedJoin='false'\n" + + " );\n" + + " \n" + + "\n" + + "insert into MyResult\n" + + "select a.name,a.channel,b.xccount\n" + + "from MyTable a join sideTable b\n" + + "on a.channel=b.channel;\n"; + test2(sql); } @Test - public void checkFieldsInfo() throws Exception { - Method method = SideSqlExec.class.getDeclaredMethod("checkFieldsInfo", CreateTmpTableParser.SqlParserResult.class, Table.class); - method.setAccessible(true); - CreateTmpTableParser.SqlParserResult result = mock(CreateTmpTableParser.SqlParserResult.class); - when(result.getFieldsInfoStr()).thenReturn("a varchar"); - - Table table = mock(Table.class); - TableSchema schema = mock(TableSchema.class); - when(table.getSchema()).thenReturn(schema); - when(schema.getFieldType(anyInt())).thenReturn(Optional.of(Types.STRING)); + public void testParseMongo2() throws Exception { + String sql = "CREATE TABLE MyTable(\n" + + " name varchar,\n" + + " channel varchar\n" + + " )WITH(\n" + + " type ='kafka10',\n" + + " bootstrapServers ='172.21.32.1:9092',\n" + + " zookeeperQuorum ='172.21.32.1:2181/kafka',\n" + + " offsetReset ='earliest',\n" + + " topic ='test1',\n" + + " parallelism ='3'\n" + + " );\n" + + " \n" + + " CREATE TABLE MyResult(\n" + + " name varchar,\n" + + " channel varchar,\n" + + "\txccount int\n" + + " )WITH(\n" + + " type ='mongo',\n" + + " address ='172.21.32.1:27017,172.21.32.1:27017',\n" + + " database ='test',\n" + + " tableName ='pv',\n" + + " parallelism ='3'\n" + + " );\n" + + " \n" + + "create table sideTable(\n" + + " CHANNEL varchar,\n" + + " XCCOUNT int,\n" + + " PRIMARY KEY(channel),\n" + + " PERIOD FOR SYSTEM_TIME\n" + + " )WITH(\n" + + " type ='mongo',\n" + + " address ='172.21.32.1:27017,172.21.32.1:27017',\n" + + " database ='test',\n" + + " tableName ='sidetest',\n" + + " cache ='ALL',\n" + + " parallelism ='1',\n" + + " partitionedJoin='false'\n" + + " );\n" + + " \n" + + "insert into MyResult\n" + + "select a.name,a.channel,b.xccount\n" + + "from MyTable a join sideTable b\n" + + "on a.channel=b.channel;\n"; + test2(sql); + } - method.invoke(sideSqlExec, result, table); + public void test2(String sql) throws Exception { + List paramList = Lists.newArrayList(); + paramList.add("-sql"); + String exeSql = URLEncoder.encode(sql, Charsets.UTF_8.name()); + paramList.add(exeSql); + paramList.add("-name"); + paramList.add("xc"); + paramList.add("-localSqlPluginPath"); + paramList.add("D:\\soucecode\\flinkStreamSQL-my-src\\plugins"); + paramList.add("-mode"); + paramList.add("local"); + paramList.add("-confProp"); + String conf = "{\"time.characteristic\":\"ProcessingTime\",\"sql.checkpoint.interval\":10000}"; + String confEncode = URLEncoder.encode(conf, Charsets.UTF_8.name()); + paramList.add(confEncode); + + String[] params = new String[paramList.size()]; + paramList.toArray(params); + Main.main(params); } } diff --git a/core/src/test/java/com/dtstack/flink/sql/side/StreamSideFactoryTest.java b/core/src/test/java/com/dtstack/flink/sql/side/StreamSideFactoryTest.java deleted file mode 100644 index d9b2edc49..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/side/StreamSideFactoryTest.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.dtstack.flink.sql.side; - -import com.dtstack.flink.sql.classloader.ClassLoaderManager; -import com.dtstack.flink.sql.table.AbstractTableParser; -import com.dtstack.flink.sql.util.PluginUtil; -import org.apache.flink.streaming.api.datastream.AsyncDataStream; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -import static org.mockito.ArgumentMatchers.anyObject; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -@RunWith(PowerMockRunner.class) -@PrepareForTest({PluginUtil.class, ClassLoaderManager.class, AsyncDataStream.class}) -public class StreamSideFactoryTest { - - @Test - public void getSqlParser() throws Exception { - - PowerMockito.mockStatic(PluginUtil.class); - when(PluginUtil.getJarFileDirPath(anyString(), anyString(), anyString())).thenReturn("/"); - when(PluginUtil.getSqlSideClassName(anyString(), anyString(), anyString())).thenReturn("clazz"); - - PowerMockito.mockStatic(ClassLoaderManager.class); - AbstractTableParser tableParser = mock(AbstractTableParser.class); - when(ClassLoaderManager.newInstance(anyString(), anyObject())).thenReturn(tableParser); - StreamSideFactory.getSqlParser("kafka", "/", "all", ""); - } -} diff --git a/core/src/test/java/com/dtstack/flink/sql/side/TestSideSqlParser.java b/core/src/test/java/com/dtstack/flink/sql/side/TestSideSqlParser.java new file mode 100644 index 000000000..18a7d2d86 --- /dev/null +++ b/core/src/test/java/com/dtstack/flink/sql/side/TestSideSqlParser.java @@ -0,0 +1,59 @@ +/* + * 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 com.dtstack.flink.sql.side; + +import org.apache.calcite.sql.parser.SqlParseException; +import com.google.common.collect.Sets; +import org.junit.Test; + +import java.util.Set; + +/** + * Reason: + * Date: 2018/7/24 + * Company: www.dtstack.com + * @author xuchao + */ + +public class TestSideSqlParser { + + @Test + public void testSideSqlParser() throws SqlParseException { + String sql = "select j1.id,j2.name,j1.info \n" + + " from\n" + + " (\n" + + " \tselect a.id,a.name,b.id \n" + + " \t\tfrom tab1 a join tab2 b\n" + + " \t\ton a.id = b.id and a.proctime between b.proctime - interval '4' second and b.proctime + interval '4' second \n" + + " ) j1\n" + + " join tab3 j2\n" + + " on j1.id = j2.id \n" + + " where j1.info like 'xc2'"; + + Set sideTbList = Sets.newHashSet("TAB3", "TAB4"); + + + SideSQLParser sideSQLParser = new SideSQLParser(); + sideSQLParser.getExeQueue(sql, sideTbList); + } + + +} diff --git a/core/src/test/java/com/dtstack/flink/sql/side/cache/LruSideCacheTest.java b/core/src/test/java/com/dtstack/flink/sql/side/cache/LruSideCacheTest.java deleted file mode 100644 index ed431b053..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/side/cache/LruSideCacheTest.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.dtstack.flink.sql.side.cache; - -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import org.junit.Before; -import org.junit.Test; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class LruSideCacheTest { - private LRUSideCache lruSideCache ; - - @Before - public void before(){ - AbstractSideTableInfo sideTableInfo = mock(AbstractSideTableInfo.class); - when(sideTableInfo.getCacheSize()).thenReturn(10); - when(sideTableInfo.getCacheTimeout()).thenReturn(1000000L); - - lruSideCache = new LRUSideCache(sideTableInfo); - lruSideCache.initCache(); - } - - - @Test - public void getFromCache(){ - lruSideCache.getFromCache("test"); - - } - - @Test - public void putCache(){ - lruSideCache.putCache("test", CacheObj.buildCacheObj(null, null)); - } -} diff --git a/core/src/test/java/com/dtstack/flink/sql/side/operator/SideAsyncOperatorTest.java b/core/src/test/java/com/dtstack/flink/sql/side/operator/SideAsyncOperatorTest.java deleted file mode 100644 index c302b1ba5..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/side/operator/SideAsyncOperatorTest.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.dtstack.flink.sql.side.operator; - -import com.dtstack.flink.sql.classloader.ClassLoaderManager; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.BaseAsyncReqRow; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.util.PluginUtil; -import com.google.common.collect.Lists; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.streaming.api.datastream.AsyncDataStream; -import org.apache.flink.streaming.api.datastream.DataStream; -import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -import java.util.List; - -import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.anyLong; -import static org.mockito.Mockito.anyObject; -import static org.mockito.Mockito.anyString; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -@RunWith(PowerMockRunner.class) -@PrepareForTest({PluginUtil.class, ClassLoaderManager.class, AsyncDataStream.class}) -public class SideAsyncOperatorTest { - - @Test - public void getSideJoinDataStream() throws Exception { - DataStream inputStream = mock(DataStream.class); - String sideType = "redis"; - String sqlRootDir = "/"; - RowTypeInfo rowTypeInfo = mock(RowTypeInfo.class); - JoinInfo joinInfo = mock(JoinInfo.class); - - List outFieldInfoList = Lists.newArrayList(); - AbstractSideTableInfo sideTableInfo = mock(AbstractSideTableInfo.class); - when(sideTableInfo.getParallelism()).thenReturn(1); - - PowerMockito.mockStatic(PluginUtil.class); - when(PluginUtil.getJarFileDirPath(anyString(), anyString(),anyString())).thenReturn("/"); - - PowerMockito.mockStatic(ClassLoaderManager.class); - BaseAsyncReqRow baseAsyncReqRow = mock(BaseAsyncReqRow.class); - when(ClassLoaderManager.newInstance(anyString(), anyObject())).thenReturn(baseAsyncReqRow); - - SingleOutputStreamOperator dataStream = mock(SingleOutputStreamOperator.class); - PowerMockito.mockStatic(AsyncDataStream.class); - when(AsyncDataStream.unorderedWait(anyObject(), anyObject(), anyLong(), anyObject(), anyInt())).thenReturn(dataStream); - when(AsyncDataStream.orderedWait(anyObject(), anyObject(), anyLong(), anyObject(), anyInt())).thenReturn(dataStream); - - SideAsyncOperator.getSideJoinDataStream(inputStream, sideType, sqlRootDir, rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo, ""); - - when(sideTableInfo.getCacheMode()).thenReturn("ORDERED"); - SideAsyncOperator.getSideJoinDataStream(inputStream, sideType, sqlRootDir, rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo, ""); - - - - - } - -} diff --git a/core/src/test/java/com/dtstack/flink/sql/side/operator/SideWithAllCacheOperatorTest.java b/core/src/test/java/com/dtstack/flink/sql/side/operator/SideWithAllCacheOperatorTest.java deleted file mode 100644 index cf1133495..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/side/operator/SideWithAllCacheOperatorTest.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.dtstack.flink.sql.side.operator; - -import com.dtstack.flink.sql.classloader.ClassLoaderManager; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.BaseAllReqRow; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.util.PluginUtil; -import com.google.common.collect.Lists; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.streaming.api.datastream.AsyncDataStream; -import org.apache.flink.streaming.api.datastream.DataStream; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -import java.util.List; - -import static org.mockito.ArgumentMatchers.anyObject; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - - -//@RunWith(PowerMockRunner.class) -//@PrepareForTest({PluginUtil.class, ClassLoaderManager.class, AsyncDataStream.class}) -public class SideWithAllCacheOperatorTest { - - // @Test - public void getSideJoinDataStream() throws Exception { - DataStream inputStream = mock(DataStream.class); - String sideType = "redis"; - String sqlRootDir = "/"; - RowTypeInfo rowTypeInfo = mock(RowTypeInfo.class); - JoinInfo joinInfo = mock(JoinInfo.class); - List outFieldInfoList = Lists.newArrayList(); - AbstractSideTableInfo sideTableInfo = mock(AbstractSideTableInfo.class); - - - PowerMockito.mockStatic(PluginUtil.class); - when(PluginUtil.getJarFileDirPath(anyString(), anyString(), anyString())).thenReturn("/"); - when(PluginUtil.getSqlSideClassName(anyString(), anyString(), anyString())).thenReturn("clazz"); - - PowerMockito.mockStatic(ClassLoaderManager.class); - BaseAllReqRow baseAllReqRow = mock(BaseAllReqRow.class); - when(ClassLoaderManager.newInstance(anyString(), anyObject())).thenReturn(baseAllReqRow); - - SideWithAllCacheOperator.getSideJoinDataStream(inputStream, sideType, sqlRootDir, rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo, ""); - } - - -} diff --git a/core/src/test/java/com/dtstack/flink/sql/sink/StreamSinkFactoryTest.java b/core/src/test/java/com/dtstack/flink/sql/sink/StreamSinkFactoryTest.java deleted file mode 100644 index 3258b2087..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/sink/StreamSinkFactoryTest.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.dtstack.flink.sql.sink; - -import com.dtstack.flink.sql.table.AbstractTargetTableInfo; -import com.dtstack.flink.sql.util.DtStringUtil; -import com.dtstack.flink.sql.util.PluginUtil; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -import java.net.URL; - -import static org.mockito.Mockito.anyString; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -@RunWith(PowerMockRunner.class) -@PrepareForTest({StreamSinkFactory.class, PluginUtil.class, DtStringUtil.class}) -public class StreamSinkFactoryTest { - - @Test(expected = Exception.class) - public void testGetSqlParser() throws Exception { - PowerMockito.mockStatic(PluginUtil.class); - when(PluginUtil.getJarFileDirPath(anyString(), anyString(),anyString())).thenReturn("./test.jar"); - - PowerMockito.mockStatic(DtStringUtil.class); - when(DtStringUtil.getPluginTypeWithoutVersion(anyString())).thenReturn("10"); - - when(PluginUtil.getSqlParserClassName(anyString(), anyString())).thenReturn("test"); - - StreamSinkFactory.getSqlParser("source", "./test.jar", ""); - } - - @Test(expected = Exception.class) - public void testGetTableSink() throws Exception { - AbstractTargetTableInfo targetTableInfo = mock(AbstractTargetTableInfo.class); - PowerMockito.mockStatic(PluginUtil.class); - when(PluginUtil.getJarFileDirPath(anyString(), anyString(), anyString())).thenReturn("./test.jar"); - - PowerMockito.mockStatic(DtStringUtil.class); - when(DtStringUtil.getPluginTypeWithoutVersion(anyString())).thenReturn("10"); - - when(PluginUtil.getGenerClassName(anyString(), anyString())).thenReturn("test"); - - when(PluginUtil.getPluginJarUrls(anyString())).thenReturn(new URL[1]); - - StreamSinkFactory.getTableSink(targetTableInfo, "./test.jar", ""); - } - -} diff --git a/core/src/test/java/com/dtstack/flink/sql/source/StreamSourceFactoryTest.java b/core/src/test/java/com/dtstack/flink/sql/source/StreamSourceFactoryTest.java deleted file mode 100644 index 13b5b71fb..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/source/StreamSourceFactoryTest.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.dtstack.flink.sql.source; - -import com.dtstack.flink.sql.table.AbstractSourceTableInfo; -import com.dtstack.flink.sql.util.DtStringUtil; -import com.dtstack.flink.sql.util.PluginUtil; -import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; -import org.apache.flink.table.api.java.StreamTableEnvironment; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -import java.net.URL; - -import static org.mockito.Mockito.anyString; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -@RunWith(PowerMockRunner.class) -@PrepareForTest({StreamSourceFactory.class, PluginUtil.class, DtStringUtil.class}) -public class StreamSourceFactoryTest { - - @Test(expected = Exception.class) - public void testGetSqlParser() throws Exception { - PowerMockito.mockStatic(PluginUtil.class); - when(PluginUtil.getJarFileDirPath(anyString(), anyString(), anyString())).thenReturn("./test.jar"); - - PowerMockito.mockStatic(DtStringUtil.class); - when(DtStringUtil.getPluginTypeWithoutVersion(anyString())).thenReturn("10"); - - when(PluginUtil.getSqlParserClassName(anyString(), anyString())).thenReturn("test"); - - StreamSourceFactory.getSqlParser("source", "./test.jar", ""); - } - - @Test(expected = Exception.class) - public void testGetTableSink() throws Exception { - AbstractSourceTableInfo sourceTableInfo = mock(AbstractSourceTableInfo.class); - PowerMockito.mockStatic(PluginUtil.class); - when(PluginUtil.getJarFileDirPath(anyString(), anyString(), anyString())).thenReturn("./test.jar"); - - PowerMockito.mockStatic(DtStringUtil.class); - when(DtStringUtil.getPluginTypeWithoutVersion(anyString())).thenReturn("10"); - - when(PluginUtil.getGenerClassName(anyString(), anyString())).thenReturn("test"); - - when(PluginUtil.getPluginJarUrls(anyString())).thenReturn(new URL[1]); - - StreamExecutionEnvironment env = mock(StreamExecutionEnvironment.class); - StreamTableEnvironment tableEnv = mock(StreamTableEnvironment.class); - - StreamSourceFactory.getStreamSource(sourceTableInfo, env, tableEnv, "./test.jar", ""); - } - -} diff --git a/core/src/test/java/com/dtstack/flink/sql/table/AbstractSideTableParserTest.java b/core/src/test/java/com/dtstack/flink/sql/table/AbstractSideTableParserTest.java deleted file mode 100644 index 3c9907eed..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/table/AbstractSideTableParserTest.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.dtstack.flink.sql.table; - -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.google.common.collect.Maps; -import org.junit.Test; -import org.mockito.Mockito; - -import java.util.Map; - -public class AbstractSideTableParserTest { - - @Test - public void testarseCacheProp(){ - AbstractSideTableParser sideTableParserTest = new AbstractSideTableParser() { - @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) throws Exception { - return null; - } - }; - AbstractSideTableInfo sideTableInfo = Mockito.mock(AbstractSideTableInfo.class); - Map props = Maps.newHashMap(); - props.put(AbstractSideTableInfo.CACHE_KEY.toLowerCase(), "all"); - props.put(AbstractSideTableInfo.CACHE_SIZE_KEY.toLowerCase(), 1000); - props.put(AbstractSideTableInfo.CACHE_TTLMS_KEY.toLowerCase(), 10000); - props.put(AbstractSideTableInfo.PARTITIONED_JOIN_KEY.toLowerCase(), false); - props.put(AbstractSideTableInfo.CACHE_MODE_KEY.toLowerCase(), "ordered"); - props.put(AbstractSideTableInfo.ASYNC_CAP_KEY.toLowerCase(), 100); - props.put(AbstractSideTableInfo.ASYNC_TIMEOUT_KEY.toLowerCase(), 1000); - props.put(AbstractSideTableInfo.ASYNC_FAIL_MAX_NUM_KEY.toLowerCase(), 12); - props.put(AbstractSideTableInfo.CONNECT_RETRY_MAX_NUM_KEY.toLowerCase(),3); - sideTableParserTest.parseCacheProp(sideTableInfo, props); - } - - -} diff --git a/core/src/test/java/com/dtstack/flink/sql/table/AbstractSourceParserTest.java b/core/src/test/java/com/dtstack/flink/sql/table/AbstractSourceParserTest.java deleted file mode 100644 index 4ed7a3d65..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/table/AbstractSourceParserTest.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.dtstack.flink.sql.table; - -import org.junit.Test; - -public class AbstractSourceParserTest { - - @Test - public void dealVirtualField(){ - - } -} diff --git a/core/src/test/java/com/dtstack/flink/sql/table/RdbParserTestBase.java b/core/src/test/java/com/dtstack/flink/sql/table/RdbParserTestBase.java deleted file mode 100644 index b030c4325..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/table/RdbParserTestBase.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.dtstack.flink.sql.table; - -import org.junit.Before; - -/** - * @program: flinkStreamSQL - * @author: wuren - * @create: 2020/11/09 - **/ -abstract public class RdbParserTestBase { - - protected AbstractTableParser parser; - protected String type; - - @Before - abstract public void setUp(); - -} diff --git a/core/src/test/java/com/dtstack/flink/sql/util/ByteUtilsTest.java b/core/src/test/java/com/dtstack/flink/sql/util/ByteUtilsTest.java deleted file mode 100644 index 31f700605..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/util/ByteUtilsTest.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.dtstack.flink.sql.util; - -import org.junit.Assert; -import org.junit.Test; - -public class ByteUtilsTest { - - @Test - public void testToBoolean(){ - byte[] content = new byte[1]; - content[0] = 1; - Assert.assertEquals(ByteUtils.toBoolean(content), true); - } - - @Test - public void testToString(){ - byte[] content = "test".getBytes(); - Assert.assertEquals(ByteUtils.byteToString(content), "test"); - } - - @Test - public void testToShort4(){ - short content = 3; - ByteUtils.shortToByte4(content); - } - - @Test - public void testByteToShort(){ - byte[] content = ByteUtils.shortToByte4((short)1); - Assert.assertEquals(ByteUtils.byte2ToShort(content), new Short((short)1)); - } - - @Test - public void testIntToByte(){ - ByteUtils.int2Bytes(2); - } - - @Test - public void testByteToInt(){ - byte[] content = ByteUtils.int2Bytes(2); - Assert.assertEquals(ByteUtils.byte4ToInt(content), 2); - } - - @Test - public void testLong2Byte(){ - ByteUtils.long2Bytes(2L); - } - - @Test - public void testBytes2Long(){ - byte[] content = ByteUtils.long2Bytes(2l); - Assert.assertEquals(ByteUtils.bytes2Long(content), 2l); - } - - @Test - public void testBytes2Byte(){ - byte[] content = ByteUtils.long2Bytes(2l); - ByteUtils.bytes2Byte(content); - } - - @Test - public void testFloat2Array(){ - byte[] content = ByteUtils.float2ByteArray(2); - } - @Test - public void testByte2Float(){ - byte[] content = ByteUtils.float2ByteArray(2); - ByteUtils.bytes2Float(content); - } - @Test - public void testDouble2Byte(){ - byte[] content = ByteUtils.double2Bytes(2); - } - @Test - public void testByte2Double(){ - byte[] content = ByteUtils.double2Bytes(2); - ByteUtils.bytes2Double(content); - } -} diff --git a/core/src/test/java/com/dtstack/flink/sql/util/ClassUtilTest.java b/core/src/test/java/com/dtstack/flink/sql/util/ClassUtilTest.java deleted file mode 100644 index 8e1e7c663..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/util/ClassUtilTest.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.dtstack.flink.sql.util; - -import org.junit.Assert; -import org.junit.Test; - -import java.math.BigDecimal; -import java.sql.Date; -import java.sql.Time; -import java.sql.Timestamp; - -public class ClassUtilTest { - - @Test - public void testStringConvertClass(){ - Assert.assertEquals(ClassUtil.stringConvertClass("bit"), Boolean.class); - Assert.assertEquals(ClassUtil.stringConvertClass("int"), Integer.class); - Assert.assertEquals(ClassUtil.stringConvertClass("blob"), Byte.class); - Assert.assertEquals(ClassUtil.stringConvertClass("bigintunsigned"), Long.class); - Assert.assertEquals(ClassUtil.stringConvertClass("text"), String.class); - Assert.assertEquals(ClassUtil.stringConvertClass("floatunsigned"), Float.class); - Assert.assertEquals(ClassUtil.stringConvertClass("doubleunsigned"), Double.class); - Assert.assertEquals(ClassUtil.stringConvertClass("date"), Date.class); - Assert.assertEquals(ClassUtil.stringConvertClass("timestamp"), Timestamp.class); - Assert.assertEquals(ClassUtil.stringConvertClass("time"), Time.class); - Assert.assertEquals(ClassUtil.stringConvertClass("decimalunsigned"), BigDecimal.class); - try { - ClassUtil.stringConvertClass("other"); - } catch (Exception e) { - - } - } - - @Test - public void testConvertType(){ - ClassUtil.convertType(1, "other", "tinyint"); - ClassUtil.convertType(1, "other", "smallint"); - ClassUtil.convertType(1, "other", "int"); - ClassUtil.convertType(1, "other", "bigint"); - ClassUtil.convertType(1, "other", "float"); - ClassUtil.convertType(1, "other", "double"); - ClassUtil.convertType("1", "other", "string"); - Date date = new Date(new java.util.Date().getTime()); - ClassUtil.convertType(date, "other", "date"); - ClassUtil.convertType(date.getTime(), "other", "timestamp"); - try { - ClassUtil.convertType(1, "other", "sd"); - } catch (Exception e) { - - } - } - - @Test - public void testGetTypeFromClass(){ - Assert.assertEquals(ClassUtil.getTypeFromClass(Byte.class), "TINYINT"); - Assert.assertEquals(ClassUtil.getTypeFromClass(Short.class), "SMALLINT"); - Assert.assertEquals(ClassUtil.getTypeFromClass(Integer.class), "INT"); - Assert.assertEquals(ClassUtil.getTypeFromClass(Long.class), "BIGINT"); - Assert.assertEquals(ClassUtil.getTypeFromClass(String.class), "STRING"); - Assert.assertEquals(ClassUtil.getTypeFromClass(Float.class), "FLOAT"); - Assert.assertEquals(ClassUtil.getTypeFromClass(Double.class), "DOUBLE"); - Assert.assertEquals(ClassUtil.getTypeFromClass(Date.class), "DATE"); - Assert.assertEquals(ClassUtil.getTypeFromClass(Timestamp.class), "TIMESTAMP"); - Assert.assertEquals(ClassUtil.getTypeFromClass(Boolean.class), "BOOLEAN"); - try { - ClassUtil.getTypeFromClass(Object.class); - } catch (Exception e){ - - } - } - @Test - public void testGetTypeFromClassName(){ - Assert.assertEquals(ClassUtil.getTypeFromClassName(Byte.class.getName()), "TINYINT"); - Assert.assertEquals(ClassUtil.getTypeFromClassName(Short.class.getName()), "SMALLINT"); - Assert.assertEquals(ClassUtil.getTypeFromClassName(Integer.class.getName()), "INT"); - Assert.assertEquals(ClassUtil.getTypeFromClassName(Long.class.getName()), "BIGINT"); - Assert.assertEquals(ClassUtil.getTypeFromClassName(String.class.getName()), "STRING"); - Assert.assertEquals(ClassUtil.getTypeFromClassName(Float.class.getName()), "FLOAT"); - Assert.assertEquals(ClassUtil.getTypeFromClassName(Double.class.getName()), "DOUBLE"); - Assert.assertEquals(ClassUtil.getTypeFromClassName(Date.class.getName()), "DATE"); - Assert.assertEquals(ClassUtil.getTypeFromClassName(Timestamp.class.getName()), "TIMESTAMP"); - Assert.assertEquals(ClassUtil.getTypeFromClassName(Boolean.class.getName()), "BOOLEAN"); - try { - ClassUtil.getTypeFromClassName(Object.class.getName()); - } catch (Exception e){ - - } - } -} diff --git a/core/src/test/java/com/dtstack/flink/sql/util/DataTypeUtilsTest.java b/core/src/test/java/com/dtstack/flink/sql/util/DataTypeUtilsTest.java deleted file mode 100644 index b045aaa28..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/util/DataTypeUtilsTest.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.dtstack.flink.sql.util; - -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.table.api.Types; -import org.junit.Assert; -import org.junit.Test; - -public class DataTypeUtilsTest { - - @Test - public void convertToArray() { - String[] normalFieldNames = new String[] { "id", "name" }; - TypeInformation[] normalTypes = new TypeInformation[] {Types.INT(), Types.STRING()}; - RowTypeInfo rowTypeInfo = new RowTypeInfo(normalTypes, normalFieldNames); - TypeInformation normalAtomicType = Types.OBJECT_ARRAY(Types.STRING()); - TypeInformation normalCompositeType = Types.OBJECT_ARRAY(rowTypeInfo); - - String atomicStrWithBlank = " ARRAY< STRING\n > "; - String compositeTypeStrWithBlank = " ARRAY< ROW< id INT, name STRING > > "; - - TypeInformation atomicArrayTypeWithBlank = DataTypeUtils.convertToArray(atomicStrWithBlank); - TypeInformation compositeTypeArrayTypeWithBlank = DataTypeUtils.convertToArray(compositeTypeStrWithBlank); - - Assert.assertTrue(normalAtomicType.equals(atomicArrayTypeWithBlank)); - Assert.assertTrue(normalCompositeType.equals(compositeTypeArrayTypeWithBlank)); - - - String atomicStr = "ARRAY"; - String compositeTypeStr = "ARRAY>"; - - TypeInformation atomicArrayType = DataTypeUtils.convertToArray(atomicStr); - TypeInformation compositeTypeArrayType = DataTypeUtils.convertToArray(compositeTypeStr); - - Assert.assertTrue(normalAtomicType.equals(atomicArrayType)); - Assert.assertTrue(normalCompositeType.equals(compositeTypeArrayType)); - } - - @Test - public void convertToRow() { - String string = " ROW < id INT, name STRING > "; - RowTypeInfo rowType = DataTypeUtils.convertToRow(string); - - String[] fieldNames = rowType.getFieldNames(); - Assert.assertTrue("id".equals(fieldNames[0])); - Assert.assertTrue("name".equals(fieldNames[1])); - - TypeInformation[] fieldTypes = rowType.getFieldTypes(); - Assert.assertTrue(Types.INT() == fieldTypes[0]); - Assert.assertTrue(Types.STRING() == fieldTypes[1]); - } - - @Test - public void convertToAtomicType() { - TypeInformation type = DataTypeUtils.convertToAtomicType(" TIMESTAMP "); - Assert.assertTrue(type == Types.SQL_TIMESTAMP()); - } -} \ No newline at end of file diff --git a/core/src/test/java/com/dtstack/flink/sql/util/DateUtilTest.java b/core/src/test/java/com/dtstack/flink/sql/util/DateUtilTest.java deleted file mode 100644 index e6a87ac9c..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/util/DateUtilTest.java +++ /dev/null @@ -1,250 +0,0 @@ -package com.dtstack.flink.sql.util; - -import org.junit.Test; - -import java.sql.Date; -import java.sql.Timestamp; -import java.text.ParseException; -import java.util.Calendar; -import java.util.Locale; - - -public class DateUtilTest { - - @Test - public void columnToDate(){ - DateUtil.columnToDate("2020-11-21 12:22:11"); - DateUtil.columnToDate(System.currentTimeMillis()); - try{ - DateUtil.columnToDate(1212121); - }catch (Exception e) { - - } - DateUtil.columnToDate(new Date(System.currentTimeMillis())); - DateUtil.columnToDate(new Timestamp(System.currentTimeMillis())); - - } - - @Test - public void stringToDate() { - DateUtil.stringToDate(null); - DateUtil.stringToDate("2010-01-11 11:32:11"); - DateUtil.stringToDate("2010-01-11"); - DateUtil.stringToDate("11:32:11"); - try{ - DateUtil.stringToDate("xxx:xxx:xx 11:32:11.4444"); - } catch (Exception e){ - - } - } - - @Test - public void getTodayStart(){ - DateUtil.getTodayStart(System.currentTimeMillis()); - } - - @Test - public void getTodayStartWithScop(){ - DateUtil.getTodayStart(System.currentTimeMillis()/1000, "MS"); - DateUtil.getTodayStart(System.currentTimeMillis(), "S"); - } - - @Test - public void getNextDayStart(){ - DateUtil.getNextDayStart(System.currentTimeMillis()); - } - - - @Test - public void getNextDayStartWithScop(){ - DateUtil.getNextDayStart(System.currentTimeMillis()/1000, "MS"); - DateUtil.getNextDayStart(System.currentTimeMillis(), "S"); - } - - - @Test - public void getMonthFirst(){ - DateUtil.getMonthFirst(System.currentTimeMillis()); - } - - @Test - public void getMonth(){ - DateUtil.getMonth(System.currentTimeMillis()); - } - - @Test - public void getYear(){ - DateUtil.getYear(System.currentTimeMillis()); - } - - @Test - public void getWeekFirst(){ - DateUtil.getWeekFirst(System.currentTimeMillis()); - } - @Test - public void getWeekOfYear(){ - DateUtil.getWeekOfYear(System.currentTimeMillis()); - } - @Test - public void getYesterdayByString(){ - DateUtil.getYesterdayByString("2010-10-11 10:22:31","yyyy-MM-dd HH:mm:ss","yyyy-MM-dd"); - } - @Test - public void getTomorrowByString() throws ParseException { - DateUtil.getTomorrowByString("2010-10-11 10:22:31","yyyy-MM-dd HH:mm:ss","yyyy-MM-dd"); - } - - - @Test - public void getTomorrowByDate() throws ParseException { - DateUtil.getTomorrowByDate(new java.util.Date()); - } - - @Test - public void get30DaysBeforeByString() throws ParseException { - DateUtil.get30DaysBeforeByString("2010-10-11 10:22:31","yyyy-MM-dd HH:mm:ss","yyyy-MM-dd"); - } - - @Test - public void get30DaysLaterByString() throws ParseException { - DateUtil.get30DaysLaterByString("2010-10-11 10:22:31","yyyy-MM-dd HH:mm:ss","yyyy-MM-dd"); - } - - @Test - public void getDateStrToFormat() throws ParseException { - DateUtil.getDateStrToFormat("2010-10-11 10:22:31","yyyy-MM-dd HH:mm:ss","yyyy-MM-dd"); - } - - @Test - public void getDateMillToFormat() throws ParseException { - DateUtil.getDateMillToFormat("2010-10-11 10:22:31","yyyy-MM-dd HH:mm:ss"); - } - - @Test - public void getFirstDay4Month(){ - DateUtil.getFirstDay4Month(2010, 3); - } - @Test - public void getLastDay4Month(){ - DateUtil.getLastDay4Month(2010, 3); - } - @Test - public void getBeforeMonthDay(){ - DateUtil.getBeforeMonthDay(System.currentTimeMillis(), true); - DateUtil.getBeforeMonthDay(System.currentTimeMillis(), false); - } - - @Test - public void getMillByOneDay(){ - DateUtil.getMillByOneDay(); - } - @Test - public void getMillByYesDay(){ - DateUtil.getMillByYesDay(); - } - @Test - public void getMillByLastWeekDay(){ - DateUtil.getMillByLastWeekDay(); - } - @Test - public void getMillByDay(){ - DateUtil.getMillByDay(); - DateUtil.getMillByDay(1, "-"); - DateUtil.getMillByDay(1, "+"); - } - - @Test - public void getStampByDay(){ - DateUtil.getStampByDay(1, "-"); - DateUtil.getStampByDay(1, "+"); - } - - @Test - public void getMillToDay(){ - DateUtil.getMillToDay(Calendar.getInstance(), 1); - } - @Test - public void getStampToDay(){ - DateUtil.getStampToDay(Calendar.getInstance(), 1); - } - @Test - public void getToday(){ - DateUtil.getToday(); - } - @Test - public void getDate(){ - DateUtil.getDate(System.currentTimeMillis(), "yyyy-MM-dd HH:mm:ss"); - DateUtil.getDate(new java.util.Date(), "yyyy-MM-dd HH:mm:ss"); - DateUtil.getDate(new java.util.Date(), "yyyy-MM-dd HH:mm:ss", Locale.getDefault()); - } - @Test - public void stringToLong() throws ParseException { - DateUtil.stringToLong("2010-11-11 12:22:22", "yyyy-MM-dd HH:mm:ss"); - } - @Test - public void stringToDateNew() { - DateUtil.stringToDate("2010-11-11 12:22:22", "yyyy-MM-dd HH:mm:ss"); - } - - @Test - public void longToString() throws ParseException { - DateUtil.longToString(System.currentTimeMillis()/1000, "yyyy-MM-dd HH:mm:ss"); - } - @Test - public void getMinusDate() { - DateUtil.getMinusDate(10, 1); - } - @Test - public void getMillByNow() { - DateUtil.getMillByNow(); - } - @Test - public void getWeeksBetweenTwoDates() { - DateUtil.getWeeksBetweenTwoDates(System.currentTimeMillis(), System.currentTimeMillis()); - } - @Test - public void getMonthsBetweenTwoDates() { - DateUtil.getMonthsBetweenTwoDates(System.currentTimeMillis(), System.currentTimeMillis()); - } - @Test - public void getMaxWeekOfYear() { - DateUtil.getMaxWeekOfYear(System.currentTimeMillis()); - } - @Test - public void parseDate() { - DateUtil.parseDate("2010-11-11 12:22:22", "yyyy-MM-dd HH:mm:ss"); - DateUtil.parseDate("2010-11-11 12:22:22", "yyyy-MM-dd HH:mm:ss", Locale.getDefault()); - } - @Test - public void getMinuteStart() { - DateUtil.getMinuteStart(System.currentTimeMillis()); - } - - @Test - public void getHourStart() { - DateUtil.getHourStart(System.currentTimeMillis()); - } - @Test - public void getDateByLong() { - DateUtil.getDateByLong(System.currentTimeMillis()); - } - @Test - public void dateToString() { - DateUtil.dateToString(new java.util.Date()); - } - - @Test - public void timestampToString() { - DateUtil.timestampToString(new java.util.Date()); - } - @Test - public void getTimestampFromStr() { - DateUtil.getTimestampFromStr("2010-02-11T12:22:12.111Z"); - } - @Test - public void getDateFromStr() { - DateUtil.getDateFromStr("2010-02-11 12:22:12"); - DateUtil.getDateFromStr("2010-02-11T12:22:12.111Z"); - } - -} diff --git a/core/src/test/java/com/dtstack/flink/sql/util/DtStringUtilTest.java b/core/src/test/java/com/dtstack/flink/sql/util/DtStringUtilTest.java deleted file mode 100644 index 9ae869b35..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/util/DtStringUtilTest.java +++ /dev/null @@ -1,101 +0,0 @@ -package com.dtstack.flink.sql.util; - -import com.google.common.collect.Maps; -import org.junit.Assert; -import org.junit.Test; - -import java.math.BigDecimal; -import java.sql.Timestamp; -import java.util.Date; -import java.util.Map; - -public class DtStringUtilTest { - - @Test - public void testSplitIgnoreQuota(){ - DtStringUtil.splitIgnoreQuota("(ss, aa)", ','); - } - - @Test - public void testReplaceIgnoreQuota(){ - String str = DtStringUtil.replaceIgnoreQuota("abcdfs", "s", "a"); - Assert.assertEquals(str, "abcdfa"); - - } - - @Test - public void testCol2string(){ - Assert.assertEquals(DtStringUtil.col2string(1, "TINYINT"), "1"); - Assert.assertEquals(DtStringUtil.col2string(1, "SMALLINT"), "1"); - Assert.assertEquals(DtStringUtil.col2string(1, "INT"), "1"); - Assert.assertEquals(DtStringUtil.col2string(1, "BIGINT"), "1"); - Assert.assertEquals(DtStringUtil.col2string(1, "FLOAT"), Float.valueOf(1).toString()); - Assert.assertEquals(DtStringUtil.col2string(1, "DOUBLE"), Double.valueOf(1).toString()); - Assert.assertEquals(DtStringUtil.col2string(1, "DECIMAL"), new BigDecimal(1).toString()); - Assert.assertEquals(DtStringUtil.col2string(1, "CHAR"), "1"); - Assert.assertEquals(DtStringUtil.col2string(true, "BOOLEAN"), Boolean.valueOf(true).toString()); - Assert.assertEquals(DtStringUtil.col2string(new Date(), "DATE"), DateUtil.dateToString(new Date())); - Assert.assertEquals(DtStringUtil.col2string(new Date(), "TIMESTAMP"), DateUtil.timestampToString(new Date())); - try { - Assert.assertEquals(DtStringUtil.col2string(1, "other"), "1"); - } catch (Exception e){ - - } - } - - @Test - public void testGetPluginTypeWithoutVersion(){ - Assert.assertEquals(DtStringUtil.getPluginTypeWithoutVersion("kafka10"), "kafka"); - } - - @Test - public void testAddJdbcParam(){ - try { - DtStringUtil.addJdbcParam(null, null, false); - }catch (Exception e){ - - } - DtStringUtil.addJdbcParam("ss", null, false); - Map addParams = Maps.newHashMap(); - addParams.put("aa", "bb"); - DtStringUtil.addJdbcParam("jdbc:mysql://172.16.8.104:3306/test?charset=utf8", addParams, false); - } - - @Test - public void testIsJson(){ - Assert.assertEquals(DtStringUtil.isJson("{}"), true); - try { - DtStringUtil.isJson(""); - }catch (Exception e){ - - } - } - - @Test - public void testParse(){ - Assert.assertEquals(DtStringUtil.parse("1", Integer.class), 1); - Assert.assertEquals(DtStringUtil.parse("1", Long.class), Long.valueOf(1)); - Assert.assertEquals(DtStringUtil.parse("1", Byte.class), "1".getBytes()[0]); - Assert.assertEquals(DtStringUtil.parse("1", String.class), "1"); - Assert.assertEquals(DtStringUtil.parse("1", Float.class), Float.valueOf(1)); - Assert.assertEquals(DtStringUtil.parse("1", Double.class), Double.valueOf(1)); - Assert.assertEquals(DtStringUtil.parse("2020-02-03 11:33:33", Timestamp.class), Timestamp.valueOf("2020-02-03 11:33:33")); - try { - Assert.assertEquals(DtStringUtil.parse("1", Object.class), 1); - } catch (Exception e){ - - } - } - - @Test - public void testFirstUpperCase(){ - Assert.assertEquals(DtStringUtil.firstUpperCase("abc"), "Abc");; - } - - @Test - public void testGetTableFullPath(){ - Assert.assertEquals(DtStringUtil.getTableFullPath("aa", "aa.roc"), "\"aa\".\"roc\""); - } - - -} diff --git a/core/src/test/java/com/dtstack/flink/sql/util/FieldReplaceUtilTest.java b/core/src/test/java/com/dtstack/flink/sql/util/FieldReplaceUtilTest.java deleted file mode 100644 index 80c74dc27..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/util/FieldReplaceUtilTest.java +++ /dev/null @@ -1,176 +0,0 @@ -package com.dtstack.flink.sql.util; - -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import org.apache.calcite.config.Lex; -import org.apache.calcite.sql.SqlBasicCall; -import org.apache.calcite.sql.SqlIdentifier; -import org.apache.calcite.sql.SqlKind; -import org.apache.calcite.sql.SqlNode; -import org.apache.calcite.sql.SqlNodeList; -import org.apache.calcite.sql.fun.SqlCase; -import org.apache.calcite.sql.parser.SqlParseException; -import org.apache.calcite.sql.parser.SqlParser; -import org.apache.flink.calcite.shaded.com.google.common.collect.ImmutableList; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.anyString; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -@RunWith(PowerMockRunner.class) -@PrepareForTest({SqlNode.class}) -public class FieldReplaceUtilTest { - - @Test - public void replaceFieldName() throws SqlParseException { - SqlParser.Config config = SqlParser.configBuilder() - .setLex(Lex.MYSQL) - .build(); - SqlParser sqlParser = SqlParser - .create("insert into resultTable select id from source s left join sideTable t on s.id = t.id union select id from source2 order by id", config); - SqlNode sqlNode = sqlParser.parseStmt(); - FieldReplaceUtil.replaceFieldName(sqlNode, "old", "new", Maps.newHashMap()); - } - - @Test - public void replaceOrderByTableName() throws Exception { - PowerMockito.spy(FieldReplaceUtil.class); - - SqlIdentifier sqlIdentifier = mock(SqlIdentifier.class); - when(sqlIdentifier.getKind()).thenReturn(SqlKind.IDENTIFIER); - sqlIdentifier.names = ImmutableList.copyOf(Arrays.asList("old", "a")); - Map mappingField = Maps.newHashMap(); - mappingField.put("a", "b"); - when(sqlIdentifier.setName(anyInt(), anyString())).thenReturn(sqlIdentifier); - PowerMockito.when(FieldReplaceUtil.class, "replaceOrderByTableName", sqlIdentifier, "old","new", mappingField).thenReturn(null); - - SqlBasicCall sqlBasicCall = mock(SqlBasicCall.class); - when(sqlBasicCall.getKind()).thenReturn(SqlKind.DEFAULT); - List sqlNodeList = Lists.newArrayList(sqlIdentifier); - when(sqlBasicCall.getOperandList()).thenReturn(sqlNodeList); - when(sqlBasicCall.getOperands()).thenReturn(new SqlNode[1]); - PowerMockito.when(FieldReplaceUtil.class, "replaceOrderByTableName", sqlBasicCall, "old","new", mappingField).thenReturn(null); - - SqlNode sqlNode = mock(SqlNode.class); - when(sqlNode.getKind()).thenReturn(SqlKind.DEFAULT); - PowerMockito.when(FieldReplaceUtil.class, "replaceOrderByTableName", sqlNode, "old","new", mappingField).thenReturn(null); - } - - - @Test - public void replaceNodeInfo() throws Exception { - PowerMockito.spy(FieldReplaceUtil.class); - - SqlIdentifier sqlIdentifier = mock(SqlIdentifier.class); - when(sqlIdentifier.getKind()).thenReturn(SqlKind.IDENTIFIER); - sqlIdentifier.names = ImmutableList.copyOf(Arrays.asList("old", "a")); - Map mappingField = Maps.newHashMap(); - mappingField.put("a", "b"); - when(sqlIdentifier.setName(anyInt(), anyString())).thenReturn(sqlIdentifier); - PowerMockito.when(FieldReplaceUtil.class, "replaceNodeInfo", sqlIdentifier, "old","new", mappingField).thenReturn(null); - - - SqlBasicCall sqlBasicCall = mock(SqlBasicCall.class); - when(sqlBasicCall.getKind()).thenReturn(SqlKind.DEFAULT); - List sqlNodes = Lists.newArrayList(sqlIdentifier); - when(sqlBasicCall.getOperandList()).thenReturn(sqlNodes); - when(sqlBasicCall.getOperands()).thenReturn(new SqlNode[1]); - PowerMockito.when(FieldReplaceUtil.class, "replaceNodeInfo", sqlBasicCall, "old","new", mappingField).thenReturn(null); - - SqlCase sqlCase = mock(SqlCase.class); - when(sqlCase.getKind()).thenReturn(SqlKind.CASE); - SqlNodeList sqlNodeList = mock(SqlNodeList.class); - when(sqlNodeList.getList()).thenReturn(sqlNodes); - when(sqlCase.getWhenOperands()).thenReturn(sqlNodeList); - when(sqlNodeList.size()).thenReturn(1); - - when(sqlCase.getThenOperands()).thenReturn(sqlNodeList); - - SqlNode sqlNode = mock(SqlNode.class); - when(sqlNode.getKind()).thenReturn(SqlKind.LITERAL); - when(sqlCase.getElseOperand()).thenReturn(sqlNode); - - try{ - PowerMockito.when(FieldReplaceUtil.class, "replaceNodeInfo", sqlCase, "old","new", mappingField).thenReturn(null); - }catch (Exception e){ - - } - - PowerMockito.when(FieldReplaceUtil.class, "replaceNodeInfo", sqlNode, "old","new", mappingField).thenReturn(null); - } - - @Test - public void createNewIdentify(){ - SqlIdentifier sqlIdentifier = mock(SqlIdentifier.class); - sqlIdentifier.names = ImmutableList.copyOf(Arrays.asList("old", "a")); - Map mappingField = Maps.newHashMap(); - mappingField.put("a", "b"); - when(sqlIdentifier.setName(anyInt(), anyString())).thenReturn(sqlIdentifier); - FieldReplaceUtil.createNewIdentify(sqlIdentifier, "old", "new", mappingField); - } - - @Test - public void replaceSelectFieldName() { - SqlIdentifier sqlIdentifier = mock(SqlIdentifier.class); - when(sqlIdentifier.getKind()).thenReturn(SqlKind.IDENTIFIER); - sqlIdentifier.names = ImmutableList.copyOf(Arrays.asList("old", "a")); - Map mappingField = Maps.newHashMap(); - mappingField.put("a", "b"); - when(sqlIdentifier.setName(anyInt(), anyString())).thenReturn(sqlIdentifier); - - SqlBasicCall sqlNode = mock(SqlBasicCall.class); - when(sqlNode.getKind()).thenReturn(SqlKind.AS); - - SqlNode[] sqlNodes = new SqlNode[1]; - sqlNodes[0] = sqlIdentifier; - when(sqlNode.getOperands()).thenReturn(sqlNodes); - FieldReplaceUtil.replaceSelectFieldName(sqlNode, "old", "new", mappingField); - - - SqlBasicCall sqlBasicCall = mock(SqlBasicCall.class); - when(sqlBasicCall.getOperands()).thenReturn(sqlNodes); - - - SqlCase sqlCase = mock(SqlCase.class); - when(sqlCase.getKind()).thenReturn(SqlKind.CASE); - SqlNodeList sqlNodeList = mock(SqlNodeList.class); - when(sqlNodeList.getList()).thenReturn(Lists.newArrayList(sqlIdentifier)); - when(sqlCase.getWhenOperands()).thenReturn(sqlNodeList); - when(sqlNodeList.get(anyInt())).thenReturn(sqlIdentifier); - when(sqlNodeList.size()).thenReturn(1); - - when(sqlCase.getThenOperands()).thenReturn(sqlNodeList); - - SqlNode sqlKindNode = mock(SqlNode.class); - when(sqlKindNode.getKind()).thenReturn(SqlKind.LITERAL); - when(sqlCase.getElseOperand()).thenReturn(sqlKindNode); - - FieldReplaceUtil.replaceSelectFieldName(sqlCase, "old", "new", mappingField); - - - - when(sqlNode.getKind()).thenReturn(SqlKind.LITERAL); - FieldReplaceUtil.replaceSelectFieldName(sqlNode, "old", "new", mappingField); - - when(sqlNode.getKind()).thenReturn(SqlKind.OTHER); - FieldReplaceUtil.replaceSelectFieldName(sqlNode, "old", "new", mappingField); - - try{ - when(sqlNode.getKind()).thenReturn(SqlKind.DEFAULT); - FieldReplaceUtil.replaceSelectFieldName(sqlNode, "old", "new", mappingField); - }catch (Exception e){ - - } - - } -} diff --git a/core/src/test/java/com/dtstack/flink/sql/util/MD5UtilTest.java b/core/src/test/java/com/dtstack/flink/sql/util/MD5UtilTest.java deleted file mode 100644 index 228338ff9..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/util/MD5UtilTest.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.dtstack.flink.sql.util; - -import org.junit.Assert; -import org.junit.Test; - -public class MD5UtilTest { - - @Test - public void testGetMD5String(){ - Assert.assertNotEquals(MD5Utils.getMD5String("aaaaa"), "d41d8cd98f00b204e9800998ecf8427e"); - } - -} diff --git a/core/src/test/java/com/dtstack/flink/sql/util/MathUtilTest.java b/core/src/test/java/com/dtstack/flink/sql/util/MathUtilTest.java deleted file mode 100644 index db51a3a3d..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/util/MathUtilTest.java +++ /dev/null @@ -1,182 +0,0 @@ -package com.dtstack.flink.sql.util; - -import org.junit.Assert; -import org.junit.Test; - -import java.math.BigDecimal; -import java.math.BigInteger; -import java.sql.Date; -import java.sql.Timestamp; - -public class MathUtilTest { - - @Test - public void testGetLongVal() { - Assert.assertEquals(MathUtil.getLongVal(null), null); - Assert.assertEquals(MathUtil.getLongVal("12"), Long.valueOf(12)); - Assert.assertEquals(MathUtil.getLongVal(12l), Long.valueOf(12)); - Assert.assertEquals(MathUtil.getLongVal(12), Long.valueOf(12)); - Assert.assertEquals(MathUtil.getLongVal(BigDecimal.valueOf(12)), Long.valueOf(12)); - Assert.assertEquals(MathUtil.getLongVal(BigInteger.valueOf(12)), Long.valueOf(12)); - try { - MathUtil.getLongVal(new Object()); - } catch (Exception e) { - - } - } - - @Test - public void testGetLongValWithDefault() { - Assert.assertEquals(MathUtil.getLongVal(null, 12l), Long.valueOf(12)); - } - - @Test - public void testGetIntegerVal() { - Assert.assertEquals(MathUtil.getIntegerVal(null), null); - Assert.assertEquals(MathUtil.getIntegerVal("12"), Integer.valueOf(12)); - Assert.assertEquals(MathUtil.getIntegerVal(12l), Integer.valueOf(12)); - Assert.assertEquals(MathUtil.getIntegerVal(12), Integer.valueOf(12)); - Assert.assertEquals(MathUtil.getIntegerVal(BigDecimal.valueOf(12)), Integer.valueOf(12)); - Assert.assertEquals(MathUtil.getIntegerVal(BigInteger.valueOf(12)), Integer.valueOf(12)); - try { - MathUtil.getIntegerVal(new Object()); - } catch (Exception e) { - - } - } - - @Test - public void testGetIntegerValWithDefault() { - Assert.assertEquals(MathUtil.getIntegerVal(null, 12), Integer.valueOf(12)); - } - - @Test - public void testGetFloatVal() { - Assert.assertEquals(MathUtil.getFloatVal(null), null); - Assert.assertEquals(MathUtil.getFloatVal("12"), Float.valueOf(12)); - Assert.assertEquals(MathUtil.getFloatVal(12.2f), Float.valueOf(12.2f)); - Assert.assertEquals(MathUtil.getFloatVal(BigDecimal.valueOf(12)), Float.valueOf(12)); - try { - MathUtil.getFloatVal(new Object()); - } catch (Exception e) { - - } - } - - @Test - public void testGetFloatValWithDefault() { - Assert.assertEquals(MathUtil.getFloatVal(null, 12.2f), Float.valueOf(12.2f)); - } - - @Test - public void testGetDoubleVal() { - Assert.assertEquals(MathUtil.getDoubleVal(null), null); - Assert.assertEquals(MathUtil.getDoubleVal("12"), Double.valueOf(12)); - Assert.assertEquals(MathUtil.getDoubleVal(12.3), Double.valueOf(12.3)); - Assert.assertEquals(MathUtil.getDoubleVal(12.2f), Double.valueOf(12.2f)); - Assert.assertEquals(MathUtil.getDoubleVal(BigDecimal.valueOf(12)), Double.valueOf(12)); - Assert.assertEquals(MathUtil.getDoubleVal(12), Double.valueOf(12)); - try { - MathUtil.getDoubleVal(new Object()); - } catch (Exception e) { - - } - } - - @Test - public void testGetDoubleValWithDefault() { - Assert.assertEquals(MathUtil.getDoubleVal(null, 12.2), Double.valueOf(12.2)); - } - - @Test - public void testGetBooleanVal() { - Assert.assertEquals(MathUtil.getBoolean(null), null); - Assert.assertEquals(MathUtil.getBoolean("true"), true); - Assert.assertEquals(MathUtil.getBoolean(true), true); - try { - MathUtil.getBoolean(new Object()); - } catch (Exception e) { - - } - } - - @Test - public void testGetBooleanValWithDefault() { - Assert.assertEquals(MathUtil.getBoolean(null, true), true); - } - - @Test - public void testGetStringVal() { - Assert.assertEquals(MathUtil.getString(null), null); - Assert.assertEquals(MathUtil.getString("true"), "true"); - Assert.assertEquals(MathUtil.getString(11), "11"); - - } - - @Test - public void testGetByteVal() { - Assert.assertEquals(MathUtil.getByte(null), null); - Assert.assertEquals(MathUtil.getByte("11"), Byte.valueOf("11")); - Assert.assertEquals(MathUtil.getByte(new Byte("11")), Byte.valueOf("11")); - try { - MathUtil.getByte(new Object()); - } catch (Exception e) { - - } - - } - - @Test - public void testGetShortVal() { - Assert.assertEquals(MathUtil.getShort(null), null); - Assert.assertEquals(MathUtil.getShort("11"), Short.valueOf("11")); - Assert.assertEquals(MathUtil.getShort(new Short((short) 11)), new Short((short) 11)); - try { - MathUtil.getShort(new Object()); - } catch (Exception e) { - - } - - } - - @Test - public void testGetDecimalVal() { - Assert.assertEquals(MathUtil.getBigDecimal(null), null); - Assert.assertEquals(MathUtil.getBigDecimal("11"), new BigDecimal("11")); - Assert.assertEquals(MathUtil.getBigDecimal(new BigDecimal("11")), new BigDecimal("11")); - Assert.assertEquals(MathUtil.getBigDecimal(new BigInteger("11")), new BigDecimal("11")); - try { - MathUtil.getBigDecimal(new Object()); - } catch (Exception e) { - - } - } - - @Test - public void testGetDateVal() { - Date now = DateUtil.getDateFromStr("2020-07-12"); - Assert.assertEquals(MathUtil.getDate(null), null); - Assert.assertEquals(MathUtil.getDate("2020-07-12"), now); - Assert.assertEquals(MathUtil.getDate(new Timestamp(now.getTime())), now); - Assert.assertEquals(MathUtil.getDate(now), now); - try { - MathUtil.getDate(new Object()); - } catch (Exception e) { - - } - } - @Test - public void testGetTimestampVal() { - Date now = DateUtil.getDateFromStr("2020-07-12"); - Assert.assertEquals(MathUtil.getTimestamp(null), null); - Assert.assertEquals(MathUtil.getTimestamp("2020-07-12"), new Timestamp(now.getTime())); - Assert.assertEquals(MathUtil.getTimestamp(new Timestamp(now.getTime())), new Timestamp(now.getTime())); - Assert.assertEquals(MathUtil.getTimestamp(now), new Timestamp(now.getTime())); - try { - MathUtil.getTimestamp(new Object()); - } catch (Exception e) { - - } - } - -} diff --git a/core/src/test/java/com/dtstack/flink/sql/util/ParseUtilTest.java b/core/src/test/java/com/dtstack/flink/sql/util/ParseUtilTest.java deleted file mode 100644 index d34a89c2d..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/util/ParseUtilTest.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.dtstack.flink.sql.util; - -import com.google.common.collect.HashBasedTable; -import com.google.common.collect.HashBiMap; -import com.google.common.collect.Lists; -import org.apache.calcite.sql.SqlBasicCall; -import org.apache.calcite.sql.SqlKind; -import org.apache.calcite.sql.SqlNode; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -@RunWith(PowerMockRunner.class) -@PrepareForTest({SqlKind.class}) -public class ParseUtilTest { - - - @Test - public void parseAnd(){ - SqlBasicCall sqlNode = mock(SqlBasicCall.class); - when(sqlNode.getKind()).thenReturn(SqlKind.AND); - - SqlBasicCall sqlBasicCall = mock(SqlBasicCall.class); - when(sqlBasicCall.getKind()).thenReturn(SqlKind.SELECT); - - List sqlNodeList = Lists.newArrayList(); - sqlNodeList.add(sqlBasicCall); - sqlNodeList.add(sqlBasicCall); - - when(sqlNode.getOperandList()).thenReturn(sqlNodeList); - when(sqlNode.getOperands()).thenReturn(sqlNodeList.toArray(new SqlNode[2])); - - ParseUtils.parseAnd(sqlNode, Lists.newArrayList()); - - } - - @Test - public void parseJoinCompareOperate(){ - SqlBasicCall sqlNode = mock(SqlBasicCall.class); - when(sqlNode.getKind()).thenReturn(SqlKind.AND); - - SqlBasicCall sqlBasicCall = mock(SqlBasicCall.class); - when(sqlBasicCall.getKind()).thenReturn(SqlKind.SELECT); - when(sqlBasicCall.toString()).thenReturn("s"); - - List sqlNodeList = Lists.newArrayList(); - sqlNodeList.add(sqlBasicCall); - - when(sqlNode.getOperandList()).thenReturn(sqlNodeList); - when(sqlNode.getOperands()).thenReturn(sqlNodeList.toArray(new SqlNode[2])); - ParseUtils.parseJoinCompareOperate(sqlNode, Lists.newArrayList()); - } - - @Test - public void transformNotEqualsOperator(){ - SqlKind sqlKind = mock(SqlKind.class); - when(sqlKind.toString()).thenReturn("NOT_EQUALS"); - ParseUtils.transformNotEqualsOperator(sqlKind); - } - - @Test - public void dealDuplicateFieldName(){ - HashBasedTable mappingTable = HashBasedTable.create(); - mappingTable.put("a", "b", "c"); - ParseUtils.dealDuplicateFieldName(mappingTable, "a"); - } - - - @Test - public void dealDuplicateFieldNameWithBi(){ - HashBiMap refFieldMap = HashBiMap.create(); - refFieldMap.put("a", "b"); - ParseUtils.dealDuplicateFieldName(refFieldMap, "a"); - } - @Test - public void dealDuplicateFieldNameWithHash(){ - Map refFieldMap = new HashMap(); - refFieldMap.put("a", "b"); - ParseUtils.dealDuplicateFieldName(refFieldMap, "a"); - } - - @Test - public void suffixWithChar(){ - ParseUtils.suffixWithChar("a", 'a', 1); - } - - - -} diff --git a/core/src/test/java/com/dtstack/flink/sql/util/PluginUtilTest.java b/core/src/test/java/com/dtstack/flink/sql/util/PluginUtilTest.java deleted file mode 100644 index 0fadb561d..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/util/PluginUtilTest.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.dtstack.flink.sql.util; - -import com.google.common.collect.Maps; -import org.junit.Assert; -import org.junit.Test; - -import java.io.IOException; -import java.net.MalformedURLException; -import java.util.Map; - -public class PluginUtilTest { - - @Test(expected = Exception.class) - public void buildSourceAndSinkPathByLoadMode() throws Exception { - String type = "source"; - String prefix = ""; - String localSqlPluginPath = "."; - String remoteSqlPluginPath = "."; - try { - PluginUtil.buildSourceAndSinkPathByLoadMode(type, prefix, localSqlPluginPath, remoteSqlPluginPath, "classpath"); - } catch (Exception e){ - PluginUtil.buildSourceAndSinkPathByLoadMode(type, prefix, localSqlPluginPath, remoteSqlPluginPath, "shipfile"); - } - } - - @Test(expected = Exception.class) - public void buildSidePathByLoadMode() throws Exception { - PluginUtil.buildSidePathByLoadMode("", "", "", "", "", ""); - String type = "source"; - String prefix = ""; - String localSqlPluginPath = "."; - String remoteSqlPluginPath = "."; - try { - PluginUtil.buildSidePathByLoadMode(type, "s", prefix, localSqlPluginPath, remoteSqlPluginPath, "classpath"); - } catch (Exception e){ - PluginUtil.buildSidePathByLoadMode(type, "a", prefix, localSqlPluginPath, remoteSqlPluginPath, "shipfile"); - } - } - - - @Test(expected = RuntimeException.class) - public void getJarFileDirPath() { - PluginUtil.getJarFileDirPath("a", "b", ""); - } - - @Test(expected = Exception.class) - public void getSideJarFileDirPath() throws MalformedURLException { - PluginUtil.getSideJarFileDirPath("a", "b", "c", "d", ""); - } - - @Test - public void getGenerClassName() throws IOException { - PluginUtil.getGenerClassName("a", "b"); - } - - @Test - public void getSqlParserClassName(){ - PluginUtil.getSqlParserClassName("a", "b"); - } - @Test - public void getSqlSideClassName(){ - PluginUtil.getSqlSideClassName("a", "b", "c"); - } - - @Test - public void objectToMap() throws Exception{ - Map cache = Maps.newHashMap(); - cache.put("k","v"); - PluginUtil.objectToMap(cache); - } - - @Test - public void jsonStrToObject() throws IOException { - Assert.assertEquals(PluginUtil.jsonStrToObject("true", Boolean.class), true); - } - - @Test - public void stringToProperties() throws IOException{ - PluginUtil.stringToProperties("{}"); - } - -} diff --git a/core/src/test/java/com/dtstack/flink/sql/util/PropertiesUtilTest.java b/core/src/test/java/com/dtstack/flink/sql/util/PropertiesUtilTest.java deleted file mode 100644 index 19565d6b6..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/util/PropertiesUtilTest.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.dtstack.flink.sql.util; - -import org.junit.Test; - -import java.util.Properties; - -public class PropertiesUtilTest { - - @Test - public void propertiesTrim(){ - Properties properties = new Properties(); - properties.put("k", "v"); - PropertiesUtils.propertiesTrim(properties); - } -} diff --git a/core/src/test/java/com/dtstack/flink/sql/util/ReflectionUtilTest.java b/core/src/test/java/com/dtstack/flink/sql/util/ReflectionUtilTest.java deleted file mode 100644 index 5296e8fab..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/util/ReflectionUtilTest.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.dtstack.flink.sql.util; - -import org.junit.Test; - -public class ReflectionUtilTest extends Object{ - - @Test - public void getDeclaredMethod(){ - ReflectionUtilTest reflectionUtilTest = new ReflectionUtilTest(); - ReflectionUtils.getDeclaredMethod(reflectionUtilTest, "getDeclaredField", String.class); - } - - @Test - public void getDeclaredField(){ - ReflectionUtilTest reflectionUtilTest = new ReflectionUtilTest(); - ReflectionUtils.getDeclaredField(reflectionUtilTest, "id"); - } - -} diff --git a/core/src/test/java/com/dtstack/flink/sql/util/TableUtilTest.java b/core/src/test/java/com/dtstack/flink/sql/util/TableUtilTest.java deleted file mode 100644 index d8e927e86..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/util/TableUtilTest.java +++ /dev/null @@ -1,374 +0,0 @@ -package com.dtstack.flink.sql.util; - -import com.dtstack.flink.sql.side.JoinInfo; -import com.google.common.collect.HashBasedTable; -import com.google.common.collect.HashBiMap; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import org.apache.calcite.config.Lex; -import org.apache.calcite.sql.SqlBasicCall; -import org.apache.calcite.sql.SqlIdentifier; -import org.apache.calcite.sql.SqlJoin; -import org.apache.calcite.sql.SqlKind; -import org.apache.calcite.sql.SqlNode; -import org.apache.calcite.sql.SqlNodeList; -import org.apache.calcite.sql.SqlSelect; -import org.apache.calcite.sql.fun.SqlCase; -import org.apache.calcite.sql.parser.SqlParseException; -import org.apache.calcite.sql.parser.SqlParser; -import org.apache.flink.calcite.shaded.com.google.common.collect.ImmutableList; -import org.apache.flink.table.api.Table; -import org.apache.flink.table.api.TableSchema; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -import java.util.Arrays; -import java.util.Map; -import java.util.Queue; - -import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.anyObject; -import static org.mockito.Mockito.anyString; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -@RunWith(PowerMockRunner.class) -@PrepareForTest({SqlSelect.class, SqlJoin.class, FieldReplaceUtil.class, TableUtils.class}) -public class TableUtilTest { - - @Test - public void parserSelectField() throws SqlParseException { - SqlParser.Config config = SqlParser.configBuilder() - .setLex(Lex.MYSQL) - .build(); - SqlParser sqlParser = SqlParser - .create("select id from source s left join sideTable t on s.id = t.id ", config); - SqlNode sqlNode = sqlParser.parseStmt(); - TableUtils.parserSelectField((SqlSelect) sqlNode, Maps.newHashMap()); - } - - @Test - public void extractSelectFieldToFieldInfo() { - SqlIdentifier sqlNode = mock(SqlIdentifier.class); - when(sqlNode.getKind()).thenReturn(SqlKind.IDENTIFIER); - when(sqlNode.isStar()).thenReturn(false); - sqlNode.names = ImmutableList.copyOf(Arrays.asList("a")); - when(sqlNode.getComponent(0)).thenReturn(sqlNode); - when(sqlNode.getSimple()).thenReturn("b"); - TableUtils.extractSelectFieldToFieldInfo(sqlNode, "", Lists.newArrayList(), Maps.newHashMap()); - - - when(sqlNode.isStar()).thenReturn(true); - sqlNode.names = ImmutableList.copyOf(Arrays.asList("a", "b")); - - SqlIdentifier sqlIdentifier = mock(SqlIdentifier.class); - when(sqlNode.skipLast(1)).thenReturn(sqlIdentifier); - when(sqlIdentifier.getSimple()).thenReturn("ab"); - try { - TableUtils.extractSelectFieldToFieldInfo(sqlNode, "", Lists.newArrayList(), Maps.newHashMap()); - } catch (RuntimeException e) { - Map localTableCache = Maps.newHashMap(); - Table table = mock(Table.class); - localTableCache.put("ab", table); - TableSchema tableSchema = mock(TableSchema.class); - when(table.getSchema()).thenReturn(tableSchema); - when(tableSchema.getFieldNames()).thenReturn(Lists.newArrayList("a").toArray(new String[1])); - TableUtils.extractSelectFieldToFieldInfo(sqlNode, "", Lists.newArrayList(), localTableCache); - } - - } - - @Test - public void extractSelectFieldToFieldInfoWithCoalesce() { - SqlIdentifier sqlNode = mock(SqlIdentifier.class); - when(sqlNode.getKind()).thenReturn(SqlKind.IDENTIFIER); - when(sqlNode.isStar()).thenReturn(false); - sqlNode.names = ImmutableList.copyOf(Arrays.asList("a")); - when(sqlNode.getComponent(0)).thenReturn(sqlNode); - when(sqlNode.getSimple()).thenReturn("b"); - - SqlBasicCall sqlBasicCall = mock(SqlBasicCall.class); - when(sqlBasicCall.getKind()).thenReturn(SqlKind.COALESCE); - SqlNode[] sqlNodes = new SqlNode[1]; - sqlNodes[0] = sqlNode; - when(sqlBasicCall.getOperands()).thenReturn(sqlNodes); - TableUtils.extractSelectFieldToFieldInfo(sqlBasicCall, "", Lists.newArrayList(), Maps.newHashMap()); - } - - - @Test - public void extractSelectFieldToFieldInfoWithAs() { - SqlIdentifier sqlNode = mock(SqlIdentifier.class); - when(sqlNode.getKind()).thenReturn(SqlKind.IDENTIFIER); - when(sqlNode.isStar()).thenReturn(false); - sqlNode.names = ImmutableList.copyOf(Arrays.asList("a")); - when(sqlNode.getComponent(0)).thenReturn(sqlNode); - when(sqlNode.getSimple()).thenReturn("b"); - - SqlCase sqlCase = mock(SqlCase.class); - when(sqlCase.getKind()).thenReturn(SqlKind.CASE); - SqlNodeList sqlNodeList = mock(SqlNodeList.class); - when(sqlNodeList.size()).thenReturn(1); - when(sqlNodeList.get(anyInt())).thenReturn(sqlNode); - when(sqlCase.getWhenOperands()).thenReturn(sqlNodeList); - when(sqlCase.getThenOperands()).thenReturn(sqlNodeList); - when(sqlCase.getElseOperand()).thenReturn(sqlNode); - SqlBasicCall sqlBasicCall = mock(SqlBasicCall.class); - when(sqlBasicCall.getKind()).thenReturn(SqlKind.AS); - SqlNode[] sqlNodes = new SqlNode[1]; - sqlNodes[0] = sqlCase; - when(sqlBasicCall.getOperands()).thenReturn(sqlNodes); - } - - - @Test - public void buildTableField() { - TableUtils.buildTableField("a", "b"); - } - - @Test - public void buildTableNameWithScope() { - TableUtils.buildTableNameWithScope("a", "1"); - TableUtils.buildTableNameWithScope("a", null); - } - - - @Test - public void buildAsNodeByJoinInfo() { - JoinInfo joinInfo = mock(JoinInfo.class); - when(joinInfo.getNewTableName()).thenReturn("new"); - when(joinInfo.getLeftTableAlias()).thenReturn(""); - when(joinInfo.getRightTableAlias()).thenReturn("b"); - - SqlBasicCall sqlNode = mock(SqlBasicCall.class); - when(joinInfo.getLeftNode()).thenReturn(sqlNode); - when(sqlNode.getKind()).thenReturn(SqlKind.AS); - SqlNode[] sqlNodes = new SqlNode[2]; - sqlNodes[0] = sqlNode; - sqlNodes[1] = sqlNode; - when(sqlNode.toString()).thenReturn("sqlnode"); - when(sqlNode.getOperands()).thenReturn(sqlNodes); - - TableUtils.buildAsNodeByJoinInfo(joinInfo, null, "roc"); - } - - @Test - public void dealSelectResultWithJoinInfo() throws Exception { - JoinInfo joinInfo = mock(JoinInfo.class); - when(joinInfo.checkIsSide()).thenReturn(true); - when(joinInfo.isRightIsSideTable()).thenReturn(true); - when(joinInfo.getNewTableName()).thenReturn("new"); - when(joinInfo.getNewTableAlias()).thenReturn("ali"); - when(joinInfo.getLeftTableAlias()).thenReturn("a"); - when(joinInfo.getRightTableAlias()).thenReturn("b"); - HashBasedTable fieldMapping = HashBasedTable.create(); - when(joinInfo.getTableFieldRef()).thenReturn(fieldMapping); - - SqlNode sqlNode = mock(SqlNode.class); - when(sqlNode.getKind()).thenReturn(SqlKind.SELECT); - when(joinInfo.getLeftNode()).thenReturn(sqlNode); - - - SqlSelect sqlSelect = PowerMockito.mock(SqlSelect.class); - SqlNodeList sqlNodeList = mock(SqlNodeList.class); - when(sqlSelect.getSelectList()).thenReturn(sqlNodeList); - - - PowerMockito.mockStatic(FieldReplaceUtil.class); - PowerMockito.doNothing().when(FieldReplaceUtil.class, "replaceFieldName", anyObject(), anyString(), anyString(), anyObject()); - - Queue queue = mock(Queue.class); - TableUtils.dealSelectResultWithJoinInfo(joinInfo, sqlSelect, queue); - when(joinInfo.isRightIsSideTable()).thenReturn(false); - SqlNode sqlRightNode = mock(SqlNode.class); - when(sqlRightNode.getKind()).thenReturn(SqlKind.SELECT); - when(joinInfo.getRightNode()).thenReturn(sqlRightNode); - TableUtils.dealSelectResultWithJoinInfo(joinInfo, sqlSelect, queue); - } - - @Test - public void getFromTableInfo() { - SqlBasicCall sqlNode = mock(SqlBasicCall.class); - when(sqlNode.getKind()).thenReturn(SqlKind.AS); - when(sqlNode.toString()).thenReturn("a"); - SqlNode[] sqlNodes = new SqlNode[2]; - sqlNodes[0] = sqlNode; - sqlNodes[1] = sqlNode; - when(sqlNode.getOperands()).thenReturn(sqlNodes); - TableUtils.getFromTableInfo(sqlNode, Sets.newHashSet()); - - SqlIdentifier sqlIdentifier = mock(SqlIdentifier.class); - when(sqlIdentifier.getKind()).thenReturn(SqlKind.IDENTIFIER); - when(sqlIdentifier.getSimple()).thenReturn("a"); - TableUtils.getFromTableInfo(sqlIdentifier, Sets.newHashSet()); - - SqlJoin sqlJoin = PowerMockito.mock(SqlJoin.class); - when(sqlJoin.getKind()).thenReturn(SqlKind.JOIN); - when(sqlJoin.getLeft()).thenReturn(sqlIdentifier); - when(sqlJoin.getRight()).thenReturn(sqlIdentifier); - - - SqlSelect sqlSelect = PowerMockito.mock(SqlSelect.class); - when(sqlSelect.getKind()).thenReturn(SqlKind.SELECT); - when(sqlSelect.getFrom()).thenReturn(sqlJoin); - TableUtils.getFromTableInfo(sqlSelect, Sets.newHashSet()); - - try { - when(sqlNode.getKind()).thenReturn(SqlKind.CAST); - TableUtils.getFromTableInfo(sqlNode, Sets.newHashSet()); - } catch (Exception e) { - - } - } - - - @Test - public void replaceSelectFieldTable() { - SqlIdentifier sqlIdentifier = mock(SqlIdentifier.class); - when(sqlIdentifier.getKind()).thenReturn(SqlKind.IDENTIFIER); - sqlIdentifier.names = ImmutableList.copyOf(Arrays.asList("old", "a")); - HashBiMap map = HashBiMap.create(); - map.put("a", "b"); - - SqlNode sqlNodeNothing = mock(SqlNode.class); - when(sqlNodeNothing.getKind()).thenReturn(SqlKind.LITERAL_CHAIN); - - SqlBasicCall sqlBasicCallNull = mock(SqlBasicCall.class); - when(sqlBasicCallNull.getKind()).thenReturn(SqlKind.IS_NULL); - when(sqlBasicCallNull.getOperands()).thenReturn(Lists.newArrayList(sqlNodeNothing).toArray(new SqlNode[1])); - - - SqlBasicCall sqlBasicCallAs = mock(SqlBasicCall.class); - when(sqlBasicCallAs.getKind()).thenReturn(SqlKind.AS); - when(sqlBasicCallAs.getOperands()).thenReturn(Lists.newArrayList(sqlNodeNothing).toArray(new SqlNode[1])); - TableUtils.replaceSelectFieldTable(sqlBasicCallAs, "old", "new", map); - - SqlCase sqlCase = mock(SqlCase.class); - when(sqlCase.getKind()).thenReturn(SqlKind.CASE); - SqlNodeList sqlNodeList = mock(SqlNodeList.class); - when(sqlNodeList.getList()).thenReturn(Lists.newArrayList(sqlNodeNothing)); - when(sqlCase.getWhenOperands()).thenReturn(sqlNodeList); - - when(sqlNodeList.get(anyInt())).thenReturn(sqlNodeNothing); - when(sqlNodeList.size()).thenReturn(1); - - when(sqlCase.getThenOperands()).thenReturn(sqlNodeList); - - SqlNode sqlKindNode = mock(SqlNode.class); - when(sqlKindNode.getKind()).thenReturn(SqlKind.LITERAL); - when(sqlCase.getElseOperand()).thenReturn(sqlKindNode); - - TableUtils.replaceSelectFieldTable(sqlCase, "old", "new", map); - - - TableUtils.replaceSelectFieldTable(sqlNodeNothing, "old", "new", map); - - when(sqlNodeNothing.getKind()).thenReturn(SqlKind.OTHER); - TableUtils.replaceSelectFieldTable(sqlNodeNothing, "old", "new", map); - - try { - when(sqlNodeNothing.getKind()).thenReturn(SqlKind.DEFAULT); - TableUtils.replaceSelectFieldTable(sqlNodeNothing, "old", "new", map); - } catch (Exception e) { - - } - - - } - - @Test(expected = Exception.class) - public void replaceOneSelectField() throws Exception { - SqlIdentifier sqlIdentifier = mock(SqlIdentifier.class); - when(sqlIdentifier.getKind()).thenReturn(SqlKind.IDENTIFIER); - sqlIdentifier.names = ImmutableList.copyOf(Arrays.asList("old", "a")); - HashBiMap map = HashBiMap.create(); - map.put("a", "b"); - PowerMockito.spy(TableUtils.class); - PowerMockito.when(TableUtils.class, "replaceOneSelectField", sqlIdentifier, "old", "new", map).thenReturn(null); - - } - - @Test - public void replaceJoinFieldRefTableName(){ - SqlNode sqlNodeNothing = mock(SqlNode.class); - when(sqlNodeNothing.getKind()).thenReturn(SqlKind.LITERAL); - Map fieldRef = Maps.newHashMap(); - fieldRef.put("ss", "aa.bb"); - TableUtils.replaceJoinFieldRefTableName(sqlNodeNothing, fieldRef); - - SqlBasicCall sqlBasicCall = mock(SqlBasicCall.class); - when(sqlBasicCall.getKind()).thenReturn(SqlKind.EQUALS); - when(sqlBasicCall.getOperands()).thenReturn(Lists.newArrayList(sqlNodeNothing).toArray(new SqlNode[1])); - TableUtils.replaceJoinFieldRefTableName(sqlBasicCall, fieldRef); - - SqlIdentifier sqlIdentifier = mock(SqlIdentifier.class); - when(sqlIdentifier.getKind()).thenReturn(SqlKind.IDENTIFIER); - sqlIdentifier.names = ImmutableList.copyOf(Arrays.asList("old", "a")); - when(sqlIdentifier.toString()).thenReturn("ss"); - - when(sqlIdentifier.setName(anyInt(), anyObject())).thenReturn(sqlIdentifier); - TableUtils.replaceJoinFieldRefTableName(sqlIdentifier, fieldRef); - - } - - @Test - public void getTargetRefField() { - Map refFieldMap = Maps.newHashMap(); - refFieldMap.put("a", "b"); - TableUtils.getTargetRefField(refFieldMap, "a"); - } - - @Test - public void replaceWhereCondition() { - TableUtils.replaceWhereCondition(null, null, null, null); - - } - - @Test - public void getConditionRefTable() { - SqlIdentifier sqlIdentifier = mock(SqlIdentifier.class); - when(sqlIdentifier.getKind()).thenReturn(SqlKind.IDENTIFIER); - when(sqlIdentifier.toString()).thenReturn("test"); - TableUtils.getConditionRefTable(sqlIdentifier, Sets.newHashSet()); - - when(sqlIdentifier.getKind()).thenReturn(SqlKind.LITERAL); - TableUtils.getConditionRefTable(sqlIdentifier, Sets.newHashSet()); - - when(sqlIdentifier.getKind()).thenReturn(SqlKind.LITERAL_CHAIN); - TableUtils.getConditionRefTable(sqlIdentifier, Sets.newHashSet()); - - when(sqlIdentifier.getKind()).thenReturn(SqlKind.OTHER); - TableUtils.getConditionRefTable(sqlIdentifier, Sets.newHashSet()); - - SqlBasicCall sqlBasicCall = mock(SqlBasicCall.class); - when(sqlBasicCall.getKind()).thenReturn(SqlKind.COALESCE); - when(sqlBasicCall.getOperands()).thenReturn(Lists.newArrayList(sqlIdentifier).toArray(new SqlNode[1])); - - - SqlCase sqlCase = mock(SqlCase.class); - when(sqlCase.getElseOperand()).thenReturn(sqlIdentifier); - - SqlNodeList sqlNodeList = mock(SqlNodeList.class); - when(sqlNodeList.getList()).thenReturn(Lists.newArrayList(sqlIdentifier)); - when(sqlCase.getThenOperands()).thenReturn(sqlNodeList); - when(sqlCase.getWhenOperands()).thenReturn(sqlNodeList); - - when(sqlCase.getKind()).thenReturn(SqlKind.CASE); - TableUtils.getConditionRefTable(sqlCase, Sets.newHashSet()); - - try { - when(sqlIdentifier.getKind()).thenReturn(SqlKind.DEFAULT); - TableUtils.getConditionRefTable(sqlCase, Sets.newHashSet()); - } catch (Exception e) { - - } - - - } - - -} diff --git a/core/src/test/java/com/dtstack/flink/sql/util/TestDtStringUtil.java b/core/src/test/java/com/dtstack/flink/sql/util/TestDtStringUtil.java deleted file mode 100644 index cf3fdb90b..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/util/TestDtStringUtil.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.util; - -import org.junit.Assert; -import org.junit.Test; - -/** - * @author tiezhu - * Date 2020/6/17 星期三 - */ -public class TestDtStringUtil { - @Test - public void dealSqlCommentTest() { - String testSQLWithComment = "CREATE TABLE MyTable --this is a comment\n"; - Assert.assertEquals("CREATE TABLE MyTable ", DtStringUtil.dealSqlComment(testSQLWithComment)); - testSQLWithComment = "CREATE TABLE 'MyTable--' --this is a comment"; - Assert.assertEquals("CREATE TABLE 'MyTable--' ", DtStringUtil.dealSqlComment(testSQLWithComment)); - testSQLWithComment = "CREATE TABLE MyTable -- this is a '--comment'\n"; - Assert.assertEquals("CREATE TABLE MyTable ", DtStringUtil.dealSqlComment(testSQLWithComment)); - } -} diff --git a/core/src/test/java/com/dtstack/flink/sql/watermarker/CustomerWaterMarkerForLongTest.java b/core/src/test/java/com/dtstack/flink/sql/watermarker/CustomerWaterMarkerForLongTest.java deleted file mode 100644 index f5c78a251..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/watermarker/CustomerWaterMarkerForLongTest.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.dtstack.flink.sql.watermarker; - -import org.apache.flink.streaming.api.windowing.time.Time; -import org.apache.flink.types.Row; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -@RunWith(PowerMockRunner.class) -@PrepareForTest({Time.class}) -public class CustomerWaterMarkerForLongTest { - - @Test - public void extractTimestamp(){ - Time time = mock(Time.class); - when(time.toMilliseconds()).thenReturn(121200000l); - CustomerWaterMarkerForLong customerWaterMarkerForLong = new CustomerWaterMarkerForLong(time, 1,""); - - Row row = mock(Row.class); - when(row.getField(1)).thenReturn(System.currentTimeMillis()); - customerWaterMarkerForLong.extractTimestamp(row); - } -} diff --git a/core/src/test/java/com/dtstack/flink/sql/watermarker/CustomerWaterMarkerForTimeStampTest.java b/core/src/test/java/com/dtstack/flink/sql/watermarker/CustomerWaterMarkerForTimeStampTest.java deleted file mode 100644 index d831c794b..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/watermarker/CustomerWaterMarkerForTimeStampTest.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.dtstack.flink.sql.watermarker; - -import org.apache.flink.streaming.api.windowing.time.Time; -import org.apache.flink.types.Row; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -@RunWith(PowerMockRunner.class) -@PrepareForTest({Time.class}) -public class CustomerWaterMarkerForTimeStampTest { - - @Test - public void extractTimestamp(){ - Time time = mock(Time.class); - when(time.toMilliseconds()).thenReturn(121200000l); - CustomerWaterMarkerForTimeStamp customerWaterMarkerForTimeStamp = new CustomerWaterMarkerForTimeStamp(time, 1,""); - - Row row = mock(Row.class); - when(row.getField(1)).thenReturn(System.currentTimeMillis()); - customerWaterMarkerForTimeStamp.extractTimestamp(row); - } -} diff --git a/core/src/test/java/com/dtstack/flink/sql/watermarker/WaterMarkerAssignerTest.java b/core/src/test/java/com/dtstack/flink/sql/watermarker/WaterMarkerAssignerTest.java deleted file mode 100644 index b4c037f0a..000000000 --- a/core/src/test/java/com/dtstack/flink/sql/watermarker/WaterMarkerAssignerTest.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.dtstack.flink.sql.watermarker; - -import com.dtstack.flink.sql.table.AbstractSourceTableInfo; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.streaming.api.datastream.DataStream; -import org.apache.flink.types.Row; -import org.junit.Assert; -import org.junit.Test; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class WaterMarkerAssignerTest { - - @Test - public void checkNeedAssignWaterMarker(){ - WaterMarkerAssigner waterMarkerAssigner = new WaterMarkerAssigner(); - AbstractSourceTableInfo sourceTableInfo = mock(AbstractSourceTableInfo.class); - when(sourceTableInfo.getEventTimeField()).thenReturn("ss"); - Assert.assertEquals(waterMarkerAssigner.checkNeedAssignWaterMarker(sourceTableInfo), true); - - when(sourceTableInfo.getEventTimeField()).thenReturn(""); - Assert.assertEquals(waterMarkerAssigner.checkNeedAssignWaterMarker(sourceTableInfo), false); - } - - @Test - public void assignWaterMarker(){ - WaterMarkerAssigner waterMarkerAssigner = new WaterMarkerAssigner(); - AbstractSourceTableInfo sourceTableInfo = mock(AbstractSourceTableInfo.class); - DataStream dataStream = mock(DataStream.class); - RowTypeInfo typeInfo = mock(RowTypeInfo.class); - - when(sourceTableInfo.getEventTimeField()).thenReturn("aa"); - when(sourceTableInfo.getMaxOutOrderness()).thenReturn(1); - when(sourceTableInfo.getName()).thenReturn("roc"); - when(sourceTableInfo.getTimeZone()).thenReturn("CST"); - String[] fieldNames = new String[1]; - fieldNames[0] = "aa"; - - TypeInformation typeInformation = mock(TypeInformation.class); - when(typeInformation.getTypeClass()).thenReturn(Long.class); - TypeInformation[] fieldTypes = new TypeInformation[1]; - fieldTypes[0] = typeInformation; - when(typeInfo.getFieldNames()).thenReturn(fieldNames); - when(typeInfo.getFieldTypes()).thenReturn(fieldTypes); - - waterMarkerAssigner.assignWaterMarker(dataStream, typeInfo, sourceTableInfo); - } -} diff --git a/db2/db2-side/db2-all-side/pom.xml b/db2/db2-side/db2-all-side/pom.xml deleted file mode 100644 index 58235e5bb..000000000 --- a/db2/db2-side/db2-all-side/pom.xml +++ /dev/null @@ -1,94 +0,0 @@ - - - - sql.side.db2 - com.dtstack.flink - 1.0-SNAPSHOT - ../pom.xml - - 4.0.0 - - sql.side.all.db2 - - db2-all-side - - jar - - - 1.0-SNAPSHOT - - - - - com.dtstack.flink - sql.side.db2.core - ${sql.side.db2.core.version} - - - - - - - org.apache.maven.plugins - maven-shade-plugin - 1.4 - - - package - - shade - - - - - - - - - - *:* - - META-INF/*.SF - META-INF/*.DSA - META-INF/*.RSA - - - - - - - - - - maven-antrun-plugin - 1.2 - - - copy-resources - - package - - run - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/db2/db2-side/db2-all-side/src/main/java/com/dtstack/flink/sql/side/db2/Db2AllReqRow.java b/db2/db2-side/db2-all-side/src/main/java/com/dtstack/flink/sql/side/db2/Db2AllReqRow.java deleted file mode 100644 index b354a6269..000000000 --- a/db2/db2-side/db2-all-side/src/main/java/com/dtstack/flink/sql/side/db2/Db2AllReqRow.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.db2; - -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.rdb.all.AbstractRdbAllReqRow; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.sql.Connection; -import java.sql.DriverManager; -import java.util.List; - -/** - * Date: 2019/11/20 - * Company: www.dtstack.com - * - * @author xiuzhu - */ - -public class Db2AllReqRow extends AbstractRdbAllReqRow { - - private static final Logger LOG = LoggerFactory.getLogger(Db2AllReqRow.class); - - private static final String DB2_DRIVER = "com.ibm.db2.jcc.DB2Driver"; - - public Db2AllReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { - super(new Db2AllSideInfo(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo)); - } - - @Override - public Connection getConn(String dbUrl, String userName, String password) { - try { - Class.forName(DB2_DRIVER); - Connection conn = DriverManager.getConnection(dbUrl, userName, password); - return conn; - } catch (Exception e) { - LOG.error("", e); - throw new RuntimeException("", e); - } - } -} diff --git a/db2/db2-side/db2-all-side/src/main/java/com/dtstack/flink/sql/side/db2/Db2AllSideInfo.java b/db2/db2-side/db2-all-side/src/main/java/com/dtstack/flink/sql/side/db2/Db2AllSideInfo.java deleted file mode 100644 index 4ce01bcc8..000000000 --- a/db2/db2-side/db2-all-side/src/main/java/com/dtstack/flink/sql/side/db2/Db2AllSideInfo.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.db2; - -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.rdb.all.RdbAllSideInfo; -import com.dtstack.flink.sql.side.rdb.table.RdbSideTableInfo; -import com.dtstack.flink.sql.util.DtStringUtil; -import org.apache.flink.api.java.typeutils.RowTypeInfo; - -import java.util.List; - -/** - * Reason: - * Date: 2019/11/20 - * Company: www.dtstack.com - * - * @author xiuzhu - */ - -public class Db2AllSideInfo extends RdbAllSideInfo { - public Db2AllSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { - super(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); - } - - @Override - public String getTableName(RdbSideTableInfo rdbSideTableInfo) { - return DtStringUtil.getTableFullPath(rdbSideTableInfo.getSchema(), rdbSideTableInfo.getTableName()); - } -} diff --git a/db2/db2-side/db2-all-side/src/test/java/com/dtstack/flink/sql/side/db2/Db2AllReqRowTest.java b/db2/db2-side/db2-all-side/src/test/java/com/dtstack/flink/sql/side/db2/Db2AllReqRowTest.java deleted file mode 100644 index 8e6bac65c..000000000 --- a/db2/db2-side/db2-all-side/src/test/java/com/dtstack/flink/sql/side/db2/Db2AllReqRowTest.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.dtstack.flink.sql.side.db2; - -import com.dtstack.flink.sql.side.rdb.all.RdbAllReqRowTestBase; - -public class Db2AllReqRowTest extends RdbAllReqRowTestBase { - - @Override - protected void init() { - clazz = Db2AllReqRow.class; - } - -} \ No newline at end of file diff --git a/db2/db2-side/db2-async-side/pom.xml b/db2/db2-side/db2-async-side/pom.xml deleted file mode 100644 index bb88b3d3e..000000000 --- a/db2/db2-side/db2-async-side/pom.xml +++ /dev/null @@ -1,92 +0,0 @@ - - - - sql.side.db2 - com.dtstack.flink - 1.0-SNAPSHOT - - 4.0.0 - - sql.side.async.db2 - db2-async-side - - jar - - - 1.0-SNAPSHOT - - - - - com.dtstack.flink - sql.side.db2.core - ${sql.side.db2.core.version} - - - - - - - org.apache.maven.plugins - maven-shade-plugin - 1.4 - - - package - - shade - - - - - - - - - - *:* - - META-INF/*.SF - META-INF/*.DSA - META-INF/*.RSA - - - - - - - - - - maven-antrun-plugin - 1.2 - - - copy-resources - - package - - run - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/db2/db2-side/db2-async-side/src/main/java/com/dtstack/flink/sql/side/db2/Db2AsyncReqRow.java b/db2/db2-side/db2-async-side/src/main/java/com/dtstack/flink/sql/side/db2/Db2AsyncReqRow.java deleted file mode 100644 index 8df7a1a02..000000000 --- a/db2/db2-side/db2-async-side/src/main/java/com/dtstack/flink/sql/side/db2/Db2AsyncReqRow.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.db2; - -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.rdb.async.RdbAsyncReqRow; -import com.dtstack.flink.sql.side.rdb.table.RdbSideTableInfo; -import io.vertx.core.json.JsonObject; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.configuration.Configuration; - -import java.util.List; - -/** - * Reason: - * Date: 2019/11/20 - * Company: www.dtstack.com - * - * @author xiuzhu - */ - -public class Db2AsyncReqRow extends RdbAsyncReqRow { - private final static String DB2_PREFERRED_TEST_QUERY_SQL = "select 1 from sysibm.dual"; - - private final static String DB2_DRIVER = "com.ibm.db2.jcc.DB2Driver"; - - public Db2AsyncReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { - super(new Db2AsyncSideInfo(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo)); - } - - @Override - public void open(Configuration parameters) throws Exception { - super.open(parameters); - } - - @Override - public JsonObject buildJdbcConfig() { - JsonObject db2ClientConfig = new JsonObject(); - RdbSideTableInfo rdbSideTableInfo = (RdbSideTableInfo) sideInfo.getSideTableInfo(); - db2ClientConfig.put("url", rdbSideTableInfo.getUrl()) - .put("driver_class", DB2_DRIVER) - .put("max_pool_size", rdbSideTableInfo.getAsyncPoolSize()) - .put("user", rdbSideTableInfo.getUserName()) - .put("password", rdbSideTableInfo.getPassword()) - .put("provider_class", DT_PROVIDER_CLASS) - .put("preferred_test_query", DB2_PREFERRED_TEST_QUERY_SQL) - .put("idle_connection_test_period", DEFAULT_IDLE_CONNECTION_TEST_PEROID) - .put("test_connection_on_checkin", DEFAULT_TEST_CONNECTION_ON_CHECKIN); - return db2ClientConfig; - } -} diff --git a/db2/db2-side/db2-async-side/src/main/java/com/dtstack/flink/sql/side/db2/Db2AsyncSideInfo.java b/db2/db2-side/db2-async-side/src/main/java/com/dtstack/flink/sql/side/db2/Db2AsyncSideInfo.java deleted file mode 100644 index 91418a1d0..000000000 --- a/db2/db2-side/db2-async-side/src/main/java/com/dtstack/flink/sql/side/db2/Db2AsyncSideInfo.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.db2; - -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.rdb.async.RdbAsyncSideInfo; -import com.dtstack.flink.sql.side.rdb.table.RdbSideTableInfo; -import com.dtstack.flink.sql.util.DtStringUtil; -import org.apache.flink.api.java.typeutils.RowTypeInfo; - -import java.util.List; - -/** - * Reason: - * Date: 2019/11/20 - * Company: www.dtstack.com - * - * @author xiuzhu - */ - -public class Db2AsyncSideInfo extends RdbAsyncSideInfo { - public Db2AsyncSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { - super(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); - } - - @Override - public String getTableName(RdbSideTableInfo rdbSideTableInfo) { - return DtStringUtil.getTableFullPath(rdbSideTableInfo.getSchema(), rdbSideTableInfo.getTableName()); - } - -} diff --git a/db2/db2-side/db2-async-side/src/test/java/com/dtstack/flink/sql/side/db2/Db2AsyncReqRowTest.java b/db2/db2-side/db2-async-side/src/test/java/com/dtstack/flink/sql/side/db2/Db2AsyncReqRowTest.java deleted file mode 100644 index 0d734003d..000000000 --- a/db2/db2-side/db2-async-side/src/test/java/com/dtstack/flink/sql/side/db2/Db2AsyncReqRowTest.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.dtstack.flink.sql.side.db2; - -import com.dtstack.flink.sql.side.rdb.async.RdbAsyncReqRowTestBase; - -public class Db2AsyncReqRowTest extends RdbAsyncReqRowTestBase { - - @Override - protected void init() { - clazz = Db2AsyncReqRow.class; - } - -} \ No newline at end of file diff --git a/db2/db2-side/db2-side-core/pom.xml b/db2/db2-side/db2-side-core/pom.xml deleted file mode 100644 index 1b9681266..000000000 --- a/db2/db2-side/db2-side-core/pom.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - sql.side.db2 - com.dtstack.flink - 1.0-SNAPSHOT - ../pom.xml - - 4.0.0 - - sql.side.db2.core - 1.0-SNAPSHOT - jar - db2-side-core - - - \ No newline at end of file diff --git a/db2/db2-side/db2-side-core/src/main/java/com/dtstack/flink/sql/side/db2/table/Db2SideParser.java b/db2/db2-side/db2-side-core/src/main/java/com/dtstack/flink/sql/side/db2/table/Db2SideParser.java deleted file mode 100644 index bc12e9a38..000000000 --- a/db2/db2-side/db2-side-core/src/main/java/com/dtstack/flink/sql/side/db2/table/Db2SideParser.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.db2.table; - -import com.dtstack.flink.sql.core.rdb.JdbcCheckKeys; -import com.dtstack.flink.sql.side.rdb.table.RdbSideParser; -import com.dtstack.flink.sql.table.AbstractTableInfo; - -import java.util.Map; - -/** - * Reason: - * Date: 2019/11/20 - * Company: www.dtstack.com - * - * @author xiuzhu - */ - -public class Db2SideParser extends RdbSideParser { - - private static final String CURR_TYPE = "db2"; - - @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { - props.put(JdbcCheckKeys.DRIVER_NAME, "com.ibm.db2.jcc.DB2Driver"); - AbstractTableInfo tableInfo = super.getTableInfo(tableName, fieldsInfo, props); - - tableInfo.setType(CURR_TYPE); - return tableInfo; - } -} diff --git a/db2/db2-side/db2-side-core/src/test/java/com/dtstack/flink/sql/side/db2/table/Db2SideParserTest.java b/db2/db2-side/db2-side-core/src/test/java/com/dtstack/flink/sql/side/db2/table/Db2SideParserTest.java deleted file mode 100644 index fc3c4cac1..000000000 --- a/db2/db2-side/db2-side-core/src/test/java/com/dtstack/flink/sql/side/db2/table/Db2SideParserTest.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.dtstack.flink.sql.side.db2.table; - -import com.dtstack.flink.sql.table.AbstractTableInfo; -import org.junit.Assert; -import org.junit.Test; - -import java.util.HashMap; -import java.util.Map; - -public class Db2SideParserTest { - -// @Test - public void getTableInfo() { - Db2SideParser sideParser = new Db2SideParser(); - - final String tableName = "table_foo"; - final String fieldsInfo = "id INT, name VARCHAR , PRIMARY KEY (id)\n" + - " , PERIOD FOR SYSTEM_TIME"; - - Map props = new HashMap(); - props.put("url", "jdbc:mysql://foo:3306/db_foo"); - props.put("tablename", "table_foo"); - props.put("username", "foo"); - props.put("password", "foo"); - - AbstractTableInfo tableInfo= sideParser.getTableInfo(tableName, fieldsInfo, props); - - final String NORMAL_TYPE = "db2"; - final String table_type = tableInfo.getType(); - Assert.assertTrue(NORMAL_TYPE.equals(table_type)); - } - -} \ No newline at end of file diff --git a/db2/db2-side/pom.xml b/db2/db2-side/pom.xml deleted file mode 100644 index 85bc19d26..000000000 --- a/db2/db2-side/pom.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - sql.db2 - com.dtstack.flink - 1.0-SNAPSHOT - ../pom.xml - - 4.0.0 - - sql.side.db2 - pom - db2-side - - - db2-async-side - db2-side-core - db2-all-side - - - - 1.0-SNAPSHOT - - - - - com.dtstack.flink - sql.side.rdb - ${rdb.side.version} - - - - com.dtstack.flink - sql.side.rdb - ${rdb.side.version} - test-jar - test - - - - - \ No newline at end of file diff --git a/db2/db2-sink/pom.xml b/db2/db2-sink/pom.xml deleted file mode 100644 index a3f26d33a..000000000 --- a/db2/db2-sink/pom.xml +++ /dev/null @@ -1,94 +0,0 @@ - - - - sql.db2 - com.dtstack.flink - 1.0-SNAPSHOT - ../pom.xml - - 4.0.0 - - sql.sink.db2 - jar - - db2-sink - http://maven.apache.org - - - 1.0-SNAPSHOT - - - - - com.dtstack.flink - sql.sink.rdb - ${sql.sink.rdb.version} - - - - - - - org.apache.maven.plugins - maven-shade-plugin - 1.4 - - - package - - shade - - - - - - - - - - *:* - - META-INF/*.SF - META-INF/*.DSA - META-INF/*.RSA - - - - - - - - - - maven-antrun-plugin - 1.2 - - - copy-resources - - package - - run - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/db2/db2-sink/src/main/java/com/dtstack/flink/sql/sink/db/DbDialect.java b/db2/db2-sink/src/main/java/com/dtstack/flink/sql/sink/db/DbDialect.java deleted file mode 100644 index 49a3613bc..000000000 --- a/db2/db2-sink/src/main/java/com/dtstack/flink/sql/sink/db/DbDialect.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.db; - -import com.dtstack.flink.sql.sink.rdb.dialect.JDBCDialect; -import com.dtstack.flink.sql.util.DtStringUtil; -import org.apache.commons.lang3.StringUtils; - -import java.util.Arrays; -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; - -/** - * Date: 2020/1/19 - * Company: www.dtstack.com - * @author maqi - */ -public class DbDialect implements JDBCDialect { - @Override - public boolean canHandle(String url) { - return url.startsWith("jdbc:db2:"); - } - - @Override - public Optional defaultDriverName() { - return Optional.of("com.ibm.db2.jcc.DB2Driver"); - } - - @Override - public String quoteIdentifier(String identifier) { - return identifier; - } - - @Override - public Optional getUpsertStatement(String schema, String tableName, String[] fieldNames, String[] uniqueKeyFields, boolean allReplace) { - tableName = DtStringUtil.getTableFullPath(schema, tableName); - StringBuilder sb = new StringBuilder(); - sb.append("MERGE INTO " + tableName + " T1 USING " - + "(" + buildValuesStatement(fieldNames) + ") T2 (" - + buildFiledNameStatement(fieldNames) + - ") ON (" - + buildConnectionConditions(uniqueKeyFields) + ") "); - - String updateSql = buildUpdateConnection(fieldNames, uniqueKeyFields, allReplace); - - if (StringUtils.isNotEmpty(updateSql)) { - sb.append(" WHEN MATCHED THEN UPDATE SET "); - sb.append(updateSql); - } - - sb.append(" WHEN NOT MATCHED THEN " - + "INSERT (" + Arrays.stream(fieldNames).map(this::quoteIdentifier).collect(Collectors.joining(",")) + ") VALUES (" - + Arrays.stream(fieldNames).map(col -> "T2." + quoteIdentifier(col)).collect(Collectors.joining(",")) + ")"); - return Optional.of(sb.toString()); - } - - /** - * build T1."A"=T2."A" or T1."A"=nvl(T2."A",T1."A") - * @param fieldNames - * @param uniqueKeyFields - * @param allReplace - * @return - */ - private String buildUpdateConnection(String[] fieldNames, String[] uniqueKeyFields, boolean allReplace) { - List uniqueKeyList = Arrays.asList(uniqueKeyFields); - return Arrays.stream(fieldNames) - .filter(col -> !uniqueKeyList.contains(col)) - .map(col -> buildConnectString(allReplace, col)) - .collect(Collectors.joining(",")); - } - - private String buildConnectString(boolean allReplace, String col) { - return allReplace ? quoteIdentifier("T1") + "." + quoteIdentifier(col) + " = " + quoteIdentifier("T2") + "." + quoteIdentifier(col) : - quoteIdentifier("T1") + "." + quoteIdentifier(col) + " =NVL(" + quoteIdentifier("T2") + "." + quoteIdentifier(col) + "," - + quoteIdentifier("T1") + "." + quoteIdentifier(col) + ")"; - } - - - private String buildConnectionConditions(String[] uniqueKeyFields) { - return Arrays.stream(uniqueKeyFields).map(col -> "T1." + quoteIdentifier(col) + "=T2." + quoteIdentifier(col)).collect(Collectors.joining(",")); - } - - /** - * build sql part e.g: VALUES('1001','zs','sss') - * - * @param column destination column - * @return - */ - public String buildValuesStatement(String[] column) { - StringBuilder sb = new StringBuilder("VALUES("); - String collect = Arrays.stream(column) - .map(col -> " ? ") - .collect(Collectors.joining(", ")); - - return sb.append(collect).append(")").toString(); - } - - /** - * build sql part e.g: id, name, address - * @param column - * @return - */ - public String buildFiledNameStatement(String[] column) { - return Arrays.stream(column) - .collect(Collectors.joining(", ")); - } - - -} diff --git a/db2/db2-sink/src/main/java/com/dtstack/flink/sql/sink/db/DbSink.java b/db2/db2-sink/src/main/java/com/dtstack/flink/sql/sink/db/DbSink.java deleted file mode 100644 index e7139d246..000000000 --- a/db2/db2-sink/src/main/java/com/dtstack/flink/sql/sink/db/DbSink.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.dtstack.flink.sql.sink.db; - -import com.dtstack.flink.sql.sink.rdb.JDBCOptions; -import com.dtstack.flink.sql.sink.rdb.AbstractRdbSink; -import com.dtstack.flink.sql.sink.rdb.format.JDBCUpsertOutputFormat; - -public class DbSink extends AbstractRdbSink { - - public DbSink() { - super(new DbDialect()); - } - @Override - public JDBCUpsertOutputFormat getOutputFormat() { - JDBCOptions jdbcOptions = JDBCOptions.builder() - .setDbUrl(dbUrl) - .setDialect(jdbcDialect) - .setUsername(userName) - .setPassword(password) - .setSchema(schema) - .setTableName(tableName) - .build(); - - return JDBCUpsertOutputFormat.builder() - .setOptions(jdbcOptions) - .setFieldNames(fieldNames) - .setFlushMaxSize(batchNum) - .setFlushIntervalMills(batchWaitInterval) - .setFieldTypes(sqlTypes) - .setKeyFields(primaryKeys) - .setAllReplace(allReplace) - .setErrorLimit(errorLimit) - .setUpdateMode(updateMode).build(); - } -} diff --git a/db2/db2-sink/src/main/java/com/dtstack/flink/sql/sink/db/table/DbSinkParser.java b/db2/db2-sink/src/main/java/com/dtstack/flink/sql/sink/db/table/DbSinkParser.java deleted file mode 100644 index 8a9ad62ab..000000000 --- a/db2/db2-sink/src/main/java/com/dtstack/flink/sql/sink/db/table/DbSinkParser.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.dtstack.flink.sql.sink.db.table; - -import com.dtstack.flink.sql.core.rdb.JdbcCheckKeys; -import com.dtstack.flink.sql.sink.rdb.table.RdbSinkParser; -import com.dtstack.flink.sql.table.AbstractTableInfo; - -import java.util.Map; - -public class DbSinkParser extends RdbSinkParser { - - private static final String CURR_TYPE = "db2"; - - @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { - props.put(JdbcCheckKeys.DRIVER_NAME, "com.ibm.db2.jcc.DB2Driver"); - AbstractTableInfo tableInfo = super.getTableInfo(tableName, fieldsInfo, props); - tableInfo.setType(CURR_TYPE); - return tableInfo; - } -} diff --git a/db2/db2-sink/src/test/java/com/dtstack/flink/sql/sink/db/DbDialectTest.java b/db2/db2-sink/src/test/java/com/dtstack/flink/sql/sink/db/DbDialectTest.java deleted file mode 100644 index 4a30b95b3..000000000 --- a/db2/db2-sink/src/test/java/com/dtstack/flink/sql/sink/db/DbDialectTest.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.dtstack.flink.sql.sink.db; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -public class DbDialectTest { - - DbDialect dialect; - - @Before - public void setUp() throws Exception { - dialect = new DbDialect(); - } - - @Test - public void testEasyUtils() { - final String s = "jdbc:db2://localhost:3306/foo_db"; - boolean r = dialect.canHandle(s); - Assert.assertTrue(r); - - String driver = dialect.defaultDriverName().get(); - Assert.assertTrue(driver.equals("com.ibm.db2.jcc.DB2Driver")); - - final String foo = "foo"; - final String NORMAL_QUOTE = "foo"; - String strWithQuote = dialect.quoteIdentifier(foo); - Assert.assertTrue(strWithQuote.equals(NORMAL_QUOTE)); - } - - @Test - public void testDialect() { - final String tableName = "table_foo"; - final String[] fieldNames = new String[] { - "id", - "name" - }; - final String[] uniqueKeyFields = new String[] { - "id", - }; - final String NORMAL_STMT = - "MERGE INTO \"table_foo\" T1 USING (VALUES( ? , ? )) T2 (id, name) ON (T1.id=T2.id) " + - "WHEN MATCHED THEN UPDATE SET T1.name =NVL(T2.name,T1.name) " + - "WHEN NOT MATCHED THEN INSERT (id,name) VALUES (T2.id,T2.name)"; - - String upsertStmt = dialect - .getUpsertStatement("", tableName, fieldNames, uniqueKeyFields, false) - .get(); - - Assert.assertTrue(NORMAL_STMT.equals(upsertStmt)); - } - -} \ No newline at end of file diff --git a/db2/db2-sink/src/test/java/com/dtstack/flink/sql/sink/db/table/DbSinkParserTest.java b/db2/db2-sink/src/test/java/com/dtstack/flink/sql/sink/db/table/DbSinkParserTest.java deleted file mode 100644 index 603de91f9..000000000 --- a/db2/db2-sink/src/test/java/com/dtstack/flink/sql/sink/db/table/DbSinkParserTest.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.dtstack.flink.sql.sink.db.table; - -import com.dtstack.flink.sql.table.AbstractTableInfo; -import org.junit.Assert; -import org.junit.Test; - -import java.util.HashMap; -import java.util.Map; - -public class DbSinkParserTest { - -// @Test - public void getTableInfo() { - DbSinkParser sinkParser = new DbSinkParser(); - - final String tableName = "table_foo"; - final String fieldsInfo = "id INT, name VARCHAR"; - - Map props = new HashMap(); - props.put("url", "jdbc:mysql://foo:3306/db_foo"); - props.put("tablename", "table_foo"); - props.put("username", "foo"); - props.put("password", "foo"); - - AbstractTableInfo tableInfo= sinkParser.getTableInfo(tableName, fieldsInfo, props); - - final String NORMAL_TYPE = "db2"; - final String table_type = tableInfo.getType(); - Assert.assertTrue(NORMAL_TYPE.equals(table_type)); - } -} \ No newline at end of file diff --git a/db2/pom.xml b/db2/pom.xml deleted file mode 100644 index bfbe0ece3..000000000 --- a/db2/pom.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - flink.sql - com.dtstack.flink - 1.0-SNAPSHOT - ../pom.xml - - 4.0.0 - - sql.db2 - pom - - db2-sink - db2-side - - - - 1.0-SNAPSHOT - - - - - - com.dtstack.flink - sql.core - ${sql.core.version} - provided - - - - com.ibm.db2.jcc - db2jcc - db2jcc4 - - - - - - - \ No newline at end of file diff --git a/dirtyData/console/pom.xml b/dirtyData/console/pom.xml deleted file mode 100644 index f23af774b..000000000 --- a/dirtyData/console/pom.xml +++ /dev/null @@ -1,91 +0,0 @@ - - - - sql.dirtyConsumer - com.dtstack.flink - 1.0-SNAPSHOT - - 4.0.0 - dirtyConsumer-console - dirtyConsumer.console - - - - - org.apache.maven.plugins - maven-shade-plugin - 1.4 - - - package - - shade - - - false - - - - - - - - *:* - - META-INF/*.SF - META-INF/*.DSA - META-INF/*.RSA - - - - - - - - - - maven-antrun-plugin - 1.2 - - - copy-resources - - package - - run - - - - - - - - - - - - - - - - - - - - junit - junit - 4.8.2 - test - - - - log4j - log4j - 1.2.17 - - - - \ No newline at end of file diff --git a/dirtyData/console/src/main/java/com/dtstack/flink/sql/dirty/console/ConsoleDirtyDataConsumer.java b/dirtyData/console/src/main/java/com/dtstack/flink/sql/dirty/console/ConsoleDirtyDataConsumer.java deleted file mode 100644 index 32e2e84af..000000000 --- a/dirtyData/console/src/main/java/com/dtstack/flink/sql/dirty/console/ConsoleDirtyDataConsumer.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.dirty.console; - -import com.dtstack.flink.sql.dirtyManager.consumer.AbstractDirtyDataConsumer; -import com.dtstack.flink.sql.dirtyManager.entity.DirtyDataEntity; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Map; -import java.util.Objects; - -/** - * @author tiezhu - * Company dtstack - * Date 2020/8/27 星期四 - */ -public class ConsoleDirtyDataConsumer extends AbstractDirtyDataConsumer { - private static final long serialVersionUID = 5727194679865135189L; - - private static final Logger LOG = LoggerFactory.getLogger(ConsoleDirtyDataConsumer.class); - - private static final Long DEFAULT_PRINT_LIMIT = 1000L; - - private Long printLimit; - - @Override - public void consume() throws InterruptedException { - DirtyDataEntity dataEntity = queue.take(); - if (count.getAndIncrement() % printLimit == 0) { - LOG.warn("\nget dirtyData: " + dataEntity.getDirtyData() + "\n" - + "cause: " + dataEntity.getCause() + "\n" - + "processTime: " + dataEntity.getProcessDate() + "\n" - + "error field: " + dataEntity.getField()); - } - } - - @Override - public void close() { - isRunning.compareAndSet(true, false); - LOG.info("console dirty consumer close ..."); - } - - @Override - public void init(Map properties) { - LOG.info("console dirty consumer init ..."); - Object printLimit = properties.get("printLimit"); - this.printLimit = Objects.isNull(printLimit) ? - DEFAULT_PRINT_LIMIT : Long.parseLong(String.valueOf(printLimit)); - } -} diff --git a/dirtyData/console/src/test/java/com/dtstack/flink/sql/dirty/console/TestPrintDirtyDataConsumer.java b/dirtyData/console/src/test/java/com/dtstack/flink/sql/dirty/console/TestPrintDirtyDataConsumer.java deleted file mode 100644 index 3d1d64c41..000000000 --- a/dirtyData/console/src/test/java/com/dtstack/flink/sql/dirty/console/TestPrintDirtyDataConsumer.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.dtstack.flink.sql.dirty.console; - -/** - * @author tiezhu - * Company dtstack - * Date 2020/8/28 星期五 - */ -public class TestPrintDirtyDataConsumer { - public static void main(String[] args) { - - } -} diff --git a/dirtyData/mysql/pom.xml b/dirtyData/mysql/pom.xml deleted file mode 100644 index 86efb7316..000000000 --- a/dirtyData/mysql/pom.xml +++ /dev/null @@ -1,90 +0,0 @@ - - - - sql.dirtyConsumer - com.dtstack.flink - 1.0-SNAPSHOT - - 4.0.0 - dirtyConsumer-mysql - - 5.1.46 - - - dirtyConsumer.mysql - - - - mysql - mysql-connector-java - ${mysql.connector.version} - - - - - - - org.apache.maven.plugins - maven-shade-plugin - 1.4 - - - package - - shade - - - false - - - - - - - - *:* - - META-INF/*.SF - META-INF/*.DSA - META-INF/*.RSA - - - - - - - - - - maven-antrun-plugin - 1.2 - - - copy-resources - - package - - run - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/dirtyData/mysql/src/main/java/com/dtstack/flink/sql/dirty/mysql/MysqlDirtyDataConsumer.java b/dirtyData/mysql/src/main/java/com/dtstack/flink/sql/dirty/mysql/MysqlDirtyDataConsumer.java deleted file mode 100644 index b03535ef5..000000000 --- a/dirtyData/mysql/src/main/java/com/dtstack/flink/sql/dirty/mysql/MysqlDirtyDataConsumer.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.dirty.mysql; - -import com.dtstack.flink.sql.dirtyManager.consumer.AbstractDirtyDataConsumer; -import com.dtstack.flink.sql.dirtyManager.entity.DirtyDataEntity; - -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.PreparedStatement; -import java.sql.SQLException; -import java.sql.Statement; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.stream.Collectors; - -/** - * @author tiezhu - * Company dtstack - * Date 2020/8/27 星期四 - */ -public class MysqlDirtyDataConsumer extends AbstractDirtyDataConsumer { - - private static final long serialVersionUID = -2959753658786001679L; - - private static final String DRIVER_NAME = "com.mysql.jdbc.Driver"; - - private static final int CONN_VALID_TIME = 1000; - - private static final Integer FIELD_NUMBER = 4; - - private final Object LOCK_STR = new Object(); - - private final String[] tableField = {"id", "dirtyData", "processTime", "cause"}; - - private PreparedStatement statement; - - private Connection connection; - - private Long batchSize; - - private void beforeConsume(String url, - String userName, - String password, - String tableName, - boolean isCreatedTable) throws ClassNotFoundException, SQLException { - synchronized (LOCK_STR) { - Class.forName(DRIVER_NAME); - connection = DriverManager.getConnection(url, userName, password); - - // create table for dirty data - if (!isCreatedTable) { - createTable(tableName); - } - - String insertField = Arrays.stream(tableField) - .map(this::quoteIdentifier) - .collect(Collectors.joining(", ")); - String insertSql = "INSERT INTO " + quoteIdentifier(tableName) - + "(" + insertField + ") VALUES (?, ?, ?, ?)"; - statement = connection.prepareStatement(insertSql); - } - } - - private String quoteIdentifier(String tableName) { - return "`" + tableName + "`"; - } - - /** - * 创建存储脏数据的表 - * - * @param tableName 表名 - * @throws SQLException SQL异常 - */ - private void createTable(String tableName) throws SQLException { - Statement statement = null; - try { - String sql = - "CREATE TABLE IF NOT EXISTS \n" - + quoteIdentifier(tableName) + " (\n" + - " `id` bigint not null AUTO_INCREMENT,\n" + - " `dirtyData` text DEFAULT NULL,\n" + - " `processTime` varchar(255) DEFAULT NULL,\n" + - " `cause` text DEFAULT NULL,\n" + - " PRIMARY KEY (id)\n" + - ") DEFAULT CHARSET=utf8;"; - statement = connection.createStatement(); - statement.execute(sql); - } catch (SQLException e) { - throw new RuntimeException("create table error !", e); - } finally { - if (statement != null && !statement.isClosed()) { - statement.close(); - } - } - } - - @Override - public void consume() throws Exception { - DirtyDataEntity entity = queue.take(); - count.incrementAndGet(); - - List data = new ArrayList<>(); - data.add(String.valueOf(count.get())); - Collections.addAll(data, entity.get()); - for (int i = 0; i < FIELD_NUMBER; i++) { - statement.setString(i + 1, Objects.isNull(data.get(i)) ? null : data.get(i)); - } - - statement.addBatch(); - - if (count.get() % batchSize == 0) { - LOG.warn("Get dirty Data: " + entity.getDirtyData()); - statement.executeBatch(); - } - } - - @Override - public void close() { - isRunning.compareAndSet(true, false); - - try { - if (connection != null && !connection.isValid(CONN_VALID_TIME)) { - connection.close(); - } - - if (statement != null && !statement.isClosed()) { - statement.close(); - } - } catch (SQLException e) { - throw new RuntimeException("close mysql resource error !"); - } - } - - @Override - public void init(Map properties) throws Exception { - SimpleDateFormat timeFormat = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss"); - String tableName = (String) properties.getOrDefault("dirtyTableName", - "DirtyData_" - + properties.get("tableName") + "_" - + timeFormat.format(System.currentTimeMillis())); - - String userName = (String) properties.get("userName"); - String password = (String) properties.get("password"); - String url = (String) properties.get("url"); - batchSize = Long.parseLong((String) properties.getOrDefault("batchSize", "10000")); - errorLimit = Long.parseLong((String) properties.getOrDefault("errorLimit", "1000")); - - boolean isCreatedTable = Boolean.parseBoolean( - (String) properties.getOrDefault("isCreatedTable", "false")); - - beforeConsume(url, userName, password, tableName, isCreatedTable); - } -} diff --git a/dirtyData/pom.xml b/dirtyData/pom.xml deleted file mode 100644 index c077855f2..000000000 --- a/dirtyData/pom.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - flink.sql - com.dtstack.flink - 1.0-SNAPSHOT - - 4.0.0 - - sql.dirtyConsumer - pom - - console - mysql - - - - 3.8.1 - 1.0-SNAPSHOT - - - - - junit - junit - ${junit.version} - test - - - - com.dtstack.flink - sql.core - ${sql.core.version} - provided - - - - \ No newline at end of file diff --git a/docs/cassandraSide.md b/docs/cassandraSide.md new file mode 100644 index 000000000..131560047 --- /dev/null +++ b/docs/cassandraSide.md @@ -0,0 +1,85 @@ + +## 1.格式: +``` + CREATE TABLE tableName( + colName cloType, + ... + PRIMARY KEY(keyInfo), + PERIOD FOR SYSTEM_TIME + )WITH( + type ='cassandra', + address ='ip:port[,ip:port]', + userName='dbUserName', + password='dbPwd', + tableName='tableName', + database='database', + cache ='LRU', + cacheSize ='10000', + cacheTTLMs ='60000', + parallelism ='1', + partitionedJoin='false' + ); +``` + +# 2.支持版本 + cassandra-3.6.x + +## 3.表结构定义 + + |参数名称|含义| + |----|---| + | tableName | 注册到flink的表名称(可选填;不填默认和hbase对应的表名称相同)| + | colName | 列名称| + | colType | 列类型 [colType支持的类型](colType.md)| + | PERIOD FOR SYSTEM_TIME | 关键字表明该定义的表为维表信息| + | PRIMARY KEY(keyInfo) | 维表主键定义;多个列之间用逗号隔开| + +## 4.参数 + + |参数名称|含义|是否必填|默认值| + |----|---|---|----| + | type |表明 输出表类型 cassandra|是|| + | address | 连接cassandra数据库 jdbcUrl |是|| + | userName | cassandra连接用户名|否|| + | password | cassandra连接密码|否|| + | tableName | cassandra表名称|是|| + | database | cassandra表名称|是|| + | cache | 维表缓存策略(NONE/LRU)|否|NONE| + | partitionedJoin | 是否在維表join之前先根据 設定的key 做一次keyby操作(可以減少维表的数据缓存量)|否|false| + | maxRequestsPerConnection | 每个连接最多允许64个并发请求|否|NONE| + | coreConnectionsPerHost | 和Cassandra集群里的每个机器都至少有2个连接|否|NONE| + | maxConnectionsPerHost | 和Cassandra集群里的每个机器都最多有6个连接|否|NONE| + | maxQueueSize | Cassandra队列大小|否|NONE| + | readTimeoutMillis | Cassandra读超时|否|NONE| + | connectTimeoutMillis | Cassandra连接超时|否|NONE| + | poolTimeoutMillis | Cassandra线程池超时|否|NONE| + + ---------- + > 缓存策略 + * NONE: 不做内存缓存 + * LRU: + * cacheSize: 缓存的条目数量 + * cacheTTLMs:缓存的过期时间(ms) + + +## 5.样例 +``` +create table sideTable( + CHANNEL varchar, + XCCOUNT int, + PRIMARY KEY(channel), + PERIOD FOR SYSTEM_TIME + )WITH( + type ='cassandra', + address ='172.21.32.1:9042,172.21.32.1:9042', + database ='test', + tableName ='sidetest', + cache ='LRU', + parallelism ='1', + partitionedJoin='false' + ); + + +``` + + diff --git a/docs/cassandraSink.md b/docs/cassandraSink.md new file mode 100644 index 000000000..8ea38e104 --- /dev/null +++ b/docs/cassandraSink.md @@ -0,0 +1,63 @@ +## 1.格式: +``` +CREATE TABLE tableName( + colName colType, + ... + colNameX colType + )WITH( + type ='cassandra', + address ='ip:port[,ip:port]', + userName ='userName', + password ='pwd', + database ='databaseName', + tableName ='tableName', + parallelism ='parllNum' + ); + +``` + +## 2.支持版本 + cassandra-3.6.x + +## 3.表结构定义 + +|参数名称|含义| +|----|---| +| tableName| 在 sql 中使用的名称;即注册到flink-table-env上的名称| +| colName | 列名称| +| colType | 列类型 [colType支持的类型](colType.md)| + +## 4.参数: + +|参数名称|含义|是否必填|默认值| +|----|----|----|----| +|type |表明 输出表类型 cassandra|是|| +|address | 连接cassandra数据库 jdbcUrl |是|| +|userName | cassandra连接用户名|否|| +|password | cassandra连接密码|否|| +|tableName | cassandra表名称|是|| +|database | cassandra表名称|是|| +|parallelism | 并行度设置|否|1| +|maxRequestsPerConnection | 每个连接最多允许64个并发请求|否|NONE| +|coreConnectionsPerHost | 和Cassandra集群里的每个机器都至少有2个连接|否|NONE| +|maxConnectionsPerHost | 和Cassandra集群里的每个机器都最多有6个连接|否|NONE| +|maxQueueSize | Cassandra队列大小|否|NONE| +|readTimeoutMillis | Cassandra读超时|否|NONE| +|connectTimeoutMillis | Cassandra连接超时|否|NONE| +|poolTimeoutMillis | Cassandra线程池超时|否|NONE| + +## 5.样例: +``` +CREATE TABLE MyResult( + channel VARCHAR, + pv VARCHAR + )WITH( + type ='cassandra', + address ='172.21.32.1:9042,172.21.32.1:9042', + userName ='dtstack', + password ='abc123', + database ='test', + tableName ='pv', + parallelism ='1' + ) + ``` \ No newline at end of file diff --git a/docs/clickhouseSide.md b/docs/clickhouseSide.md new file mode 100644 index 000000000..63d3cc3da --- /dev/null +++ b/docs/clickhouseSide.md @@ -0,0 +1,85 @@ + +## 1.格式: +``` + CREATE TABLE tableName( + colName cloType, + ... + PRIMARY KEY(keyInfo), + PERIOD FOR SYSTEM_TIME + )WITH( + type='clickhouse', + url='jdbcUrl', + userName='dbUserName', + password='dbPwd', + tableName='tableName', + cache ='LRU', + cacheSize ='10000', + cacheTTLMs ='60000', + parallelism ='1', + partitionedJoin='false' + ); +``` + +# 2.支持版本 + 19.14.x、19.15.x、19.16.x + +## 3.表结构定义 + + |参数名称|含义| + |----|---| + | tableName | clickhouse表名称| + | colName | 列名称| + | colType | 列类型 [colType支持的类型](colType.md)| + | PERIOD FOR SYSTEM_TIME | 关键字表明该定义的表为维表信息| + | PRIMARY KEY(keyInfo) | 维表主键定义;多个列之间用逗号隔开| + +## 4.参数 + + |参数名称|含义|是否必填|默认值| + |----|---|---|----| + | type | 表明维表的类型 clickhouse |是|| + | url | 连接clickhouse数据库 jdbcUrl |是|| + | userName | clickhouse连接用户名 |是|| + | password | clickhouse连接密码|是|| + | tableName | clickhouse表名称|是|| + | tableName | clickhouse 的表名称|是|| + | cache | 维表缓存策略(NONE/LRU)|否|NONE| + | partitionedJoin | 是否在維表join之前先根据 設定的key 做一次keyby操作(可以減少维表的数据缓存量)|否|false| + + ---------- + > 缓存策略 + * NONE: 不做内存缓存 + * LRU: + * cacheSize: 缓存的条目数量 + * cacheTTLMs:缓存的过期时间(ms) + * cacheMode: (unordered|ordered)异步加载是有序还是无序,默认有序。 + * asyncCapacity:异步请求容量,默认1000 + * asyncTimeout:异步请求超时时间,默认10000毫秒 + +## 5.样例 +``` +create table sideTable( + channel varchar, + xccount int, + PRIMARY KEY(channel), + PERIOD FOR SYSTEM_TIME + )WITH( + type='clickhouse', + url='jdbc:clickhouse://172.16.8.104:3306/test?charset=utf8', + userName='dtstack', + password='abc123', + tableName='sidetest', + cache ='LRU', + cacheSize ='10000', + cacheTTLMs ='60000', + cacheMode='unordered', + asyncCapacity='1000', + asyncTimeout='10000' + parallelism ='1', + partitionedJoin='false' + ); + + +``` + + diff --git a/docs/clickhouseSink.md b/docs/clickhouseSink.md new file mode 100644 index 000000000..d9774727f --- /dev/null +++ b/docs/clickhouseSink.md @@ -0,0 +1,53 @@ +## 1.格式: +``` +CREATE TABLE tableName( + colName colType, + ... + colNameX colType + )WITH( + type ='clickhouse', + url ='jdbcUrl', + userName ='userName', + password ='pwd', + tableName ='tableName', + parallelism ='parllNum' + ); + +``` + +## 2.支持版本 + 19.14.x、19.15.x、19.16.x + +## 3.表结构定义 + +|参数名称|含义| +|----|---| +| tableName| clickhouse表名称| +| colName | 列名称| +| colType | 列类型 [colType支持的类型](colType.md)| + +## 4.参数: + +|参数名称|含义|是否必填|默认值| +|----|----|----|----| +|type |表明 输出表类型 clickhouse |是|| +|url | 连接clickhouse 数据库 jdbcUrl |是|| +|userName | clickhouse 连接用户名 |是|| +| password | clickhouse 连接密码|是|| +| tableName | clickhouse 表名称|是|| +| parallelism | 并行度设置|否|1| + +## 5.样例: +``` +CREATE TABLE MyResult( + channel VARCHAR, + pv VARCHAR + )WITH( + type ='clickhouse', + url ='jdbc:clickhouse://172.16.8.104:3306/test?charset=utf8', + userName ='dtstack', + password ='abc123', + tableName ='pv2', + parallelism ='1' + ) + ``` \ No newline at end of file diff --git a/docs/config.md b/docs/config.md deleted file mode 100644 index eb4750422..000000000 --- a/docs/config.md +++ /dev/null @@ -1,110 +0,0 @@ -### 命令行参数选项 - -``` -sh submit.sh -key1 val1 -key2 val2 -``` -其中key的可选参数描述如下 - -* **mode** - * 描述:执行模式,也就是flink集群的工作模式 - * local: 本地模式 - * standalone: 提交到独立部署模式的flink集群 - * yarn: 提交到yarn模式的flink集群,该模式下需要提前启动一个yarn-session,使用默认名"Flink session cluster" - * yarnPer: yarn per_job模式提交(即创建新flink application),默认名为flink任务名称 - * 必选:否 - * 默认值:local - -* **pluginLoadMode** - * 描述:yarnPer 模式下的插件包加载方式。 - * classpath: 从节点机器加载指定remoteSqlPluginPath路径插件包,需要预先在每个运行节点下存放一份插件包。 - * shipfile: 将localSqlPluginPath路径下的插件从本地上传到hdfs,不需要集群的每台机器存放一份插件包。 - * 必选:否 - * 默认值:classpath - - -* **name** - * 描述:flink 任务对应名称。 - * 必选:是 - * 默认值:无 - -* **sql** - * 描述:待执行的flink sql所在路径 。 - * 必选:是 - * 默认值:无 - -* **localSqlPluginPath** - * 描述:本地插件根目录地址,也就是打包后产生的plugins目录。 - * 必选:是 - * 默认值:无 - -* **remoteSqlPluginPath** - * 描述:flink执行集群上的插件根目录地址(将打包好的插件存放到各个flink节点上,如果是yarn集群需要存放到所有的nodemanager上)。 - * 必选:否 - * 默认值:无 - -* **addjar** - * 描述:扩展jar路径,当前主要是UDF定义的jar; - * 必选:否 - * 默认值:无 - -* **addShipfile** - * 描述:扩展上传的文件,比如开启;Kerberos认证需要的keytab文件和krb5.conf文件 - * 必选:否 - * 默认值:无 - -* **confProp** - * 描述:一些参数设置 - * 必选:否 - * 默认值:{} - * 可选参数: - * sql.ttl.min: 最小过期时间,大于0的整数,如1d、1h(d\D:天,h\H:小时,m\M:分钟,s\s:秒) - * sql.ttl.max: 最大过期时间,大于0的整数,如2d、2h(d\D:天,h\H:小时,m\M:分钟,s\s:秒),需同时设置最小时间,且比最小时间大5分钟 - * state.backend: 任务状态后端,可选为MEMORY,FILESYSTEM,ROCKSDB,默认为flinkconf中的配置。 - * state.checkpoints.dir: FILESYSTEM,ROCKSDB状态后端文件系统存储路径,例如:hdfs://ns1/dtInsight/flink180/checkpoints。 - * state.backend.incremental: ROCKSDB状态后端是否开启增量checkpoint,默认为true。 - * sql.env.parallelism: 默认并行度设置 - * sql.max.env.parallelism: 最大并行度设置 - * time.characteristic: 可选值[ProcessingTime|IngestionTime|EventTime] - * sql.checkpoint.interval: 设置了该参数表明开启checkpoint(ms) - * sql.checkpoint.mode: 可选值[EXACTLY_ONCE|AT_LEAST_ONCE] - * sql.checkpoint.timeout: 生成checkpoint的超时时间(ms) - * sql.max.concurrent.checkpoints: 最大并发生成checkpoint数 - * sql.checkpoint.cleanup.mode: 默认是不会将checkpoint存储到外部存储,[true(任务cancel之后会删除外部存储)|false(外部存储需要手动删除)] - * flinkCheckpointDataURI: 设置checkpoint的外部存储路径,根据实际的需求设定文件路径,hdfs://, file:// - * jobmanager.memory.mb: per_job模式下指定jobmanager的内存大小(单位MB, 默认值:768) - * taskmanager.memory.mb: per_job模式下指定taskmanager的内存大小(单位MB, 默认值:768) - * taskmanager.num: per_job模式下指定taskmanager的实例数(默认1) - * taskmanager.slots:per_job模式下指定每个taskmanager对应的slot数量(默认1) - * savePointPath:任务恢复点的路径(默认无) - * allowNonRestoredState:指示保存点是否允许非还原状态的标志(默认false) - * logLevel: 日志级别动态配置(默认info) - * [prometheus 相关参数](./prometheus.md) per_job可指定metric写入到外部监控组件,以prometheus pushgateway举例 - * async.side.clientShare:异步访问维表是否开启连接池共享,开启则 1.一个tm上多个task共享该池, 2.一个tm上多个url相同的维表单\多个task共享该池 (默认false) - * async.side.poolSize:连接池中连接的个数,上面参数为true才生效(默认5) - - -* **flinkconf** - * 描述:flink配置文件所在的目录(单机模式下不需要),如/hadoop/flink-1.10.0/conf - * 必选:否 - * 默认值:无 - -* **yarnconf** - * 描述:Hadoop配置文件(包括hdfs和yarn)所在的目录(单机模式下不需要),如/hadoop/etc/hadoop - * 必选:否 - * 默认值:无 - -* **flinkJarPath** - * 描述:yarnPer 模式提交需要指定本地的flink jar存放路径 - * 必选:否 - * 默认值:无 - -* **queue** - * 描述:yarnPer 模式下指定的yarn queue - * 必选:否 - * 默认值:default - -* **yarnSessionConf** - * 描述:yarn session 模式下指定的运行的一些参数,[可参考](https://ci.apache.org/projects/flink/flink-docs-release-1.8/ops/cli.html),目前只支持指定yid - * 必选:否 - * 默认值:{} - \ No newline at end of file diff --git a/docs/plugin/consoleSink.md b/docs/consoleSink.md similarity index 92% rename from docs/plugin/consoleSink.md rename to docs/consoleSink.md index 5a923236c..206d7faaa 100644 --- a/docs/plugin/consoleSink.md +++ b/docs/consoleSink.md @@ -20,7 +20,7 @@ CREATE TABLE tableName( |----|---| | tableName| 在 sql 中使用的名称;即注册到flink-table-env上的名称| | colName | 列名称| -| colType | 列类型 [colType支持的类型](../colType.md)| +| colType | 列类型 [colType支持的类型](colType.md)| ## 4.参数: diff --git a/docs/createView.md b/docs/createView.md index 5b923f180..6f81fa8cb 100644 --- a/docs/createView.md +++ b/docs/createView.md @@ -1,4 +1,4 @@ -## 语法 +##语法 ``` CREATE VIEW viewName [ (columnName[ , columnName]*) ] @@ -7,7 +7,7 @@ CREATE VIEW viewName [ (columnName[ , columnName]*) ]; INSERT INTO viewName queryStatement; ``` -## 样例 +##样例 ``` CREATE TABLE MyTable( name varchar, diff --git a/docs/demo.md b/docs/demo.md deleted file mode 100644 index 421ad6617..000000000 --- a/docs/demo.md +++ /dev/null @@ -1,83 +0,0 @@ -### 样例1: -注册自定义函数,并指定某一列作为eventTime; -kafkaSource join hbaseDim ==> hbaseOut - -``` -CREATE scala FUNCTION CHARACTER_LENGTH WITH com.dtstack.Kun; - -CREATE TABLE MyTable( - name varchar, - channel varchar, - pv int, - xctime bigint, - CHARACTER_LENGTH(channel) AS timeLeng //自定义的函数 - )WITH( - type ='kafka09', - bootstrapServers ='172.16.8.198:9092', - zookeeperQuorum ='172.16.8.198:2181/kafka', - offsetReset ='latest', - topic ='nbTest1', - parallelism ='1' - ); - -CREATE TABLE MyResult( - channel varchar, - pv varchar - )WITH( - type ='mysql', - url ='jdbc:mysql://172.16.8.104:3306/test?charset=utf8', - userName ='dtstack', - password ='abc123', - tableName ='pv2', - parallelism ='1' - ); - -CREATE TABLE workerinfo( - cast(logtime as TIMESTAMP) AS rtime, - cast(logtime) AS rtime - )WITH( - type ='hbase', - zookeeperQuorum ='rdos1:2181', - tableName ='workerinfo', - rowKey ='ce,de', - parallelism ='1', - zookeeperParent ='/hbase' - ); - -CREATE TABLE sideTable( - cf:name varchar as name, - cf:info varchar as info, - PRIMARY KEY(name), - PERIOD FOR SYSTEM_TIME //维表标识 - )WITH( - type ='hbase', - zookeeperQuorum ='rdos1:2181', - zookeeperParent ='/hbase', - tableName ='workerinfo', - cache ='LRU', - cacheSize ='10000', - cacheTTLMs ='60000', - parallelism ='1' - ); - -insert -into - MyResult - select - d.channel, - d.info - from - ( select - a.*,b.info - from - MyTable a - join - sideTable b - on a.channel=b.name - where - a.channel = 'xc2' - and a.pv=10 ) as d -``` - -### 创建视图demo: -[参考视图文档](docs/createView.md) diff --git a/docs/elasticsearchSink.md b/docs/elasticsearchSink.md new file mode 100644 index 000000000..69d69af75 --- /dev/null +++ b/docs/elasticsearchSink.md @@ -0,0 +1,52 @@ +## 1.格式: +``` +CREATE TABLE tableName( + colName colType, + bb INT + )WITH( + type ='elasticsearch', + address ='ip:port[,ip:port]', + cluster='clusterName', + estype ='esType', + index ='index', + id ='num[,num]', + parallelism ='1' + ) +``` +## 2.支持的版本 + ES5 + +## 3.表结构定义 + +|参数名称|含义| +|----|---| +|tableName|在 sql 中使用的名称;即注册到flink-table-env上的名称| +|colName|列名称| +|colType|列类型 [colType支持的类型](colType.md)| + +## 4.参数: +|参数名称|含义|是否必填|默认值| +|----|---|---|----| +|type|表明 输出表类型[mysq|hbase|elasticsearch]|是|| +|address | 连接ES Transport地址(tcp地址)|是|| +|cluster | ES 集群名称 |是|| +|index | 选择的ES上的index名称|是|| +|estype | 选择ES上的type名称|是|| +|id | 生成id的规则(当前是根据指定的字段pos获取字段信息,拼接生成id)|是|| +|parallelism | 并行度设置|否|1| + +## 5.样例: +``` +CREATE TABLE MyResult( + aa INT, + bb INT + )WITH( + type ='elasticsearch', + address ='172.16.10.47:9500', + cluster='es_47_menghan', + estype ='type1', + index ='xc_es_test', + id ='0,1', + parallelism ='1' + ) + ``` \ No newline at end of file diff --git a/docs/function.md b/docs/function.md deleted file mode 100644 index e272011d2..000000000 --- a/docs/function.md +++ /dev/null @@ -1,109 +0,0 @@ -## 支持UDF,UDTF,UDAT: - -### UDTF使用案例 - -1. cross join:左表的每一行数据都会关联上UDTF 产出的每一行数据,如果UDTF不产出任何数据,那么这1行不会输出。 -2. left join:左表的每一行数据都会关联上UDTF 产出的每一行数据,如果UDTF不产出任何数据,则这1行的UDTF的字段会用null值填充。 left join UDTF 语句后面必须接 on true参数。 - - -场景:将某个字段拆分为两个字段。 - -```$xslt - -create table function UDTFOneColumnToMultiColumn with cn.todd.flink180.udflib.UDTFOneColumnToMultiColumn; - -CREATE TABLE MyTable ( - userID VARCHAR , - eventType VARCHAR, - productID VARCHAR) -WITH ( - type = 'kafka11', - bootstrapServers = '172.16.8.107:9092', - zookeeperQuorum = '172.16.8.107:2181/kafka', - offsetReset = 'latest', - topic ='mqTest03', - topicIsPattern = 'false' -); - -CREATE TABLE MyTable1 ( - channel VARCHAR , - pv VARCHAR, - name VARCHAR) -WITH ( - type = 'kafka11', - bootstrapServers = '172.16.8.107:9092', - zookeeperQuorum = '172.16.8.107:2181/kafka', - offsetReset = 'latest', - topic ='mqTest01', - topicIsPattern = 'false' -); - -CREATE TABLE MyTable2 ( - userID VARCHAR, - eventType VARCHAR, - productID VARCHAR, - date1 VARCHAR, - time1 VARCHAR -) -WITH ( - type = 'console', - bootstrapServers = '172.16.8.107:9092', - zookeeperQuorum = '172.16.8.107:2181/kafka', - offsetReset = 'latest', - topic ='mqTest02', - topicIsPattern = 'false' -); - -## 视图使用UDTF ---create view udtf_table as --- select MyTable.userID,MyTable.eventType,MyTable.productID,date1,time1 - -- from MyTable LEFT JOIN lateral table(UDTFOneColumnToMultiColumn(productID)) - -- as T(date1,time1) on true; - - - - -insert - into - MyTable2 -select - userID,eventType,productID,date1,time1 -from - ( - select MyTable.userID,MyTable.eventType,MyTable.productID,date1,time1 - from MyTable ,lateral table(UDTFOneColumnToMultiColumn(productID)) as T(date1,time1)) as udtf_table; - -``` -一行转多列UDTFOneColumnToMultiColumn - -```$xslt -public class UDTFOneColumnToMultiColumn extends TableFunction { - public void eval(String value) { - String[] valueSplits = value.split("_"); - - //一行,两列 - Row row = new Row(2); - row.setField(0, valueSplits[0]); - row.setField(1, valueSplits[1]); - collect(row); - } - - @Override - public TypeInformation getResultType() { - return new RowTypeInfo(Types.STRING, Types.STRING); - } -} -``` - -输入输出: - - -输入: {"userID": "user_5", "eventType": "browse", "productID":"product_5"} - -输出: - - +--------+-----------+-----------+---------+-------+ - | userID | eventType | productID | date1 | time1 | - +--------+-----------+-----------+---------+-------+ - | user_5 | browse | product_5 | product | 5 | - +--------+-----------+-----------+---------+-------+ \ No newline at end of file diff --git a/docs/hbaseSide.md b/docs/hbaseSide.md new file mode 100644 index 000000000..0c4e545f9 --- /dev/null +++ b/docs/hbaseSide.md @@ -0,0 +1,73 @@ + +## 1.格式: +``` + CREATE TABLE tableName( + columnFamily:columnName type as alias, + ... + PRIMARY KEY(keyInfo), + PERIOD FOR SYSTEM_TIME + )WITH( + type ='hbase', + zookeeperQuorum ='ip:port', + zookeeperParent ='/hbase', + tableName ='tableNamae', + cache ='LRU', + cacheSize ='10000', + cacheTTLMs ='60000', + parallelism ='1', + partitionedJoin='false' + ); +``` +## 2.支持版本 + hbase2.0 + +## 3.表结构定义 + +|参数名称|含义| +|----|---| +| tableName | 注册到flink的表名称(可选填;不填默认和hbase对应的表名称相同)| +| columnFamily:columnName | hbase中的列族名称和列名称 | +| alias | hbase 中的列对应到flink中注册的列名称 | +| PERIOD FOR SYSTEM_TIME | 关键字表明该定义的表为维表信息| +| PRIMARY KEY(keyInfo) | 维表主键定义;hbase 维表rowkey的构造方式;可选择的构造包括 md5(alias + alias), '常量',也包括上述方式的自由组合 | + +## 3.参数 + +|参数名称|含义|是否必填|默认值| +|----|---|---|----| +| type | 表明维表的类型[hbase|mysql]|是|| +| zookeeperQuorum | hbase 的zk地址;格式ip:port[;ip:port]|是|| +| zookeeperParent | hbase 的zk parent路径|是|| +| tableName | hbase 的表名称|是|| +| cache | 维表缓存策略(NONE/LRU)|否|NONE| +| partitionedJoin | 是否在維表join之前先根据 設定的key 做一次keyby操作(可以減少维表的数据缓存量)|否|false| + +-------------- +> 缓存策略 + * NONE: 不做内存缓存 + * LRU: + * cacheSize: 缓存的条目数量 + * cacheTTLMs:缓存的过期时间(ms) + +## 4.样例 +``` +CREATE TABLE sideTable( + cf:name varchar as name, + cf:info int as info, + PRIMARY KEY(md5(name) + 'test'), + PERIOD FOR SYSTEM_TIME + )WITH( + type ='hbase', + zookeeperQuorum ='rdos1:2181', + zookeeperParent ='/hbase', + tableName ='workerinfo', + cache ='LRU', + cacheSize ='10000', + cacheTTLMs ='60000', + parallelism ='1', + partitionedJoin='true' + ); + +``` + + diff --git a/docs/hbaseSink.md b/docs/hbaseSink.md new file mode 100644 index 000000000..c6a15e766 --- /dev/null +++ b/docs/hbaseSink.md @@ -0,0 +1,55 @@ +## 1.格式: +``` +CREATE TABLE MyResult( + colFamily:colName colType, + ... + )WITH( + type ='hbase', + zookeeperQuorum ='ip:port[,ip:port]', + tableName ='tableName', + rowKey ='colFamily:colName[,colFamily:colName]', + parallelism ='1', + zookeeperParent ='/hbase' + ) + + +``` + +## 2.支持版本 +hbase2.0 + +## 3.表结构定义 + +|参数名称|含义| +|----|---| +| tableName | 在 sql 中使用的名称;即注册到flink-table-env上的名称 +| colFamily:colName | hbase中的列族名称和列名称 +| colType | 列类型 [colType支持的类型](colType.md) + +## 4.参数: + +|参数名称|含义|是否必填|默认值| +|----|---|---|-----| +|type | 表明 输出表类型[mysq|hbase|elasticsearch]|是|| +|zookeeperQuorum | hbase zk地址,多个直接用逗号隔开|是|| +|zookeeperParent | zkParent 路径|是|| +|tableName | 关联的hbase表名称|是|| +|rowKey | hbase的rowkey关联的列信息|是|| +|parallelism | 并行度设置|否|1| + + +## 5.样例: +``` +CREATE TABLE MyResult( + cf:channel varchar, + cf:pv BIGINT + )WITH( + type ='hbase', + zookeeperQuorum ='rdos1:2181', + tableName ='workerinfo', + rowKey ='cf:channel', + parallelism ='1', + zookeeperParent ='/hbase' + ) + + ``` \ No newline at end of file diff --git a/docs/images/streamsql_dd.jpg b/docs/images/streamsql_dd.jpg deleted file mode 100644 index 4a32461c1..000000000 Binary files a/docs/images/streamsql_dd.jpg and /dev/null differ diff --git a/docs/kafkaSource.md b/docs/kafkaSource.md new file mode 100644 index 000000000..580eda6b4 --- /dev/null +++ b/docs/kafkaSource.md @@ -0,0 +1,358 @@ +## 1.格式: +``` +数据现在支持json格式{"xx":"bb","cc":"dd"} + +CREATE TABLE tableName( + colName colType, + ... + function(colNameX) AS aliasName, + WATERMARK FOR colName AS withOffset( colName , delayTime ) + )WITH( + type ='kafka09', + kafka.bootstrap.servers ='ip:port,ip:port...', + kafka.zookeeper.quorum ='ip:port,ip:port/zkparent', + kafka.auto.offset.reset ='latest', + kafka.topic ='topicName', + parallelism ='parllNum', + --timezone='America/Los_Angeles', + timezone='Asia/Shanghai', + sourcedatatype ='json' #可不设置 + ); +``` + +## 2.支持的版本 + kafka08,kafka09,kafka10,kafka11及以上版本 + **kafka读取和写入的版本必须一致,否则会有兼容性错误。** + +## 3.表结构定义 + +|参数名称|含义| +|----|---| +| tableName | 在 sql 中使用的名称;即注册到flink-table-env上的名称| +| colName | 列名称| +| colType | 列类型 [colType支持的类型](colType.md)| +| function(colNameX) as aliasName | 支持在定义列信息的时候根据已有列类型生成新的列(函数可以使用系统函数和已经注册的UDF)| +| WATERMARK FOR colName AS withOffset( colName , delayTime ) | 标识输入流生的watermake生成规则,根据指定的colName(当前支持列的类型为Long | Timestamp) 和delayTime生成waterMark 同时会在注册表的使用附带上rowtime字段(如果未指定则默认添加proctime字段);注意:添加该标识的使用必须设置系统参数 time.characteristic:EventTime; delayTime: 数据最大延迟时间(ms)| + +## 4.参数: + +|参数名称|含义|是否必填|默认值| +|----|---|---|---| +|type | kafka09 | 是|kafka08、kafka09、kafka10、kafka11、kafka(对应kafka1.0及以上版本)| +|kafka.group.id | 需要读取的 groupId 名称|否|| +|kafka.bootstrap.servers | kafka bootstrap-server 地址信息(多个用逗号隔开)|是|| +|kafka.zookeeper.quorum | kafka zk地址信息(多个之间用逗号分隔)|是|| +|kafka.topic | 需要读取的 topic 名称|是|| +|patterntopic | topic是否是正则表达式格式(true|false) |否| false +|kafka.auto.offset.reset | 读取的topic 的offset初始位置[latest|earliest|指定offset值({"0":12312,"1":12321,"2":12312},{"partition_no":offset_value})]|否|latest| +|parallelism | 并行度设置|否|1| +|sourcedatatype | 数据类型|否|json| +|timezone|时区设置[timezone支持的参数](timeZone.md)|否|'Asia/Shanghai' +**kafka相关参数可以自定义,使用kafka.开头即可。** + +## 5.样例: +``` +CREATE TABLE MyTable( + name varchar, + channel varchar, + pv INT, + xctime bigint, + CHARACTER_LENGTH(channel) AS timeLeng + )WITH( + type ='kafka09', + kafka.bootstrap.servers ='172.16.8.198:9092', + kafka.zookeeper.quorum ='172.16.8.198:2181/kafka', + kafka.auto.offset.reset ='latest', + kafka.topic ='nbTest1,nbTest2,nbTest3', + --kafka.topic ='mqTest.*', + --patterntopic='true' + parallelism ='1', + sourcedatatype ='json' #可不设置 + ); +``` +## 6.支持嵌套json、数据类型字段解析 + +嵌套json解析示例 + +json: {"name":"tom", "obj":{"channel": "root"}, "pv": 4, "xctime":1572932485} +``` +CREATE TABLE MyTable( + name varchar, + obj.channel varchar as channel, + pv INT, + xctime bigint, + CHARACTER_LENGTH(channel) AS timeLeng + )WITH( + type ='kafka09', + bootstrapServers ='172.16.8.198:9092', + zookeeperQuorum ='172.16.8.198:2181/kafka', + offsetReset ='latest', + groupId='nbTest', + topic ='nbTest1,nbTest2,nbTest3', + --- topic ='mqTest.*', + ---topicIsPattern='true', + parallelism ='1' + ); +``` + +数组类型字段解析示例 + +json: {"name":"tom", "obj":{"channel": "root"}, "user": [{"pv": 4}, {"pv": 10}], "xctime":1572932485} +``` +CREATE TABLE MyTable( + name varchar, + obj.channel varchar as channel, + user[1].pv INT as pv, + xctime bigint, + CHARACTER_LENGTH(channel) AS timeLeng + )WITH( + type ='kafka09', + bootstrapServers ='172.16.8.198:9092', + zookeeperQuorum ='172.16.8.198:2181/kafka', + offsetReset ='latest', + groupId='nbTest', + topic ='nbTest1,nbTest2,nbTest3', + --- topic ='mqTest.*', + ---topicIsPattern='true', + parallelism ='1' + ); +``` +or + +json: {"name":"tom", "obj":{"channel": "root"}, "pv": [4, 7, 10], "xctime":1572932485} +``` +CREATE TABLE MyTable( + name varchar, + obj.channel varchar as channel, + pv[1] INT as pv, + xctime bigint, + CHARACTER_LENGTH(channel) AS timeLeng + )WITH( + type ='kafka09', + bootstrapServers ='172.16.8.198:9092', + zookeeperQuorum ='172.16.8.198:2181/kafka', + offsetReset ='latest', + groupId='nbTest', + topic ='nbTest1,nbTest2,nbTest3', + --- topic ='mqTest.*', + ---topicIsPattern='true', + parallelism ='1' + ); +``` +# 二、csv格式数据源 +根据字段分隔符进行数据分隔,按顺序匹配sql中配置的列。如数据分隔列数和sql中配置的列数相等直接匹配;如不同参照lengthcheckpolicy策略处理。 +## 1.参数: + +|参数名称|含义|是否必填|默认值| +|----|---|---|---| +|type | kafka09 | 是|| +|kafka.bootstrap.servers | kafka bootstrap-server 地址信息(多个用逗号隔开)|是|| +|kafka.zookeeper.quorum | kafka zk地址信息(多个之间用逗号分隔)|是|| +|kafka.topic | 需要读取的 topic 名称|是|| +|kafka.auto.offset.reset | 读取的topic 的offset初始位置[latest|earliest]|否|latest| +|parallelism | 并行度设置 |否|1| +|sourcedatatype | 数据类型|是 |csv| +|fielddelimiter | 字段分隔符|是 || +|lengthcheckpolicy | 单行字段条数检查策略 |否|可选,默认为SKIP,其它可选值为EXCEPTION、PAD。SKIP:字段数目不符合时跳过 。EXCEPTION:字段数目不符合时抛出异常。PAD:按顺序填充,不存在的置为null。| +**kafka相关参数可以自定义,使用kafka.开头即可。** + +## 2.样例: +``` +CREATE TABLE MyTable( + name varchar, + channel varchar, + pv INT, + xctime bigint, + CHARACTER_LENGTH(channel) AS timeLeng + )WITH( + type ='kafka09', + kafka.bootstrap.servers ='172.16.8.198:9092', + kafka.zookeeper.quorum ='172.16.8.198:2181/kafka', + kafka.auto.offset.reset ='latest', + kafka.topic ='nbTest1', + --kafka.topic ='mqTest.*', + --kafka.topicIsPattern='true' + parallelism ='1', + sourcedatatype ='csv', + fielddelimiter ='\|', + lengthcheckpolicy = 'PAD' + ); + ``` +# 三、text格式数据源UDF自定义拆分 +Kafka源表数据解析流程:Kafka Source Table -> UDTF ->Realtime Compute -> SINK。从Kakfa读入的数据,都是VARBINARY(二进制)格式,对读入的每条数据,都需要用UDTF将其解析成格式化数据。 + 与其他格式不同,本格式定义DDL必须与以下SQL一摸一样,表中的五个字段顺序务必保持一致: + +## 1. 定义源表,注意:kafka源表DDL字段必须与以下例子一模一样。WITH中参数可改。 +``` +create table kafka_stream( + _topic STRING, + _messageKey STRING, + _message STRING, + _partition INT, + _offset BIGINT, +) with ( + type ='kafka09', + kafka.bootstrap.servers ='172.16.8.198:9092', + kafka.zookeeper.quorum ='172.16.8.198:2181/kafka', + kafka.auto.offset.reset ='latest', + kafka.topic ='nbTest1', + parallelism ='1', + sourcedatatype='text' + ) +``` +## 2.参数: + +|参数名称|含义|是否必填|默认值| +|----|---|---|---| +|type | kafka09 | 是|| +|kafka.bootstrap.servers | kafka bootstrap-server 地址信息(多个用逗号隔开)|是|| +|kafka.zookeeper.quorum | kafka zk地址信息(多个之间用逗号分隔)|是|| +|kafka.topic | 需要读取的 topic 名称|是|| +|kafka.auto.offset.reset | 读取的topic 的offset初始位置[latest|earliest]|否|latest| +|parallelism | 并行度设置|否|1| +|sourcedatatype | 数据类型|否|text| +**kafka相关参数可以自定义,使用kafka.开头即可。** + +## 2.自定义: +从kafka读出的数据,需要进行窗口计算。 按照实时计算目前的设计,滚窗/滑窗等窗口操作,需要(且必须)在源表DDL上定义Watermark。Kafka源表比较特殊。如果要以kafka中message字段中的的Event Time进行窗口操作, +需要先从message字段,使用UDX解析出event time,才能定义watermark。 在kafka源表场景中,需要使用计算列。 假设,kafka中写入的数据如下: +2018-11-11 00:00:00|1|Anna|female整个计算流程为:Kafka SOURCE->UDTF->Realtime Compute->RDS SINK(单一分隔符可直接使用类csv格式模板,自定义适用于更复杂的数据类型,本说明只做参考) + +**SQL** +``` +-- 定义解析Kakfa message的UDTF + CREATE FUNCTION kafkapaser AS 'com.XXXX.kafkaUDTF'; + CREATE FUNCTION kafkaUDF AS 'com.XXXX.kafkaUDF'; + -- 定义源表,注意:kafka源表DDL字段必须与以下例子一模一样。WITH中参数可改。 + create table kafka_src ( + _topic STRING, + _messageKey STRING, + _message STRING, + _partition INT, + _offset BIGINT, + ctime AS TO_TIMESTAMP(kafkaUDF(_message)), -- 定义计算列,计算列可理解为占位符,源表中并没有这一列,其中的数据可经过下游计算得出。注意计算里的类型必须为timestamp才能在做watermark。 + watermark for ctime as withoffset(ctime,0) -- 在计算列上定义watermark + ) WITH ( + type = 'kafka010', -- Kafka Source类型,与Kafka版本强相关,目前支持的Kafka版本请参考本文档 + topic = 'test_kafka_topic', + ... + ); + create table rds_sink ( + name VARCHAR, + age INT, + grade VARCHAR, + updateTime TIMESTAMP + ) WITH( + type='mysql', + url='jdbc:mysql://localhost:3306/test', + tableName='test4', + userName='test', + password='XXXXXX' + ); + -- 使用UDTF,将二进制数据解析成格式化数据 + CREATE VIEW input_view ( + name, + age, + grade, + updateTime + ) AS + SELECT + COUNT(*) as cnt, + T.ctime, + T.order, + T.name, + T.sex + from + kafka_src as S, + LATERAL TABLE (kafkapaser _message)) as T ( + ctime, + order, + name, + sex + ) + Group BY T.sex, + TUMBLE(ctime, INTERVAL '1' MINUTE); + -- 对input_view中输出的数据做计算 + CREATE VIEW view2 ( + cnt, + sex + ) AS + SELECT + COUNT(*) as cnt, + T.sex + from + input_view + Group BY sex, TUMBLE(ctime, INTERVAL '1' MINUTE); + -- 使用解析出的格式化数据进行计算,并将结果输出到RDS中 + insert into rds_sink + SELECT + cnt,sex + from view2; + ``` +**UDF&UDTF** +``` +package com.XXXX; + import com.XXXX.fastjson.JSONObject; + import org.apache.flink.table.functions.TableFunction; + import org.apache.flink.table.types.DataType; + import org.apache.flink.table.types.DataTypes; + import org.apache.flink.types.Row; + import java.io.UnsupportedEncodingException; + /** + 以下例子解析输入Kafka中的JSON字符串,并将其格式化输出 + **/ + public class kafkaUDTF extends TableFunction { + public void eval(byte[] message) { + try { + // 读入一个二进制数据,并将其转换为String格式 + String msg = new String(message, "UTF-8"); + // 提取JSON Object中各字段 + String ctime = Timestamp.valueOf(data.split('\\|')[0]); + String order = data.split('\\|')[1]; + String name = data.split('\\|')[2]; + String sex = data.split('\\|')[3]; + // 将解析出的字段放到要输出的Row()对象 + Row row = new Row(4); + row.setField(0, ctime); + row.setField(1, age); + row.setField(2, grade); + row.setField(3, updateTime); + System.out.println("Kafka message str ==>" + row.toString()); + // 输出一行 + collect(row); + } catch (ClassCastException e) { + System.out.println("Input data format error. Input data " + msg + "is not json string"); + } + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + } + @Override + // 如果返回值是Row,就必须重载实现这个方法,显式地告诉系统返回的字段类型 + // 定义输出Row()对象的字段类型 + public DataType getResultType(Object[] arguments, Class[] argTypes) { + return DataTypes.createRowType(DataTypes.TIMESTAMP,DataTypes.STRING, DataTypes.Integer, DataTypes.STRING,DataTypes.STRING); + } + } + + package com.dp58; + package com.dp58.sql.udx; + import org.apache.flink.table.functions.FunctionContext; + import org.apache.flink.table.functions.ScalarFunction; + public class KafkaUDF extends ScalarFunction { + // 可选,open方法可以不写 + // 需要import org.apache.flink.table.functions.FunctionContext; + public String eval(byte[] message) { + // 读入一个二进制数据,并将其转换为String格式 + String msg = new String(message, "UTF-8"); + return msg.split('\\|')[0]; + } + public long eval(String b, String c) { + return eval(b) + eval(c); + } + //可选,close方法可以不写 + @Override + public void close() { + } + } + ``` diff --git a/docs/kuduSide.md b/docs/kuduSide.md new file mode 100644 index 000000000..5a73596ad --- /dev/null +++ b/docs/kuduSide.md @@ -0,0 +1,127 @@ + +## 1.格式: +All: +``` +create table sideTable( + id int, + tablename1 VARCHAR, + PRIMARY KEY(id), + PERIOD FOR SYSTEM_TIME + )WITH( + type='kudu', + kuduMasters ='ip1,ip2,ip3', + tableName ='impala::default.testSide', + cache ='ALL', + primaryKey='id,xx', + lowerBoundPrimaryKey='10,xx', + upperBoundPrimaryKey='15,xx', + workerCount='1', + defaultOperationTimeoutMs='600000', + defaultSocketReadTimeoutMs='6000000', + batchSizeBytes='100000000', + limitNum='1000', + isFaultTolerant='false', + partitionedJoin='false' + ); +``` +LRU: +``` +create table sideTable( + id int, + tablename1 VARCHAR, + PRIMARY KEY(id), + PERIOD FOR SYSTEM_TIME + )WITH( + type='kudu', + kuduMasters ='ip1,ip2,ip3', + tableName ='impala::default.testSide', + cache ='LRU', + workerCount='1', + defaultOperationTimeoutMs='600000', + defaultSocketReadTimeoutMs='6000000', + batchSizeBytes='100000000', + limitNum='1000', + isFaultTolerant='false', + partitionedJoin='false' + ); + ``` + +## 2.支持版本 +kudu 1.9.0+cdh6.2.0 + +## 3.表结构定义 + + |参数名称|含义| + |----|---| + | tableName | 注册到flink的表名称(可选填;不填默认和hbase对应的表名称相同)| + | colName | 列名称| + | colType | 列类型 [colType支持的类型](colType.md)| + | PERIOD FOR SYSTEM_TIME | 关键字表明该定义的表为维表信息| + | PRIMARY KEY(keyInfo) | 维表主键定义;多个列之间用逗号隔开| + +## 3.参数 + + +|参数名称|含义|是否必填|默认值| +|----|---|---|-----| +|type | 表明维表的类型[hbase|mysql|kudu]|是|| +| kuduMasters | kudu master节点的地址;格式ip[ip,ip2]|是|| +| tableName | kudu 的表名称|是|| +| workerCount | 工作线程数 |否|| +| defaultOperationTimeoutMs | 写入操作超时时间 |否|| +| defaultSocketReadTimeoutMs | socket读取超时时间 |否|| +| primaryKey | 需要过滤的主键 ALL模式独有 |否|| +| lowerBoundPrimaryKey | 需要过滤的主键的最小值 ALL模式独有 |否|| +| upperBoundPrimaryKey | 需要过滤的主键的最大值(不包含) ALL模式独有 |否|| +| workerCount | 工作线程数 |否|| +| defaultOperationTimeoutMs | 写入操作超时时间 |否|| +| defaultSocketReadTimeoutMs | socket读取超时时间 |否|| +| batchSizeBytes |返回数据的大小 | 否|| +| limitNum |返回数据的条数 | 否|| +| isFaultTolerant |查询是否容错 查询失败是否扫描第二个副本 默认false 容错 | 否|| +| cache | 维表缓存策略(NONE/LRU/ALL)|否|NONE| +| partitionedJoin | 是否在維表join之前先根据 設定的key 做一次keyby操作(可以減少维表的数据缓存量)|否|false| + + +-------------- +> 缓存策略 + * NONE: 不做内存缓存 + * LRU: + * cacheSize: 缓存的条目数量 + * cacheTTLMs:缓存的过期时间(ms) + +## 4.样例 +All: +``` +create table sideTable( + id int, + tablename1 VARCHAR, + PRIMARY KEY(id), + PERIOD FOR SYSTEM_TIME + )WITH( + type='kudu', + kuduMasters ='ip1,ip2,ip3', + tableName ='impala::default.testSide', + cache ='ALL', + primaryKey='id,xx', + lowerBoundPrimaryKey='10,xx', + upperBoundPrimaryKey='15,xx', + partitionedJoin='false' + ); +``` +LRU: +``` +create table sideTable( + id int, + tablename1 VARCHAR, + PRIMARY KEY(id), + PERIOD FOR SYSTEM_TIME + )WITH( + type='kudu', + kuduMasters ='ip1,ip2,ip3', + tableName ='impala::default.testSide', + cache ='LRU', + partitionedJoin='false' + ); + ``` + diff --git a/docs/kuduSink.md b/docs/kuduSink.md new file mode 100644 index 000000000..990dfdd7d --- /dev/null +++ b/docs/kuduSink.md @@ -0,0 +1,62 @@ +## 1.格式: +``` +CREATE TABLE tableName( + colName colType, + ... + colNameX colType + )WITH( + type ='kudu', + kuduMasters ='ip1,ip2,ip3', + tableName ='impala::default.test', + writeMode='upsert', + workerCount='1', + defaultOperationTimeoutMs='600000', + defaultSocketReadTimeoutMs='6000000', + parallelism ='parllNum' + ); + + +``` + +## 2.支持版本 +kudu 1.9.0+cdh6.2.0 + +## 3.表结构定义 + +|参数名称|含义| +|----|---| +| tableName | 在 sql 中使用的名称;即注册到flink-table-env上的名称 +| colName | 列名称,redis中存储为 表名:主键名:主键值:列名]| +| colType | 列类型 [colType支持的类型](colType.md)| + + +## 4.参数: + +|参数名称|含义|是否必填|默认值| +|----|---|---|-----| +|type | 表名 输出表类型[mysq|hbase|elasticsearch|redis|kudu]|是|| +| kuduMasters | kudu master节点的地址;格式ip[ip,ip2]|是|| +| tableName | kudu 的表名称|是|| +| writeMode | 写入kudu的模式 insert|update|upsert |否 |upsert +| workerCount | 工作线程数 |否| +| defaultOperationTimeoutMs | 写入操作超时时间 |否| +| defaultSocketReadTimeoutMs | socket读取超时时间 |否| +|parallelism | 并行度设置|否|1| + + +## 5.样例: +``` +CREATE TABLE MyResult( + id int, + title VARCHAR, + amount decimal, + tablename1 VARCHAR + )WITH( + type ='kudu', + kuduMasters ='localhost1,localhost2,localhost3', + tableName ='impala::default.test', + writeMode='upsert', + parallelism ='1' + ); + + ``` \ No newline at end of file diff --git a/docs/mongoSide.md b/docs/mongoSide.md new file mode 100644 index 000000000..db557f441 --- /dev/null +++ b/docs/mongoSide.md @@ -0,0 +1,78 @@ + +## 1.格式: +``` + CREATE TABLE tableName( + colName cloType, + ... + PRIMARY KEY(keyInfo), + PERIOD FOR SYSTEM_TIME + )WITH( + type ='mongo', + address ='ip:port[,ip:port]', + userName='dbUserName', + password='dbPwd', + tableName='tableName', + database='database', + cache ='LRU', + cacheSize ='10000', + cacheTTLMs ='60000', + parallelism ='1', + partitionedJoin='false' + ); +``` + +# 2.支持版本 + mongo-3.8.2 + +## 3.表结构定义 + + |参数名称|含义| + |----|---| + | tableName | 注册到flink的表名称(可选填;不填默认和hbase对应的表名称相同)| + | colName | 列名称| + | colType | 列类型 [colType支持的类型](colType.md)| + | PERIOD FOR SYSTEM_TIME | 关键字表明该定义的表为维表信息| + | PRIMARY KEY(keyInfo) | 维表主键定义;多个列之间用逗号隔开| + +## 4.参数 + + |参数名称|含义|是否必填|默认值| + |----|---|---|----| + | type |表明 输出表类型 mongo|是|| + | address | 连接mongo数据库 jdbcUrl |是|| + | userName | mongo连接用户名|否|| + | password | mongo连接密码|否|| + | tableName | mongo表名称|是|| + | database | mongo表名称|是|| + | cache | 维表缓存策略(NONE/LRU)|否|NONE| + | partitionedJoin | 是否在維表join之前先根据 設定的key 做一次keyby操作(可以減少维表的数据缓存量)|否|false| + + ---------- + > 缓存策略 + * NONE: 不做内存缓存 + * LRU: + * cacheSize: 缓存的条目数量 + * cacheTTLMs:缓存的过期时间(ms) + + +## 5.样例 +``` +create table sideTable( + CHANNEL varchar, + XCCOUNT int, + PRIMARY KEY(channel), + PERIOD FOR SYSTEM_TIME + )WITH( + type ='mongo', + address ='172.21.32.1:27017,172.21.32.1:27017', + database ='test', + tableName ='sidetest', + cache ='LRU', + parallelism ='1', + partitionedJoin='false' + ); + + +``` + + diff --git a/docs/mongoSink.md b/docs/mongoSink.md new file mode 100644 index 000000000..b0f916aab --- /dev/null +++ b/docs/mongoSink.md @@ -0,0 +1,56 @@ +## 1.格式: +``` +CREATE TABLE tableName( + colName colType, + ... + colNameX colType + )WITH( + type ='mongo', + address ='ip:port[,ip:port]', + userName ='userName', + password ='pwd', + database ='databaseName', + tableName ='tableName', + parallelism ='parllNum' + ); + +``` + +## 2.支持版本 + mongo-3.8.2 + +## 3.表结构定义 + +|参数名称|含义| +|----|---| +| tableName| 在 sql 中使用的名称;即注册到flink-table-env上的名称| +| colName | 列名称| +| colType | 列类型 [colType支持的类型](colType.md)| + +## 4.参数: + +|参数名称|含义|是否必填|默认值| +|----|----|----|----| +|type |表明 输出表类型 mongo|是|| +|address | 连接mongo数据库 jdbcUrl |是|| +|userName | mongo连接用户名|否|| +|password | mongo连接密码|否|| +|tableName | mongo表名称|是|| +|database | mongo表名称|是|| +|parallelism | 并行度设置|否|1| + +## 5.样例: +``` +CREATE TABLE MyResult( + channel VARCHAR, + pv VARCHAR + )WITH( + type ='mongo', + address ='172.21.32.1:27017,172.21.32.1:27017', + userName ='dtstack', + password ='abc123', + database ='test', + tableName ='pv', + parallelism ='1' + ) + ``` \ No newline at end of file diff --git a/docs/plugin/polardbSide.md b/docs/mysqlSide.md similarity index 78% rename from docs/plugin/polardbSide.md rename to docs/mysqlSide.md index eaef0acb9..f0eb16090 100644 --- a/docs/plugin/polardbSide.md +++ b/docs/mysqlSide.md @@ -1,3 +1,4 @@ + ## 1.格式: ``` CREATE TABLE tableName( @@ -6,7 +7,7 @@ PRIMARY KEY(keyInfo), PERIOD FOR SYSTEM_TIME )WITH( - type='polardb', + type='mysql', url='jdbcUrl', userName='dbUserName', password='dbPwd', @@ -20,15 +21,15 @@ ``` # 2.支持版本 - mysql-8.0.16 + mysql-5.6.35 ## 3.表结构定义 |参数名称|含义| |----|---| - | tableName | polardb表名称| + | tableName | mysql表名称| | colName | 列名称| - | colType | 列类型 [colType支持的类型](../colType.md)| + | colType | 列类型 [colType支持的类型](colType.md)| | PERIOD FOR SYSTEM_TIME | 关键字表明该定义的表为维表信息| | PRIMARY KEY(keyInfo) | 维表主键定义;多个列之间用逗号隔开| @@ -36,11 +37,12 @@ |参数名称|含义|是否必填|默认值| |----|---|---|----| - | type | 表明维表的类型 polardb |是|| - | url | 连接polardb数据库 jdbcUrl |是|| - | userName | ploardb连接用户名 |是|| - | password | ploardb连接密码|是|| - | tableName | ploardb表名称|是|| + | type | 表明维表的类型 mysql |是|| + | url | 连接mysql数据库 jdbcUrl |是|| + | userName | mysql连接用户名 |是|| + | password | mysql连接密码|是|| + | tableName | mysql表名称|是|| + | tableName | mysql 的表名称|是|| | cache | 维表缓存策略(NONE/LRU)|否|NONE| | partitionedJoin | 是否在維表join之前先根据 設定的key 做一次keyby操作(可以減少维表的数据缓存量)|否|false| @@ -62,8 +64,8 @@ create table sideTable( PRIMARY KEY(channel), PERIOD FOR SYSTEM_TIME )WITH( - type='polardb', - url='jdbc:mysql://xxx.xxx.xxx:3306/test?charset=utf8', + type='mysql', + url='jdbc:mysql://172.16.8.104:3306/test?charset=utf8', userName='dtstack', password='abc123', tableName='sidetest', @@ -76,4 +78,8 @@ create table sideTable( parallelism ='1', partitionedJoin='false' ); - ``` \ No newline at end of file + + +``` + + diff --git a/docs/plugin/polardbSink.md b/docs/mysqlSink.md similarity index 59% rename from docs/plugin/polardbSink.md rename to docs/mysqlSink.md index 4a17b72c6..3218f9371 100644 --- a/docs/plugin/polardbSink.md +++ b/docs/mysqlSink.md @@ -5,7 +5,7 @@ CREATE TABLE tableName( ... colNameX colType )WITH( - type ='polardb', + type ='mysql', url ='jdbcUrl', userName ='userName', password ='pwd', @@ -16,25 +16,25 @@ CREATE TABLE tableName( ``` ## 2.支持版本 - mysql-8.0.16 + mysql-5.6.35 ## 3.表结构定义 |参数名称|含义| |----|---| -| tableName| polardb表名称| +| tableName| mysql表名称| | colName | 列名称| -| colType | 列类型 [colType支持的类型](../colType.md)| +| colType | 列类型 [colType支持的类型](colType.md)| ## 4.参数: |参数名称|含义|是否必填|默认值| |----|----|----|----| -|type |表名 输出表类型 polardb|是|| -|url | 连接polardb数据库 jdbcUrl |是|| -|userName | polardb连接用户名 |是|| -| password | polardb连接密码|是|| -| tableName | polardb表名称|是|| +|type |表名 输出表类型[mysq|hbase|elasticsearch]|是|| +|url | 连接mysql数据库 jdbcUrl |是|| +|userName | mysql连接用户名 |是|| +| password | mysql连接密码|是|| +| tableName | mysql表名称|是|| | parallelism | 并行度设置|否|1| ## 5.样例: @@ -43,11 +43,11 @@ CREATE TABLE MyResult( channel VARCHAR, pv VARCHAR )WITH( - type ='polardb', - url ='jdbc:mysql://xxx.xxx.xxx:3306/test?charset=utf8', + type ='mysql', + url ='jdbc:mysql://172.16.8.104:3306/test?charset=utf8', userName ='dtstack', password ='abc123', tableName ='pv2', parallelism ='1' - ); + ) ``` \ No newline at end of file diff --git a/docs/newMetric.md b/docs/newMetric.md deleted file mode 100644 index 771689e5f..000000000 --- a/docs/newMetric.md +++ /dev/null @@ -1,32 +0,0 @@ -### 1. 自定义的性能指标(新增) - -### 开启prometheus 需要设置的 confProp 参数 -* metrics.reporter.promgateway.class: org.apache.flink.metrics.prometheus.PrometheusPushGatewayReporter -* metrics.reporter.promgateway.host: prometheus pushgateway的地址 -* metrics.reporter.promgateway.port:prometheus pushgateway的端口 -* metrics.reporter.promgateway.jobName: 实例名称 -* metrics.reporter.promgateway.randomJobNameSuffix: 是否在实例名称后面添加随机字符串(默认:true) -* metrics.reporter.promgateway.deleteOnShutdown: 是否在停止的时候删除数据(默认false) - -#### kafka插件 -* 业务延迟: flink_taskmanager_job_task_operator_dtEventDelay(单位s) - 数据本身的时间和进入flink的当前时间的差值. - -* 各个输入源的脏数据:flink_taskmanager_job_task_operator_dtDirtyData - 从kafka获取的数据解析失败的视为脏数据 - -* 各Source的数据输入TPS: flink_taskmanager_job_task_operator_dtNumRecordsInRate - kafka接受的记录数(未解析前)/s - -* 各Source的数据输入RPS: flink_taskmanager_job_task_operator_dtNumRecordsInResolveRate - kafka接受的记录数(解析后)/s - -* 各Source的数据输入BPS: flink_taskmanager_job_task_operator_dtNumBytesInRate - kafka接受的字节数/s - -* Kafka作为输入源的各个分区的延迟数: flink_taskmanager_job_task_operator_topic_partition_dtTopicPartitionLag - 当前kafka10,kafka11有采集该指标 - -* 各个输出源RPS: flink_taskmanager_job_task_operator_dtNumRecordsOutRate - 写入的外部记录数/s - \ No newline at end of file diff --git a/docs/oracleSide.md b/docs/oracleSide.md new file mode 100644 index 000000000..74fc56680 --- /dev/null +++ b/docs/oracleSide.md @@ -0,0 +1,85 @@ + +## 1.格式: +``` + CREATE TABLE tableName( + colName cloType, + ... + PRIMARY KEY(keyInfo), + PERIOD FOR SYSTEM_TIME + )WITH( + type='oracle', + url='jdbcUrl', + userName='dbUserName', + password='dbPwd', + tableName='tableName', + cache ='LRU', + schema = 'MQTEST', + parallelism ='1', + partitionedJoin='false' + ); +``` + +# 2.支持版本 + 10g 11g + +## 3.表结构定义 + + |参数名称|含义| + |----|---| + | tableName | oracle表名称| + | colName | 列名称| + | colType | 列类型 [colType支持的类型](colType.md)| + | PERIOD FOR SYSTEM_TIME | 关键字表明该定义的表为维表信息| + | PRIMARY KEY(keyInfo) | 维表主键定义;多个列之间用逗号隔开| + +## 4.参数 + + |参数名称|含义|是否必填|默认值| + |----|---|---|----| + | type | 表明维表的类型 oracle |是|| + | url | 连接oracle数据库 jdbcUrl |是|| + | userName | oracle连接用户名 |是|| + | password | oracle连接密码|是|| + | tableName | oracle表名称|是|| + | schema | oracle 的schema|否|当前登录用户| + | cache | 维表缓存策略(NONE/LRU)|否|NONE| + | partitionedJoin | 是否在維表join之前先根据 設定的key 做一次keyby操作(可以減少维表的数据缓存量)|否|false| + + ---------- + > 缓存策略 + * NONE: 不做内存缓存 + * LRU: + * cacheSize: 缓存的条目数量 + * cacheTTLMs:缓存的过期时间(ms) + * cacheMode: (unordered|ordered)异步加载是有序还是无序,默认有序。 + * asyncCapacity:异步请求容量,默认1000 + * asyncTimeout:异步请求超时时间,默认10000毫秒 + +## 5.样例 +``` +create table sideTable( + channel varchar, + xccount int, + PRIMARY KEY(channel), + PERIOD FOR SYSTEM_TIME + )WITH( + type='oracle', + url='jdbc:oracle:thin:@xx.xx.xx.xx:1521:orcl', + userName='xx', + password='xx', + tableName='sidetest', + cache ='LRU', + cacheSize ='10000', + cacheTTLMs ='60000', + cacheMode='unordered', + asyncCapacity='1000', + asyncTimeout='10000' + parallelism ='1', + partitionedJoin='false', + schema = 'MQTEST' + ); + + +``` + + diff --git a/docs/oracleSink.md b/docs/oracleSink.md new file mode 100644 index 000000000..47ddd8371 --- /dev/null +++ b/docs/oracleSink.md @@ -0,0 +1,55 @@ +## 1.格式: +``` +CREATE TABLE tableName( + colName colType, + ... + colNameX colType + )WITH( + type ='oracle', + url ='jdbcUrl', + userName ='userName', + password ='pwd', + tableName ='tableName', + parallelism ='parllNum' + ); + +``` + +## 2.支持版本 + 10g 11g + +## 3.表结构定义 + +|参数名称|含义| +|----|---| +| tableName| oracle表名称| +| colName | 列名称| +| colType | 列类型 [colType支持的类型](colType.md)| + +## 4.参数: + +|参数名称|含义|是否必填|默认值| +|----|----|----|----| +|type |表名 输出表类型[mysq|hbase|elasticsearch|oracle]|是|| +|url | 连接oracle数据库 jdbcUrl |是|| +|userName | oracle连接用户名 |是|| +| password | oracle连接密码|是|| +| tableName | oracle表名称|是|| +| schema | oracle 的schema|否|当前登录用户| +| parallelism | 并行度设置|否|1| + +## 5.样例: +``` +CREATE TABLE MyResult( + channel VARCHAR, + pv VARCHAR + )WITH( + type ='oracle', + url ='jdbc:oracle:thin:@xx.xx.xx.xx:1521:orcl', + userName ='dtstack', + password ='abc123', + tableName ='pv2', + schema = 'MQTEST', + parallelism ='1' + ) + ``` \ No newline at end of file diff --git a/docs/plugin/cassandraSide.md b/docs/plugin/cassandraSide.md deleted file mode 100644 index 048caed62..000000000 --- a/docs/plugin/cassandraSide.md +++ /dev/null @@ -1,176 +0,0 @@ - -## 1.格式: - - 通过建表语句中的` PERIOD FOR SYSTEM_TIME`将表标识为维表,其中`PRIMARY KEY(keyInfo)`中的keyInfo,表示用来和源表进行关联的字段, - 维表JOIN的条件必须与`keyInfo`字段一致。 -``` - CREATE TABLE tableName( - colName cloType, - ... - PRIMARY KEY(keyInfo), - PERIOD FOR SYSTEM_TIME - )WITH( - type ='cassandra', - address ='ip:port[,ip:port]', - userNae='dbUserName', - password='dbPwd', - tableName='tableName', - database='database', - cache ='LRU', - cacheSize ='10000', - cacheTTLMs ='60000', - parallelism ='1', - partitionedJoin='false' - ); -``` - -# 2.支持版本 - cassandra-3.x - -## 3.表结构定义 - - |参数名称|含义| - |----|---| - | tableName | 注册到flink的表名称(可选填;不填默认和cassandra对应的表名称相同)| - | colName | 列名称| - | colType | 列类型| - | PERIOD FOR SYSTEM_TIME | 关键字表明该定义的表为维表信息| - | PRIMARY KEY(keyInfo) | 维表主键定义;多个列之间用逗号隔开| - -## 4.参数 - - |参数名称|含义|是否必填|默认值| - |----|---|---|----| - | type |表明 输出表类型 cassandra|是|| - | address | 连接cassandra数据库 jdbcUrl |是|| - | userName | cassandra连接用户名|否|| - | password | cassandra连接密码|否|| - | tableName | cassandra表名称|是|| - | database | cassandra表名称|是|| - | cache | 维表缓存策略(NONE/LRU)|否|NONE| - | partitionedJoin | 是否在維表join之前先根据 設定的key 做一次keyby操作(可以減少维表的数据缓存量)|否|false| - | maxRequestsPerConnection | 每个连接允许的并发请求数|否|1| - | coreConnectionsPerHost | 每台主机连接的核心数|否|8| - | maxConnectionsPerHost | Cassandra集群里的每个机器都最多连接数|否|32768| - | maxQueueSize | Cassandra队列大小|否|100000| - | readTimeoutMillis | Cassandra读超时|否|60000| - | connectTimeoutMillis | Cassandra连接超时|否|60000| - | poolTimeoutMillis | Cassandra线程池超时|否|60000| - - ---------- - > 缓存策略 -- NONE:不做内存缓存。每条流数据触发一次维表查询操作。 -- ALL: 任务启动时,一次性加载所有数据到内存,并进行缓存。适用于维表数据量较小的情况。 -- LRU: 任务执行时,根据维表关联条件使用异步算子加载维表数据,并进行缓存。 - - -## 5.维表定义样例 - -### ALL全量维表定义 -``` -CREATE TABLE sideTable( - id bigint, - school varchar, - home varchar, - PRIMARY KEY(id), - PERIOD FOR SYSTEM_TIME -)WITH( - type='mysql', - url='jdbc:mysql://172.16.8.109:3306/tiezhu', - userName='dtstack', - password='abc123', - tableName='stressTest', - cache='ALL', - parallelism='1' -); -``` -### LRU异步维表定义 -``` -CREATE TABLE sideTable( - id bigint, - message varchar, - PRIMARY KEY(id), - PERIOD FOR SYSTEM_TIME -)WITH( - type ='cassandra', - address ='192.168.80.106:9042, 192.168.80.107:9042', - database ='tiezhu', - tableName ='stu', - userName='cassandra', - password='cassandra', - cache ='LRU', - parallelism ='1', - partitionedJoin='false' -); -``` -## 6.完整样例 -``` -CREATE TABLE MyTable( - id bigint, - name varchar, - address varchar -)WITH( - type = 'kafka10', - bootstrapServers = '172.16.101.224:9092', - zookeeperQuorm = '172.16.100.188:2181/kafka', - offsetReset = 'latest', - topic = 'tiezhu_test_in2', - timezone = 'Asia/Shanghai', - topicIsPattern = 'false', - parallelism = '1' -); - -CREATE TABLE sideTable( - id bigint, - message varchar, - PRIMARY KEY(id), - PERIOD FOR SYSTEM_TIME -)WITH( - type ='cassandra', - address ='192.168.80.106:9042, 192.168.80.107:9042', - database ='tiezhu', - tableName ='stu', - userName='cassandra', - password='cassandra', - cache ='LRU', - parallelism ='1', - partitionedJoin='false' -); - -CREATE TABLE MyResult( - id bigint, - name varchar, - address varchar, - message varchar - )WITH( - type ='cassandra', - address ='192.168.80.106:9042,192.168.80.107:9042', - userName='cassandra', - password='cassandra', - database ='tiezhu', - tableName ='stu_out', - parallelism ='1' -); - -insert -into - MyResult - select - t1.id AS id, - t1.name AS name, - t1.address AS address, - t2.message AS message - from - ( - select - id, - name, - address - from - MyTable - ) t1 - join sideTable t2 - on t1.id = t2.id; -``` - - diff --git a/docs/plugin/cassandraSink.md b/docs/plugin/cassandraSink.md deleted file mode 100644 index a4ffaf818..000000000 --- a/docs/plugin/cassandraSink.md +++ /dev/null @@ -1,150 +0,0 @@ -## 1.格式: -``` -CREATE TABLE tableName( - colName colType, - ... - colNameX colType - )WITH( - type ='cassandra', - address ='ip:port[,ip:port]', - userName ='userName', - password ='pwd', - database ='databaseName', - tableName ='tableName', - parallelism ='parllNum' - ); - -``` - -## 2.支持版本 - cassandra-3.x - -## 3.表结构定义 - -|参数名称|含义| -|----|---| -| tableName| 在 sql 中使用的名称;即注册到flink-table-env上的名称| -| colName | 列名称| -| colType | 列类型 [colType支持的类型](../colType.md)| - -## 4.参数 - -|参数名称|含义|是否必填|默认值| -|----|----|----|----| -|type |表明 输出表类型 cassandra|是|| -|address | 连接cassandra数据库 jdbcUrl |是|| -|userName | cassandra连接用户名|否|| -|password | cassandra连接密码|否|| -|tableName | cassandra表名称|是|| -|database | cassandra表名称|是|| -|parallelism | 并行度设置|否|1| -| maxRequestsPerConnection | 每个连接允许的并发请求数|否|1| -| coreConnectionsPerHost | 每台主机连接的核心数|否|8| -| maxConnectionsPerHost | Cassandra集群里的每个机器都最多连接数|否|32768| -| maxQueueSize | Cassandra队列大小|否|100000| -| readTimeoutMillis | Cassandra读超时|否|60000| -| connectTimeoutMillis | Cassandra连接超时|否|60000| -| poolTimeoutMillis | Cassandra线程池超时|否|60000| - -## 5.完整样例: -``` -CREATE TABLE MyTable( - id bigint, - name varchar, - address varchar -)WITH( - type = 'kafka10', - bootstrapServers = '172.16.101.224:9092', - zookeeperQuorm = '172.16.100.188:2181/kafka', - offsetReset = 'latest', - topic = 'tiezhu_test_in2', - timezone = 'Asia/Shanghai', - topicIsPattern = 'false', - parallelism = '1' -); - -CREATE TABLE sideTable( - id bigint, - message varchar, - PRIMARY KEY(id), - PERIOD FOR SYSTEM_TIME -)WITH( - type ='cassandra', - address ='192.168.80.106:9042, 192.168.80.107:9042', - database ='tiezhu', - tableName ='stu', - userName='cassandra', - password='cassandra', - cache ='LRU', - parallelism ='1', - partitionedJoin='false' -); - -CREATE TABLE MyResult( - id bigint, - name varchar, - address varchar, - message varchar - )WITH( - type ='cassandra', - address ='192.168.80.106:9042,192.168.80.107:9042', - userName='cassandra', - password='cassandra', - database ='tiezhu', - tableName ='stu_out', - parallelism ='1' -); - -insert -into - MyResult - select - t1.id AS id, - t1.name AS name, - t1.address AS address, - t2.message AS message - from - ( - select - id, - name, - address - from - MyTable - ) t1 - join sideTable t2 - on t1.id = t2.id; - ``` -### 6.结果表数据展示 -``` -cqlsh:tiezhu> desc stu_out - -CREATE TABLE tiezhu.stu_out ( - id int PRIMARY KEY, - address text, - message text, - name text -) WITH bloom_filter_fp_chance = 0.01 - AND caching = {'keys': 'ALL', 'rows_per_partition': 'NONE'} - AND comment = '' - AND compaction = {'class': 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy', 'max_threshold': '32', 'min_threshold': '4'} - AND compression = {'chunk_length_in_kb': '64', 'class': 'org.apache.cassandra.io.compress.LZ4Compressor'} - AND crc_check_chance = 1.0 - AND dclocal_read_repair_chance = 0.1 - AND default_time_to_live = 0 - AND gc_grace_seconds = 864000 - AND max_index_interval = 2048 - AND memtable_flush_period_in_ms = 0 - AND min_index_interval = 128 - AND read_repair_chance = 0.0 - AND speculative_retry = '99PERCENTILE'; - - -cqlsh:tiezhu> select * from stu_out limit 1; - - id | address | message | name -----+------------+------------------+---------- - 23 | hangzhou23 | flinkStreamSql23 | tiezhu23 - -(1 rows) -``` \ No newline at end of file diff --git a/docs/plugin/clickhouseSide.md b/docs/plugin/clickhouseSide.md deleted file mode 100644 index c41226973..000000000 --- a/docs/plugin/clickhouseSide.md +++ /dev/null @@ -1,155 +0,0 @@ -## 1.格式: - -通过建表语句中的` PERIOD FOR SYSTEM_TIME`将表标识为维表,其中`PRIMARY KEY(keyInfo)`中的keyInfo,表示用来和源表进行关联的字段, - 维表JOIN的条件必须与`keyInfo`字段一致。 - -```sql - CREATE TABLE tableName( - colName cloType, - ... - PRIMARY KEY(keyInfo), - PERIOD FOR SYSTEM_TIME - )WITH( - type='clickhouse', - url='jdbcUrl', - userName='dbUserName', - password='dbPwd', - tableName='tableName', - cache ='LRU', - cacheSize ='10000', - cacheTTLMs ='60000', - parallelism ='1', - partitionedJoin='false' - ); -``` - -# 2.支持版本 - - 19.14.x、19.15.x、19.16.x - -## 3.表结构定义 - - [维表参数信息](sideParams.md) - -clinkhose独有的参数信息 - -| 参数名称 | 含义 | 是否必填 | 默认值 | -| -------- | --------------------- | -------- | ------ | -| type | 维表类型, clinkhouse | 是 | | -| url | 连接数据库 jdbcUrl | 是 | | -| userName | 连接用户名 | 是 | | -| password | 连接密码 | 是 | | - -## 4.样例 - ------- - -## ALL全量维表定义 - -```sql -// 定义全量维表 -CREATE TABLE sideTable( - id INT, - name VARCHAR, - PRIMARY KEY(id), - PERIOD FOR SYSTEM_TIME - )WITH( - type ='clickhouse', - url ='jdbc:clickhouse://172.16.8.104:3306/zftest', - userName ='dtstack', - password ='abc123', - tableName ='all_test_clinkhousesql', - cache ='ALL', - cacheTTLMs ='60000', - parallelism ='1' - ); -``` - -### LRU异步维表定义 - -``` -CREATE TABLE sideTable( - id INT, - name VARCHAR, - PRIMARY KEY(id) , - PERIOD FOR SYSTEM_TIME - )WITH( - type ='clickhousesql', - url ='jdbc:clickhousesql://172.16.8.104:3306/zftest', - userName ='dtstack', - password ='abc123', - tableName ='lru_test_clickhousesql', - partitionedJoin ='false', - cache ='LRU', - cacheSize ='10000', - cacheTTLMs ='60000', - asyncPoolSize ='3', - parallelism ='1' - ); -``` - -### ClickHouseSQL异步维表关联 - -```sql -CREATE TABLE MyTable( - id int, - name varchar - )WITH( - type ='kafka11', - bootstrapServers ='172.16.8.107:9092', - zookeeperQuorum ='172.16.8.107:2181/kafka', - offsetReset ='latest', - topic ='cannan_zftest01', - timezone='Asia/Shanghai', - enableKeyPartitions ='false', - topicIsPattern ='false', - parallelism ='1' - ); - -CREATE TABLE MyResult( - id INT, - name VARCHAR - )WITH( - type ='clickhousesql', - url ='jdbc:clickhousesql://172.16.8.104:3306/zftest', - userName ='dtstack', - password ='abc123', - tableName ='test_clickhouse_zf', - updateMode ='append', - parallelism ='1', - batchSize ='100', - batchWaitInterval ='1000' - ); - -CREATE TABLE sideTable( - id INT, - name VARCHAR, - PRIMARY KEY(id) , - PERIOD FOR SYSTEM_TIME - )WITH( - type ='clickhousesql', - url ='jdbc:clickhousesql://172.16.8.104:3306/zftest', - userName ='dtstack', - password ='abc123', - tableName ='test_clickhouse_10', - partitionedJoin ='false', - cache ='LRU', - cacheSize ='10000', - cacheTTLMs ='60000', - asyncPoolSize ='3', - parallelism ='1' - ); - -insert -into - MyResult - select - m.id, - s.name - from - MyTable m - join - sideTable s - on m.id=s.id; -``` - diff --git a/docs/plugin/clickhouseSink.md b/docs/plugin/clickhouseSink.md deleted file mode 100644 index 6b4a724be..000000000 --- a/docs/plugin/clickhouseSink.md +++ /dev/null @@ -1,122 +0,0 @@ -## 1.格式: -``` -CREATE TABLE tableName( - colName colType, - ... - colNameX colType - )WITH( - type ='clickhouse', - url ='jdbcUrl', - userName ='userName', - password ='pwd', - tableName ='tableName', - parallelism ='parllNum' - ); - -``` - -## 2.支持版本 - 19.14.x、19.15.x、19.16.x - -## 3.表结构定义 - -|参数名称|含义| -|----|---| -| tableName| clickhouse表名称| -| colName | 列名称| -| colType | clickhouse基本数据类型,不包括Array,Tuple,Nested等| - -## 4.参数: - -|参数名称|含义|是否必填|默认值| -|----|----|----|----| -|type |表明 输出表类型 clickhouse |是|| -|url | 连接clickhouse 数据库 jdbcUrl |是|| -|userName | clickhouse 连接用户名 |是|| -| password | clickhouse 连接密码|是|| -| tableName | clickhouse 表名称|是|| -| parallelism | 并行度设置|否|1| -|updateMode| 只支持APPEND模式,过滤掉回撤数据||| - - -## 5.样例: - - -``` - -CREATE TABLE source1 ( - id int, - name VARCHAR -)WITH( - type ='kafka11', - bootstrapServers ='172.16.8.107:9092', - zookeeperQuorum ='172.16.8.107:2181/kafka', - offsetReset ='latest', - topic ='mqTest03', - timezone='Asia/Shanghai', - topicIsPattern ='false' - ); - - - -CREATE TABLE source2( - id int, - address VARCHAR -)WITH( - type ='kafka11', - bootstrapServers ='172.16.8.107:9092', - zookeeperQuorum ='172.16.8.107:2181/kafka', - offsetReset ='latest', - topic ='mqTest04', - timezone='Asia/Shanghai', - topicIsPattern ='false' -); - - -CREATE TABLE MyResult( - id int, - name VARCHAR, - address VARCHAR -)WITH( - type='clickhouse', - url='jdbc:clickhouse://172.16.10.168:8123/tudou?charset=utf8', - userName='dtstack', - password='abc123', - tableName='MyResult', - updateMode = 'append' -); - -insert into MyResult -select - s1.id, - s1.name, - s2.address -from - source1 s1 -left join - source2 s2 -on - s1.id = s2.id - - - ``` - - -**Clickhouse建表语句** - - - ```aidl -CREATE TABLE tudou.MyResult (`id` Int64, `name` String, `address` String) - ENGINE = MergeTree PARTITION BY address ORDER BY id SETTINGS index_granularity = 8192 -``` - - - - -数据结果: - -向Topic mqTest03 发送数据 {"name":"maqi","id":1001} 插入 (1001,"maqi",null) - -向Topic mqTest04 发送数据 {"address":"hz","id":1001} 插入 (1001,"maqi","hz") - - \ No newline at end of file diff --git a/docs/plugin/db2Side.md b/docs/plugin/db2Side.md deleted file mode 100644 index faf1b3060..000000000 --- a/docs/plugin/db2Side.md +++ /dev/null @@ -1,171 +0,0 @@ - -## 1.格式: - 通过建表语句中的` PERIOD FOR SYSTEM_TIME`将表标识为维表,其中`PRIMARY KEY(keyInfo)`中的keyInfo,表示用来和源表进行关联的字段, - 维表JOIN的条件必须与`keyInfo`字段一致。 -``` - CREATE TABLE tableName( - colName cloType, - ... - PRIMARY KEY(keyInfo), - PERIOD FOR SYSTEM_TIME - )WITH( - type='db2', - url='jdbcUrl', - userName='dbUserName', - password='dbPwd', - tableName='tableName', - cache ='LRU', - cacheSize ='10000', - cacheTTLMs ='60000', - parallelism ='1', - partitionedJoin='false' - ); -``` - -# 2.支持版本 - db2 9.X - -## 3.表结构定义 - - - [维表参数信息](sideParams.md) - db2独有的参数配置: - - |参数名称|含义| - |----|---| -| type | 维表类型, db2 |是|| -| url | 连接数据库 jdbcUrl |是|| -| userName | 连接用户名 |是|| -| password | 连接密码|是|| -| schema | 表所属scheam|否|| - - - -## 4.样例 - -### ALL全量维表定义 -``` - // 定义全量维表 -CREATE TABLE sideTable( - id INT, - name VARCHAR, - PRIMARY KEY(id) , - PERIOD FOR SYSTEM_TIME - )WITH( - type='db2', - url='jdbc:db2://172.16.10.251:50000/mqTest', - userName='DB2INST1', - password='abc123', - tableName='USER_INFO2', - schema = 'DTSTACK' - cache ='ALL', - cacheTTLMs ='60000', - parallelism ='2' - ); - -``` -### LRU异步维表定义 - -``` -CREATE TABLE sideTable( - id INT, - name VARCHAR, - PRIMARY KEY(id) , - PERIOD FOR SYSTEM_TIME - )WITH( - type='db2', - url='jdbc:db2://172.16.10.251:50000/mqTest', - userName='DB2INST1', - password='abc123', - tableName='USER_INFO2', - schema = 'DTSTACK' - partitionedJoin ='false', - cache ='LRU', - cacheSize ='10000', - cacheTTLMs ='60000', - asyncPoolSize ='3', - parallelism ='2' - ); - -``` - - -### DB2异步维表关联输出到Console -``` - -CREATE TABLE source1 ( - id int, - name VARCHAR -)WITH( - type ='kafka11', - bootstrapServers ='172.16.8.107:9092', - zookeeperQuorum ='172.16.8.107:2181/kafka', - offsetReset ='latest', - topic ='mqTest03', - timezone='Asia/Shanghai', - topicIsPattern ='false' - ); - - - -CREATE TABLE source2( - id int, - address VARCHAR, - PERIOD FOR SYSTEM_TIME -)WITH( - type='db2', - url='jdbc:db2://172.16.10.251:50000/mqTest', - userName='DB2INST1', - password='abc123', - tableName='USER_INFO2', - schema = 'DTSTACK', - batchSize = '1' -); - - -CREATE TABLE MyResult( - id int, - name VARCHAR, - address VARCHAR, - primary key (id) -)WITH( - type='console' -); - -insert into MyResult -select - s1.id, - s1.name, - s2.address -from - source1 s1 -left join - source2 s2 -on - s1.id = s2.id - -``` - -DB2维表字段信息 - -```aidl --- DTSTACK.USER_INFO2 definition - -CREATE TABLE "DTSTACK "."USER_INFO2" ( - "ID" INTEGER , - "NAME" VARCHAR(50 OCTETS) , - "ADDRESS" VARCHAR(50 OCTETS) ) - IN "USERSPACE1" - ORGANIZE BY ROW - ; - -GRANT CONTROL ON TABLE "DTSTACK "."USER_INFO2" TO USER "DB2INST1" -; -``` - -维表数据:(1001,maqi,hz) - -源表数据:{"name":"maqi","id":1001} - - -输出结果: (1001,maqi,hz) \ No newline at end of file diff --git a/docs/plugin/db2Sink.md b/docs/plugin/db2Sink.md deleted file mode 100644 index 9994bc4a5..000000000 --- a/docs/plugin/db2Sink.md +++ /dev/null @@ -1,137 +0,0 @@ -## 1.格式: -``` -CREATE TABLE tableName( - colName colType, - ... - colNameX colType, - [primary key (colName)] - )WITH( - type ='db2', - url ='jdbcUrl', - userName ='userName', - password ='pwd', - tableName ='tableName', - parallelism ='parllNum' - ); - -``` - -## 2.支持版本 - db2 9.X - -## 3.表结构定义 - -|参数名称|含义| -|----|---| -| tableName| db2表名称| -| colName | 列名称| -| colType | 列类型 [colType支持的类型](../colType.md)| -| primary key | updateMode为UPSERT时,需要指定的主键信息,不需要和数据库一致| - - -## 4.参数: - -|参数名称|含义|是否必填|默认值| -|----|----|----|----| -|type |结果表插件类型,必须为db2|是|| -|url | 连接db2数据库 jdbcUrl |是|| -|userName |db2连接用户名 |是|| -|password | db2连接密码|是|| -|tableName | db2表名称|是|| -|schema | db2表空间|否|| -|parallelism | 并行度设置|否|1| -|batchSize | flush的大小|否|100| -|batchWaitInterval | flush的时间间隔,单位ms|否|1000| -|allReplace| true:新值替换旧值|否|false| -|updateMode| APPEND:不回撤数据,只下发增量数据,UPSERT:先删除回撤数据,然后更新|否|结果表设置主键则为UPSERT| - -## 5.样例: - -回溯流删除 - -``` - -CREATE TABLE source1 ( - id int, - name VARCHAR -)WITH( - type ='kafka11', - bootstrapServers ='172.16.8.107:9092', - zookeeperQuorum ='172.16.8.107:2181/kafka', - offsetReset ='latest', - topic ='mqTest03', - timezone='Asia/Shanghai', - topicIsPattern ='false' - ); - - - -CREATE TABLE source2( - id int, - address VARCHAR -)WITH( - type ='kafka11', - bootstrapServers ='172.16.8.107:9092', - zookeeperQuorum ='172.16.8.107:2181/kafka', - offsetReset ='latest', - topic ='mqTest04', - timezone='Asia/Shanghai', - topicIsPattern ='false' -); - - -CREATE TABLE MyResult( - id int, - name VARCHAR, - address VARCHAR, - primary key (id) -)WITH( - type='db2', - url='jdbc:db2://172.16.10.251:50000/mqTest', - userName='DB2INST1', - password='abc123', - tableName='USER_INFO2', - schema = 'DTSTACK', - updateMode = 'upsert', // 设置 primary key则默认为upsert - batchSize = '1' -); - -insert into MyResult -select - s1.id, - s1.name, - s2.address -from - source1 s1 -left join - source2 s2 -on - s1.id = s2.id - - - - ``` - - - DB2结果表建表语句: - - ```aidl -CREATE TABLE "DTSTACK "."USER_INFO2" ( - "ID" INTEGER , - "NAME" VARCHAR(50 OCTETS) , - "ADDRESS" VARCHAR(50 OCTETS) ) - IN "USERSPACE1" - ORGANIZE BY ROW - ; - -GRANT CONTROL ON TABLE "DTSTACK "."USER_INFO2" TO USER "DB2INST1" -; -``` - - - -数据结果: - -向Topic mqTest03 发送数据 {"name":"maqi","id":1001} 插入 (1001,"maqi",null) - -向Topic mqTest04 发送数据 {"address":"hz","id":1001} 删除 (1001,"maqi",null) 插入 (1001,"maqi","hz") \ No newline at end of file diff --git a/docs/plugin/elasticsearch5Sink.md b/docs/plugin/elasticsearch5Sink.md deleted file mode 100644 index 294fbb69d..000000000 --- a/docs/plugin/elasticsearch5Sink.md +++ /dev/null @@ -1,98 +0,0 @@ -## 1.格式: -``` -CREATE TABLE tableName( - colName colType, - bb INT - )WITH( - type ='elasticsearch', - address ='ip:port[,ip:port]', - cluster='clusterName', - estype ='esType', - index ='index', - id ='num[,num]'(id = 'field[,field]'), - parallelism ='1' - ) -``` -## 2.支持的版本 - ES5 - -## 3.表结构定义 - -|参数名称|含义| -|----|---| -|tableName|在 sql 中使用的名称;即注册到flink-table-env上的名称| -|colName|列名称| -|colType|列类型 [colType支持的类型](../colType.md)| - -## 4.参数: -|参数名称|含义|是否必填|默认值| -|----|---|---|----| -|type|表明 输出表类型[mysq|hbase|elasticsearch]|是|elasticsearch| -|address | 连接ES Transport地址(tcp地址)|是|9300| -|cluster | ES 集群名称 |是|| -|index | 选择的ES上的index名称|是|| -|estype | 选择ES上的type名称|是|| -|id | 生成id的规则(当前是根据指定的字段名称(或者字段position)获取字段信息,拼接生成id)|否|| -|authMesh | 是否进行用户名密码认证(xpack认证) | 否 | false| -|userName | 用户名 | 否,authMesh='true'时为必填 || -|password | 密码 | 否,authMesh='true'时为必填 || -|parallelism | 并行度设置|否|1| - -## 5.样例: -```sql -CREATE TABLE MyTable( - channel varchar, - pv varchar - )WITH( - type ='kafka11', - bootstrapServers ='172.16.8.107:9092', - zookeeperQuorum ='172.16.8.107:2181/kafka', - offsetReset ='latest', - topic ='es_test', - timezone='Asia/Shanghai', - updateMode ='append', - enableKeyPartitions ='false', - topicIsPattern ='false', - parallelism ='1' - ); - -CREATE TABLE MyResult( - pv varchar, - channel varchar - )WITH( - type ='elasticsearch', - address ='172.16.8.193:9300', - authMesh='true', - username='elastic', - password='abc123', - estype ='external', - cluster ='docker-cluster', - index ='myresult', - id ='pv', --- id = '1' # 在支持position方式和属性名方式 - updateMode ='append', - parallelism ='1' - ); - - -insert -into - MyResult - select - s.pv as pv, - s.channel as channel - from - MyTable s - - ``` - -## 6.结果示例 -### 输入数据示例 -``` -{"channel":"xc26","pv":"10","xctime":1232312} -``` -### 输出数据示例 -``` -http://172.16.8.193:9200/myresult/_search -{"_index":"myresult","_type":"external","_id":"8aX_DHIBn3B7OBuqFl-i","_score":1.0,"_source":{"pv":"10","channel":"xc26"}} -``` \ No newline at end of file diff --git a/docs/plugin/elasticsearch6Side.md b/docs/plugin/elasticsearch6Side.md deleted file mode 100644 index a739a75b6..000000000 --- a/docs/plugin/elasticsearch6Side.md +++ /dev/null @@ -1,97 +0,0 @@ -## 1.格式 -``` - CREATE TABLE tableName( - colName cloType, - ... - PRIMARY KEY(keyInfo), - PERIOD FOR SYSTEM_TIME - )WITH( - type='elasticsearch6', - address ='ip:port[,ip:port]', - cluster='clusterName', - estype ='esType', - index ='index', - authMesh='true', - userName='dbUserName', - password='dbPwd', - cache ='LRU', - cacheSize ='10000', - cacheTTLMs ='60000', - parallelism ='1', - partitionedJoin='false' - ); -``` - -# 2.支持版本 - - elasticsearch `6.x` - -## 3.表结构定义 - -|参数名称|含义| -|---|---| -| tableName | elasticsearch表名称| -| colName | 列名称| -| colType | 列类型 [colType支持的类型](../colType.md)| -| PERIOD FOR SYSTEM_TIME | 关键字表明该定义的表为维表信息| -| PRIMARY KEY(keyInfo) | 维表主键定义;多个列之间用逗号隔开| - -## 4.参数 - -|参数名称|含义|是否必填|默认值| -|----|---|---|----| -|type|表明 输出表类型[elasticsearch6]|是|| -|address | 连接ES Http地址|是|| -|cluster | ES 集群名称 |是|| -|index | 选择的ES上的index名称|否|| -|esType | 选择ES上的type名称|否|| -|authMesh | 是否进行用户名密码认证 | 否 | false| -|userName | 用户名 | 否,authMesh='true'时为必填 || -|password | 密码 | 否,authMesh='true'时为必填 || -| cache | 维表缓存策略(NONE/LRU)|否|NONE| -| partitionedJoin | 是否在維表join之前先根据 設定的key 做一次keyby操作(可以減少维表的数据缓存量)|否|false| -|parallelism | 并行度设置|否|1| - - ----------- -> 缓存策略 - -* NONE: 不做内存缓存 -* LRU: - * cacheSize: 缓存的条目数量 - * cacheTTLMs:缓存的过期时间(ms) - * cacheMode: (unordered|ordered)异步加载是有序还是无序,默认有序。 - * asyncCapacity:异步请求容量,默认1000 - * asyncTimeout:异步请求超时时间,默认10000毫秒 - -## 5.样例 - -``` -create table sideTable( - channel varchar, - xccount int, - PRIMARY KEY(channel), - PERIOD FOR SYSTEM_TIME - )WITH( - type ='elasticsearch6', - address ='localhost:9200', - cluster='es_47_menghan', - estype ='type1', - index ='xc_es_test', - authMesh='true', - userName='dtstack', - password='abc123', - cache ='LRU', - cacheSize ='10000', - cacheTTLMs ='60000', - cacheMode='unordered', - asyncCapacity='1000', - asyncTimeout='10000' - parallelism ='1', - partitionedJoin='false' - ); - - -``` - - diff --git a/docs/plugin/elasticsearch6Sink.md b/docs/plugin/elasticsearch6Sink.md deleted file mode 100644 index 4eb6283c6..000000000 --- a/docs/plugin/elasticsearch6Sink.md +++ /dev/null @@ -1,126 +0,0 @@ -## 1.格式: -``` -CREATE TABLE tableName( - colName colType, - bb INT - )WITH( - type ='elasticsearch6', - address ='ip:port[,ip:port]', - cluster='clusterName', - esType ='esType', - index ='index', - id ='num[,num]'(id = 'field[,field]'), - authMesh = 'true', - userName = 'userName', - password = 'password', - parallelism ='1' - ) -``` -## 2.支持的版本 - elasticsearch `6.x` - -## 3.表结构定义 - -|参数名称|含义| -|----|---| -|tableName|在 sql 中使用的名称;即注册到flink-table-env上的名称| -|colName|列名称| -|colType|列类型 [colType支持的类型](../colType.md)| - -## 4.参数: -|参数名称|含义|是否必填|默认值| -|----|---|---|----| -|type|表明 输出表类型[elasticsearch6]|是|| -|address | 连接ES Http地址|是|| -|cluster | ES 集群名称 |是|| -|index | 选择的ES上的index名称|是|| -|esType | 选择ES上的type名称|是|| -|id | 生成id的规则(当前是根据指定的字段名称(或者字段position)获取字段信息,拼接生成id)|否|| -| |若id为空字符串或索引都超出范围,则随机生成id值)||| -|authMesh | 是否进行用户名密码认证 | 否 | false| -|userName | 用户名 | 否,authMesh='true'时为必填 || -|password | 密码 | 否,authMesh='true'时为必填 || -|parallelism | 并行度设置|否|1| - -## 5.完整样例: -``` -CREATE TABLE MyTable( - channel varchar, - pv INT, - xctime bigint - )WITH( - type ='kafka11', - bootstrapServers ='172.16.8.107:9092', - zookeeperQuorum ='172.16.8.107:2181/kafka', - offsetReset ='latest', - topic ='es_test', - timezone='Asia/Shanghai', - updateMode ='append', - enableKeyPartitions ='false', - topicIsPattern ='false', - parallelism ='1' - ); - -CREATE TABLE MyResult( - pv varchar, - channel varchar - )WITH( - type ='elasticsearch6', - address ='172.16.8.193:9200', - authMesh='true', - username='elastic', - password='abc123', - estype ='external', - cluster ='docker-cluster', - index ='myresult', - id ='pv', --- id = '1' # 在支持position方式和属性名方式 - parallelism ='1' - ); - -CREATE TABLE sideTable( - a varchar, - b varchar, - PRIMARY KEY(a) , - PERIOD FOR SYSTEM_TIME - )WITH( - type ='elasticsearch6', - address ='172.16.8.193:9200', - estype ='external', - cluster ='docker-cluster', - index ='sidetest', - authMesh='true', - username='elastic', - password='abc123', - cache ='LRU', - cacheSize ='10000', - cacheTTLMs ='60000', - partitionedJoin ='false', - parallelism ='1' - ); - -insert -into - MyResult - select - w.b as pv, - s.channel as channel - from - MyTable s - join - sideTable w - on s.pv = w.a - where - w.a = '10' - and s.channel='xc'; - ``` -## 6.结果数据 -### 输入数据 -``` -{"channel":"xc26","pv":10,"xctime":1232312} -``` -### 输出数据 -``` -http://172.16.8.193:9200/myresult/_search -{"_index":"myresult","_type":"external","_id":"8aX_DHIBn3B7OBuqFl-i","_score":1.0,"_source":{"pv":"10","channel":"xc26"}} -``` \ No newline at end of file diff --git a/docs/plugin/elasticsearch7Side.md b/docs/plugin/elasticsearch7Side.md deleted file mode 100644 index 38ee0c3e2..000000000 --- a/docs/plugin/elasticsearch7Side.md +++ /dev/null @@ -1,90 +0,0 @@ -## 1.格式 - -```sql - CREATE TABLE tableName( - colName cloType, - ... - PRIMARY KEY(keyInfo), - PERIOD FOR SYSTEM_TIME - )WITH( - type='elasticsearch7', - address ='ip:port[,ip:port]', - index ='index', - authMesh='true', - userName='dbUserName', - password='dbPwd', - cache ='LRU', - cacheSize ='10000', - cacheTTLMs ='60000', - parallelism ='1', - partitionedJoin='false' - ); -``` - -# 2.支持版本 - - elasticsearch `6.x` - -## 3.表结构定义 - -|参数名称|含义| -|----|---| -| tableName | elasticsearch表名称| -| colName | 列名称| -| colType | 列类型 [colType支持的类型](../colType.md)| -| PERIOD FOR SYSTEM_TIME | 关键字表明该定义的表为维表信息| -| PRIMARY KEY(keyInfo) | 维表主键定义;多个列之间用逗号隔开| - -## 4.参数 - -|参数名称|含义|是否必填|默认值| -|---|---|---|---| -|type|表明 输出表类型[elasticsearch6]|是|| -|address | 连接ES Http地址|是|| -|index | 选择的ES上的index名称|否|| -|authMesh | 是否进行用户名密码认证 | 否 | false| -|userName | 用户名 | 否,authMesh='true'时为必填 || -|password | 密码 | 否,authMesh='true'时为必填 || -|cache | 维表缓存策略(NONE/LRU)|否|NONE| -|partitionedJoin | 是否在維表join之前先根据 設定的key 做一次keyby操作(可以減少维表的数据缓存量)|否|false| -|parallelism | 并行度设置|否|1| - ----------- -> 缓存策略 -* NONE: 不做内存缓存 -* LRU: - * cacheSize: 缓存的条目数量 - * cacheTTLMs:缓存的过期时间(ms) - * cacheMode: (unordered|ordered)异步加载是有序还是无序,默认有序。 - * asyncCapacity:异步请求容量,默认1000 - * asyncTimeout:异步请求超时时间,默认10000毫秒 - -## 5.样例 - -```sql -create table sideTable( - channel varchar, - xccount int, - PRIMARY KEY(channel), - PERIOD FOR SYSTEM_TIME - )WITH( - type ='elasticsearch6', - address ='localhost:9200', - cluster='es_47_menghan', - estype ='type1', - index ='xc_es_test', - authMesh='true', - userName='dtstack', - password='abc123', - cache ='LRU', - cacheSize ='10000', - cacheTTLMs ='60000', - cacheMode='unordered', - asyncCapacity='1000', - asyncTimeout='10000' - parallelism ='1', - partitionedJoin='false' - ); -``` - - diff --git a/docs/plugin/elasticsearch7Sink.md b/docs/plugin/elasticsearch7Sink.md deleted file mode 100644 index b1a8114ab..000000000 --- a/docs/plugin/elasticsearch7Sink.md +++ /dev/null @@ -1,119 +0,0 @@ -## 1.格式: -``` -CREATE TABLE tableName( - colName colType, - bb INT - )WITH( - type ='elasticsearch7', - address ='ip:port[,ip:port]', - index ='index', - id = 'field[,field]', - authMesh = 'true', - userName = 'userName', - password = 'password', - parallelism ='1' - ) -``` -## 2.支持的版本 - elasticsearch `7.x` - -## 3.表结构定义 - -|参数名称|含义| -|----|---| -|tableName|在 sql 中使用的名称;即注册到flink-table-env上的名称| -|colName|列名称| -|colType|列类型 [colType支持的类型](../colType.md)| - -## 4.参数: -|参数名称|含义|是否必填|默认值| -|----|---|---|----| -|type|表明 输出表类型[elasticsearch7]|是|| -|address | 连接ES Http地址|是|| -|index | 选择的ES上的index名称,支持静态索引和动态索引,动态索引示例: `{user_name}`|是|| -|index_definition| 为ES定义索引的字段类型、别名以及shard数量|否| -|id | 生成id的规则,根据字段名称定义文档ID|否|uuid| -|authMesh | 是否进行用户名密码认证(xpack) | 否 | false| -|userName | 用户名 | 否,authMesh='true'时为必填 || -|password | 密码 | 否,authMesh='true'时为必填 || -|parallelism | 并行度设置|否|1| - -## 5.完整样例: -``` -CREATE TABLE MyTable( - channel varchar, - pv int, - )WITH( - type ='kafka11', - bootstrapServers ='172.16.8.107:9092', - zookeeperQuorum ='172.16.8.107:2181/kafka', - offsetReset ='latest', - topic ='es_test', - timezone='Asia/Shanghai', - updateMode ='append', - enableKeyPartitions ='false', - topicIsPattern ='false', - parallelism ='1' - ); - -CREATE TABLE MyResult( - channel varchar, - pv int - )WITH( - type ='elasticsearch7', - address ='172.16.8.193:9200', - authMesh='true', - username='elastic', - password='abc123', - estype ='external', - cluster ='docker-cluster', - index ='myresult', --- index = '{pv}' # 动态索引写法 - id ='pv', - parallelism ='1' - ); - -CREATE TABLE sideTable( - a varchar, - b varchar, - PRIMARY KEY(a) , - PERIOD FOR SYSTEM_TIME - )WITH( - type ='elasticsearch7', - address ='172.16.8.193:9200', - index ='sidetest', - authMesh='true', - username='elastic', - password='abc123', - cache ='LRU', - cacheSize ='10000', - cacheTTLMs ='60000', - partitionedJoin ='false', - parallelism ='1' - ); - -insert -into - MyResult - select - w.b as pv, - s.channel as channel - from - MyTable s - join - sideTable w - on s.pv = w.a - where - w.a = '10' - and s.channel='xc'; - ``` -## 6.结果数据 -### 输入数据 -``` -{"channel":"xc26","pv":10,"xctime":1232312} -``` -### 输出数据 -``` -http://localhost:9200/myresult/_search -{"_index":"myresult","_type":"external","_id":"8aX_DHIBn3B7OBuqFl-i","_score":1.0,"_source":{"pv":"10","channel":"xc26"}} -``` \ No newline at end of file diff --git a/docs/plugin/filesource.md b/docs/plugin/filesource.md deleted file mode 100644 index f3161b14a..000000000 --- a/docs/plugin/filesource.md +++ /dev/null @@ -1,184 +0,0 @@ -## 1.格式: - -``` -CREATE TABLE tableName( - colName colType, - ... - )WITH( - type ='file', - format = 'csv', - fieldDelimiter = ',', - fileName = 'xxxx', - filePath = 'xx/xxx', - location = 'local', - nullLiteral = 'null', - allowComment = 'true', - arrayElementDelimiter = ',', - quoteCharacter = '"', - escapeCharacter = '\\', - ignoreParseErrors = 'true', - hdfsSite = 'xxx/hdfs-site.xml', - coreSite = 'xxx/core-site.xml', - hdfsUser = 'root', - charsetName = 'UTF-8' - ); -``` - -## 2.支持的格式 - -支持 HDFS、 Local 支持 Csv、Json、Arvo 格式文件 - -## 3.表结构定义 - -|参数名称|含义| -|----|---| -| tableName | 在 sql 中使用的名称;即注册到flink-table-env上的名称| -| colName | 列名称| -| colType | 列类型 [colType支持的类型](../colType.md)| - -## 4.参数 - -通用参数设置 - -|参数名称|默认值|是否必填|参数说明| -|----|---|---|---| -|type|file|是|当前表的类型| -|format|csv|是|文件格式,仅支持csv,json,Arvo类型| -|fileName|无|是|文件名| -|filePath|无|是|文件绝对路径| -|location|local|是|文件存储介质,仅支持HDFS、Local| -|charsetName|UTF-8|否|文件编码格式| - -### 4.1 Csv 参数设置 - -|参数名称|默认值|是否必填|参数说明| -|----|---|---|---| -|ignoreParseErrors|true|否|是否忽略解析失败的数据| -|fieldDelimiter|,|否|csv数据的分割符| -|nullLiteral|"null"|否|填充csv数据中的null值| -|allowComments|true|否|| -|arrayElementDelimiter|,|否|| -|quoteCharacter|"|否|| -|escapeCharacter|\|否|| - -### 4.2 Arvo 参数说明 - -|参数名称|默认值|是否必填|参数说明| -|----|---|---|---| -|avroFormat|无|是|在format = 'arvo'的情况下是必填项| - -### 4.3 HDFS 参数说明 - -|参数名称|默认值|是否必填|参数说明| -|----|---|---|---| -|hdfsSite|${HADOOP_CONF_HOME}/hdfs-site.xml|是|hdfs-site.xml所在位置| -|coreSite|${HADOOP_CONF_HOME}/core-site.xml|是|core-site.xml所在位置| -|hdfsUser|root|否|HDFS访问用户,默认是[root]用户| - -### 4.4 Json 参数说明 - -Json无特殊参数 - -## 5.样例 - -数据展示: - -csv - -```csv -712382,1/1/2017 0:00,1/1/2017 0:03,223,7051,Wellesley St E / Yonge St Green P,7089,Church St / Wood St,Member -``` - -json - -```json -{ - "trip_id": "712382", - "trip_start_time": "1/1/2017 0:00", - "trip_stop_time": "1/1/2017 0:03", - "trip_duration_seconds": "223", - "from_station_id": "7051", - "from_station_name": "Wellesley St E / Yonge St Green P", - "to_station_id": "7089", - "to_station_name": "Church St / Wood St", - "user_type": "Member" -}, - -``` - -### 5.1 csv - -```sql -CREATE TABLE SourceOne -( - trip_id varchar, - trip_start_time varchar, - trip_stop_time varchar, - trip_duration_seconds varchar, - from_station_id varchar, - from_station_name varchar, - to_station_id varchar, - to_station_name varchar, - user_type varchar -) WITH ( - type = 'file', - format = 'csv', - fieldDelimiter = ',', - fileName = '2017-Q1.csv', - filePath = '/data', - location = 'local', - charsetName = 'UTF-8' - ); -``` - -### 5.2 json - -```sql -CREATE TABLE SourceOne -( - trip_id varchar, - trip_start_time varchar, - trip_stop_time varchar, - trip_duration_seconds varchar, - from_station_id varchar, - from_station_name varchar, - to_station_id varchar, - to_station_name varchar, - user_type varchar -) WITH ( - type = 'file', - format = 'json', - fieldDelimiter = ',', - fileName = '2017-Q1.json', - filePath = '/data', - charsetName = 'UTF-8' - ); -``` - -### 5.3 HDFS - -```sql -CREATE TABLE SourceOne -( - trip_id varchar, - trip_start_time varchar, - trip_stop_time varchar, - trip_duration_seconds varchar, - from_station_id varchar, - from_station_name varchar, - to_station_id varchar, - to_station_name varchar, - user_type varchar -) WITH ( - type = 'file', - format = 'json', - fieldDelimiter = ',', - fileName = '2017-Q1.json', - filePath = 'hdfs://ns1/data', - location = 'hdfs', - hdfsSite = '/Users/wtz/dtstack/conf/yarn/kudu1/hdfs-site.xml', - coreSite = '/Users/wtz/dtstack/conf/yarn/kudu1/core-site.xml', - hdfsUser = 'admin', - charsetName = 'UTF-8' - ); -``` diff --git a/docs/plugin/hbaseSide.md b/docs/plugin/hbaseSide.md deleted file mode 100644 index 550dfbae0..000000000 --- a/docs/plugin/hbaseSide.md +++ /dev/null @@ -1,252 +0,0 @@ - -## 1.格式 -``` - CREATE TABLE tableName( - columnFamily:columnName type as alias, - ... - PRIMARY KEY(keyInfo), - PERIOD FOR SYSTEM_TIME - )WITH( - type ='hbase', - zookeeperQuorum ='ip:port', - zookeeperParent ='/hbase', - tableName ='tableNamae', - cache ='LRU', - cacheSize ='10000', - cacheTTLMs ='60000', - parallelism ='1', - partitionedJoin='false' - ); -``` -## 2.支持版本 - hbase2.0 - -## 3.表结构定义 - -|参数名称|含义| -|----|---| -| tableName | 注册到flink的表名称(可选填;不填默认和hbase对应的表名称相同)| -| columnFamily:columnName | hbase中的列族名称和列名称 | -| alias | hbase 中的列对应到flink中注册的列名称 | -| PERIOD FOR SYSTEM_TIME | 关键字表明该定义的表为维表信息| -| PRIMARY KEY(keyInfo) | 维表主键定义;hbase 维表rowkey的构造方式:可选择的构造包括 md5(alias + alias), '常量',也包括上述方式的自由组合 | - -## 4.参数 - -参数详细说明请看[参数详细说明](sideParams.md) - -|参数名称|含义|是否必填|默认值| -|----|---|---|----| -| type | 表明维表的类型[hbase|mysql]|是|| -| zookeeperQuorum | hbase 的zk地址;格式ip:port[;ip:port]|是|| -| zookeeperParent | hbase 的zk parent路径|是|| -| tableName | hbase 的表名称|是|| -| cache | 维表缓存策略(NONE/LRU)|否|NONE| -| partitionedJoin | 是否在維表join之前先根据 設定的key 做一次keyby操作(可以減少维表的数据缓存量)|否|false| -|hbase.security.auth.enable | 是否开启kerberos认证|否|false| -|hbase.security.authentication|认证类型|否|kerberos| -|hbase.kerberos.regionserver.principal | regionserver的principal,这个值从hbase-site.xml的hbase.regionserver.kerberos.principal属性中获取|否|| -|hbase.keytab|client的keytab 文件|否| -|hbase.principal|client的principal|否|| -|hbase.sasl.clientconfig | hbase.sasl.clientconfig值|否|Client,和jaas文件中的域对应| -|java.security.krb5.conf | java.security.krb5.conf值|否|| - 另外开启Kerberos认证还需要在VM参数中配置krb5, -Djava.security.krb5.conf=/Users/xuchao/Documents/flinkSql/kerberos/krb5.conf - 同时在addShipfile参数中添加keytab文件的路径,参数具体细节请看[命令参数说明](../config.md) --------------- - -## 5.样例 -### LRU维表示例 -``` -CREATE TABLE sideTable ( - wtz:message varchar as message, - wtz:info varchar as info , - PRIMARY KEY (rowkey), - PERIOD FOR SYSTEM_TIME -) WITH ( - type = 'hbase', - zookeeperQuorum = '192.168.80.105:2181,192.168.80.106:2181,192.168.80.107:2181', - zookeeperParent = '/hbase', - tableName = 'testFlinkStreamSql', - parallelism = '1', - cache = 'LRU', - cacheSize ='10000', - cacheTTLMs ='60000', - parallelism ='1', - partitionedJoin='false' -); -``` - -### ALL维表示例 -``` -CREATE TABLE sideTable ( - wtz:message varchar as message, - wtz:info varchar as info , - PRIMARY KEY (rowkey), - PERIOD FOR SYSTEM_TIME -) WITH ( - type = 'hbase', - zookeeperQuorum = '192.168.80.105:2181,192.168.80.106:2181,192.168.80.107:2181', - zookeeperParent = '/hbase', - tableName = 'testFlinkStreamSql', - parallelism = '1', - cache = 'ALL', - cacheTTLMs ='60000', - parallelism ='1', - partitionedJoin='false' -); -``` - -## 6.hbase完整样例 - -### 数据说明 - -在hbase中,数据是以列簇的形式存储,其中rowKey作为主键,按字典排序。 - -在样例中,wtz为列族名,message, info为列名,数据在hbase中的存储情况为: -``` -hbase(main):002:0> scan 'testFlinkStreamSql' -ROW COLUMN+CELL - cfcd208495d565ef66e7dff9f98764dazhangsantest column=wtz:info, timestamp=1587089266719, value=hadoop - cfcd208495d565ef66e7dff9f98764dazhangsantest column=wtz:message, timestamp=1587089245780, value=hbase - c4ca4238a0b923820dcc509a6f75849blisitest column=wtz:info, timestamp=1587088818432, value=flink - c4ca4238a0b923820dcc509a6f75849blisitest column=wtz:message, timestamp=1587088796633, value=dtstack - c81e728d9d4c2f636f067f89cc14862cwangwutest column=wtz:info, timestamp=1587088858564, value=sql - c81e728d9d4c2f636f067f89cc14862cwangwutest column=wtz:message, timestamp=1587088840507, value=stream -``` -在hbase中,rowKey是一个二进制码流,可以为任意字符串,flinkStreamSql读取rowKey并通过rowKey唯一确定数据,对rowKey没有任何限制,对rowKey可选择的构造包括 md5(alias + alias), '常量',也可以它们的自由组合。 -在本次案例中,rowKey为了简单,设置成了"0,1,2"这样的数值型字符,若有必要,也可以设计得更为复杂。 -### hbase异步维表关联完整案例 -``` -CREATE TABLE MyTable( - id varchar, - name varchar, - address varchar -)WITH( - type = 'kafka10', - bootstrapServers = '172.16.101.224:9092', - zookeeperQuorm = '172.16.100.188:2181/kafka', - offsetReset = 'latest', - topic = 'tiezhu_test_in', - groupId = 'flink_sql', - timezone = 'Asia/Shanghai', - topicIsPattern = 'false', - parallelism = '1' -); - -CREATE TABLE MyResult( - id varchar, - name varchar, - address varchar, - message varchar, - info varchar -)WITH( - type = 'console' - ); - - CREATE TABLE sideTable ( - wtz:message varchar as message, - wtz:info varchar as info , - PRIMARY KEY (md5(rowkey1) + rowkey2 + 'test'), - PERIOD FOR SYSTEM_TIME -) WITH ( - type = 'hbase', - zookeeperQuorum = '192.168.80.105:2181,192.168.80.106:2181,192.168.80.107:2181', - zookeeperParent = '/hbase', - tableName = 'testFlinkStreamSql', - parallelism = '1', - cache = 'LRU', - cacheSize ='10000', - cacheTTLMs ='60000', - parallelism ='1', - partitionedJoin='false' -); - -insert -into - MyResult - select - a.name, - a.id, - a.address, - b.message, - b.info - from - MyTable a - left join - sideTable b - on a.id=b.rowkey1 and a.name = b.rowkey2; -``` -### kerberos维表示例 -``` -CREATE TABLE MyTable( - name varchar, - channel varchar, - pv INT, - xctime bigint -)WITH( - type ='kafka11', - bootstrapServers ='172.16.8.107:9092', - zookeeperQuorum ='172.16.8.107:2181/kafka', - offsetReset ='latest', - topic ='es_test', - timezone='Asia/Shanghai', - updateMode ='append', - enableKeyPartitions ='false', - topicIsPattern ='false', - parallelism ='1' -); - -CREATE TABLE MyResult( - name varchar, - channel varchar -)WITH( - type ='mysql', - url ='jdbc:mysql://172.16.10.45:3306/test', - userName ='dtstack', - password ='abc123', - tableName ='myresult', - updateMode ='append', - parallelism ='1', - batchSize ='100', - batchWaitInterval ='1000' -); - -CREATE TABLE sideTable( - cf:name varchar as name, - cf:info varchar as info, - PRIMARY KEY(md5(name) +'test') , - PERIOD FOR SYSTEM_TIME -)WITH( - type ='hbase', - zookeeperQuorum ='172.16.10.104:2181,172.16.10.224:2181,172.16.10.252:2181', - zookeeperParent ='/hbase', - tableName ='workerinfo', - partitionedJoin ='false', - cache ='LRU', - cacheSize ='10000', - cacheTTLMs ='60000', - asyncTimeoutNum ='0', - parallelism ='1', - hbase.security.auth.enable='true', - hbase.security.authentication='kerberos', - hbase.sasl.clientconfig='Client', - hbase.kerberos.regionserver.principal='hbase/_HOST@DTSTACK.COM', - hbase.keytab='yijing.keytab', - hbase.principal='yijing@DTSTACK.COM', - java.security.krb5.conf='krb5.conf' -); - -insert into - MyResult -select - b.name as name, - a.channel - -from - MyTable a - -join - sideTable b - -on a.channel=b.name -``` diff --git a/docs/plugin/hbaseSink.md b/docs/plugin/hbaseSink.md deleted file mode 100644 index 169236097..000000000 --- a/docs/plugin/hbaseSink.md +++ /dev/null @@ -1,149 +0,0 @@ -## 1.格式: -``` -CREATE TABLE MyResult( - colFamily:colName colType, - ... - )WITH( - type ='hbase', - zookeeperQuorum ='ip:port[,ip:port]', - tableName ='tableName', - rowKey ='colName[+colName]', - parallelism ='1', - zookeeperParent ='/hbase' - ) - - -``` - -## 2.支持版本 -hbase2.0 - -## 3.表结构定义 - -|参数名称|含义| -|----|---| -| tableName | 在 sql 中使用的名称;即注册到flink-table-env上的名称 -| colFamily:colName | hbase中的列族名称和列名称 -| colType | 列类型 [colType支持的类型](../colType.md) - -## 4.参数: - -|参数名称|含义|是否必填|默认值| -|----|---|---|-----| -|type | 表明 输出表类型[mysq|hbase|elasticsearch]|是|| -|zookeeperQuorum | hbase zk地址,多个直接用逗号隔开|是|| -|zookeeperParent | zkParent 路径|是|| -|tableName | 关联的hbase表名称|是|| -|rowkey | hbase的rowkey关联的列信息'+'多个值以逗号隔开|是|| -|updateMode|APPEND:不回撤数据,只下发增量数据,UPSERT:先删除回撤数据,然后更新|否|APPEND| -|parallelism | 并行度设置|否|1| -|kerberosAuthEnable | 是否开启kerberos认证|否|false| -|regionserverPrincipal | regionserver的principal,这个值从hbase-site.xml的hbase.regionserver.kerberos.principal属性中获取|否|| -|clientKeytabFile|client的keytab 文件|否| -|clientPrincipal|client的principal|否|| -|zookeeperSaslClient | zookeeper.sasl.client值|否|true| -|securityKrb5Conf | java.security.krb5.conf值|否|| - 另外开启Kerberos认证还需要在VM参数中配置krb5, -Djava.security.krb5.conf=/Users/xuchao/Documents/flinkSql/kerberos/krb5.conf - 同时在addShipfile参数中添加keytab文件的路径,参数具体细节请看[命令参数说明](../config.md) -## 5.样例: - -### 普通结果表语句示例 -``` -CREATE TABLE MyTable( - name varchar, - channel varchar, - age int - )WITH( - type ='kafka10', - bootstrapServers ='172.16.8.107:9092', - zookeeperQuorum ='172.16.8.107:2181/kafka', - offsetReset ='latest', - topic ='mqTest01', - timezone='Asia/Shanghai', - updateMode ='append', - enableKeyPartitions ='false', - topicIsPattern ='false', - parallelism ='1' - ); - -CREATE TABLE MyResult( - cf:name varchar , - cf:channel varchar - )WITH( - type ='hbase', - zookeeperQuorum ='172.16.10.104:2181,172.16.10.224:2181,172.16.10.252:2181', - zookeeperParent ='/hbase', - tableName ='myresult', - partitionedJoin ='false', - parallelism ='1', - rowKey='name+channel' - ); - -insert -into - MyResult - select - channel, - name - from - MyTable a - - - ``` - -### kerberos认证结果表语句示例 -``` -CREATE TABLE MyTable( - name varchar, - channel varchar, - age int - )WITH( - type ='kafka10', - bootstrapServers ='172.16.8.107:9092', - zookeeperQuorum ='172.16.8.107:2181/kafka', - offsetReset ='latest', - topic ='mqTest01', - timezone='Asia/Shanghai', - updateMode ='append', - enableKeyPartitions ='false', - topicIsPattern ='false', - parallelism ='1' - ); - -CREATE TABLE MyResult( - cf:name varchar , - cf:channel varchar - )WITH( - type ='hbase', - zookeeperQuorum ='cdh2.cdhsite:2181,cdh4.cdhsite:2181', - zookeeperParent ='/hbase', - tableName ='myresult', - partitionedJoin ='false', - parallelism ='1', - rowKey='name', - kerberosAuthEnable='true', - regionserverPrincipal='hbase/_HOST@DTSTACK.COM', - clientKeytabFile='test.keytab', - clientPrincipal='test@DTSTACK.COM', - securityKrb5Conf='krb5.conf', - ); - -insert -into - MyResult - select - channel, - name - from - MyTable a - -``` - -## 6.hbase数据 -### 数据内容说明 -hbase的rowkey 构建规则:以描述的rowkey字段值作为key,多个字段以'+'连接 -### 数据内容示例 -hbase(main):007:0> scan 'myresult' - ROW COLUMN+CELL - roc-daishu column=cf:channel, timestamp=1589183971724, value=daishu - roc-daishu column=cf:name, timestamp=1589183971724, value=roc \ No newline at end of file diff --git a/docs/plugin/httpSink.md b/docs/plugin/httpSink.md deleted file mode 100644 index 7b6d1bb4a..000000000 --- a/docs/plugin/httpSink.md +++ /dev/null @@ -1,66 +0,0 @@ -## 1.格式: -``` -CREATE TABLE tableName( - colName colType, - ... - colNameX colType - )WITH( - type ='http', - url ='http://xxx:8080/test/returnAll' - ,flag ='aa' - ,delay = '10' - ); - -``` - - -## 3.表结构定义 - -|参数名称|含义| -|----|---| -| tableName| http表名称| -| colName | 列名称| -| colType | 列类型 [colType支持的类型](../colType.md)| - -## 4.参数: - -|参数名称|含义|是否必填|默认值| -|----|----|----|----| -|http |结果表插件类型,必须为http|是|| -|url | 地址 |是|| -|flag | 结果返回标识符|否|| -|delay |每条结果数据之间延时时间 |否|默认20毫秒| - - -## 5.样例: - -``` - --- {"name":"maqi","id":1001} -CREATE TABLE sourceIn ( - id int, - name VARCHAR -)WITH( - type = 'kafka', - bootstrapServers = 'localhost:9092', - topic ='test1' - ); - -CREATE TABLE sinkOut ( - id int - , name varchar -) WITH ( - type ='http', - url ='http://xxx:8080/test/returnAll' - ,flag ='aa' - ,delay = '10' -); - -insert into sinkOut select id,name from sourceIn; - - ``` - -发送数据:{"name":"maqi","id":1001} -
结果数据: -
1.flag不填或者为空串:{"name":"maqi","id":1001} -
2.flag有内容:{"flag":"11111111","name":"maqi","id":1001,"tableName":"sinkOut"} diff --git a/docs/plugin/impalaColType.md b/docs/plugin/impalaColType.md deleted file mode 100644 index 4b84b3aa3..000000000 --- a/docs/plugin/impalaColType.md +++ /dev/null @@ -1,14 +0,0 @@ -| 支持的类型 | java对应类型 | -| ------ | ----- | -| boolean | Boolean | -| char | Character | -| double | Double| -| float | Float| -| tinyint | Byte | -| smallint | Short| -| int | Integer | -| bigint | Long | -| decimal |BigDecimal| -| string | String | -| varchar | String | -| timestamp | Timestamp | \ No newline at end of file diff --git a/docs/plugin/impalaSide.md b/docs/plugin/impalaSide.md deleted file mode 100644 index 64c22b498..000000000 --- a/docs/plugin/impalaSide.md +++ /dev/null @@ -1,199 +0,0 @@ -## 1.格式: - -```sql - CREATE TABLE tableName( - colName cloType, - ... - PRIMARY KEY(keyInfo), - PERIOD FOR SYSTEM_TIME - )WITH( - type='impala', - url='jdbcUrl', - userName='dbUserName', - password='dbPwd', - tableName='tableName', - cache ='LRU', - cacheSize ='10000', - cacheTTLMs ='60000', - parallelism ='1', - partitionedJoin='false' - ); -``` - -## 2.支持版本 - - 2.10.0-cdh5.13.0 - -## 3.表结构定义 - - [维表参数信息](sideParams.md) - -impala独有的参数配置 - -| 参数名称 | 含义 | 是否必填 | 默认值 | -| ------------------- | ------------------------------------------------------------ | --------------------------------- | ---------- | -| type | 表明维表的类型[impala] | 是 | | -| url | 连接postgresql数据库 jdbcUrl | 是 | | -| userName | postgresql连接用户名 | 是 | | -| password | postgresql连接密码 | 是 | | -| tableName | postgresql表名称 | 是 | | -| authMech | 身份验证机制 (0, 1, 2, 3), 暂不支持kerberos | 是 | 0 | -| principal | kerberos用于登录的principal(authMech=1时独有) | authMech=1为必填 | | -| keyTabFilePath | keytab文件的路径(authMech=1时独有) | authMech=1为必填 | | -| krb5FilePath | krb5.conf文件路径(authMech=1时独有) | authMech=1为必填 | | -| krbServiceName | Impala服务器的Kerberos principal名称(authMech=1时独有) | authMech=1为必填 | | -| krbRealm | Kerberos的域名(authMech=1时独有) | 否 | HADOOP.COM | -| enablePartition | 是否支持分区 | 否 | false | -| partitionfields | 分区字段名 | 否,enablePartition='true'时为必填 | | -| partitionFieldTypes | 分区字段类型 | 否,enablePartition='true'时为必填 | | -| partitionValues | 分区值 | 否,enablePartition='true'时为必填 | | -| cache | 维表缓存策略(NONE/LRU/ALL) | 否 | NONE | -| partitionedJoin | 是否在維表join之前先根据 設定的key 做一次keyby操作(可以減少维表的数据缓存量) | 否 | false | - -## 4.样例 - -### ALL全量维表定义 - -```sql - // 定义全量维表 -CREATE TABLE sideTable( - id INT, - name VARCHAR, - PRIMARY KEY(id) , - PERIOD FOR SYSTEM_TIME - )WITH( - type ='mysql', - url ='jdbc:impala://localhost:21050/mqtest', - userName ='dtstack', - password ='1abc123', - tableName ='test_impala_all', - authMech='3', - cache ='ALL', - cacheTTLMs ='60000', - parallelism ='2', - partitionedJoin='false' - ); - -``` - -### LRU异步维表定义 - -```sql -create table sideTable( - channel varchar, - xccount int, - PRIMARY KEY(channel), - PERIOD FOR SYSTEM_TIME - )WITH( - type='impala', - url='jdbc:impala://localhost:21050/mytest', - userName='dtstack', - password='abc123', - tableName='sidetest', - authMech='3', - cache ='LRU', - cacheSize ='10000', - cacheTTLMs ='60000', - parallelism ='1', - partitionedJoin='false' - ); - -``` - -### MySQL异步维表关联 - -```sql -CREATE TABLE MyTable( - id int, - name varchar - )WITH( - type ='kafka11', - bootstrapServers ='172.16.8.107:9092', - zookeeperQuorum ='172.16.8.107:2181/kafka', - offsetReset ='latest', - topic ='cannan_yctest01', - timezone='Asia/Shanghai', - enableKeyPartitions ='false', - topicIsPattern ='false', - parallelism ='1' - ); - -CREATE TABLE MyResult( - id INT, - name VARCHAR - )WITH( - type='impala', - url='jdbc:impala://localhost:21050/mytest', - userName='dtstack', - password='abc123', - tableName ='test_impala_zf', - updateMode ='append', - parallelism ='1', - batchSize ='100', - batchWaitInterval ='1000' - ); - -CREATE TABLE sideTable( - id INT, - name VARCHAR, - PRIMARY KEY(id) , - PERIOD FOR SYSTEM_TIME - )WITH( - type='impala', - url='jdbc:impala://localhost:21050/mytest', - userName='dtstack', - password='abc123', - tableName ='test_impala_10', - partitionedJoin ='false', - cache ='LRU', - cacheSize ='10000', - cacheTTLMs ='60000', - asyncPoolSize ='3', - parallelism ='1' - ); - -insert -into - MyResult - select - m.id, - s.name - from - MyTable m - join - sideTable s - on m.id=s.id; - -``` - -### 分区样例 - -注:分区字段放在最后面,如下,name是分区字段,放在channel,xccount字段的后面 - -```sql -create table sideTable( - channel varchar, - xccount int, - name varchar, - PRIMARY KEY(channel), - PERIOD FOR SYSTEM_TIME - )WITH( - type='impala', - url='jdbc:impala://localhost:21050/mytest', - userName='dtstack', - password='abc123', - tableName='sidetest', - authMech='3', - cache ='LRU', - cacheSize ='10000', - cacheTTLMs ='60000', - parallelism ='1', - enablePartition='true', - partitionfields='name', - partitionFieldTypes='varchar', - partitionValues='{"name":["tom","jeck"]}', - partitionedJoin='false' - ); - -``` - diff --git a/docs/plugin/impalaSink.md b/docs/plugin/impalaSink.md deleted file mode 100644 index 4847cf2e2..000000000 --- a/docs/plugin/impalaSink.md +++ /dev/null @@ -1,130 +0,0 @@ -## 1.格式: -``` -CREATE TABLE tableName( - colName colType, - ... - colNameX colType - )WITH( - type ='impala', - url ='jdbcUrl', - userName ='userName', - password ='pwd', - tableName ='tableName', - parallelism ='parllNum' - ); - -``` - -## 2.支持版本 - 2.10.0-cdh5.13.0 - -## 3.表结构定义 - -|参数名称|含义| -|----|---| -| tableName| 在 sql 中使用的名称;即注册到flink-table-env上的名称| -| colName | 列名称| -| colType | 列类型 [colType支持的类型](impalaColType.md)| - -## 4.参数: - -|参数名称|含义|是否必填|默认值| -|----|----|----|----| -| type |表明 输出表类型[impala]|是|| -| url | 连接postgresql数据库 jdbcUrl |是|| -| userName | postgresql连接用户名 |是|| -| password | postgresql连接密码|是|| -| tableName | postgresqll表名称|是|| -| authMech | 身份验证机制 (0, 1, 2, 3),暂不支持kerberos |是|0| -| principal | kerberos用于登录的principal(authMech=1时独有) |authMech=1为必填| -| keyTabFilePath | keytab文件的路径(authMech=1时独有) |authMech=1为必填 || -| krb5FilePath | krb5.conf文件路径(authMech=1时独有) |authMech=1为必填|| -| krbHostFQDN | 主机的标准域名(authMech=1时独有) |authMech=1为必填 || -| krbServiceName | Impala服务器的Kerberos principal名称(authMech=1时独有) |authMech=1为必填|| -| krbRealm | Kerberos的域名(authMech=1时独有) |否| HADOOP.COM | -| enablePartition | 是否支持分区 |否|false| -| partitionFields | 分区字段名|否,enablePartition='true'时为必填|| -| parallelism | 并行度设置|否|1| -| parallelism | 并行度设置|否|1| -|updateMode| 只支持APPEND模式,过滤掉回撤数据||| - - -## 5.样例: -``` -CREATE TABLE MyTable( - channel VARCHAR, - pt int, - xctime varchar, - name varchar - )WITH( - type ='kafka11', - bootstrapServers ='172.16.8.107:9092', - zookeeperQuorum ='172.16.8.107:2181/kafka', - offsetReset ='latest', - topic ='mqTest03' - ); - -CREATE TABLE MyResult( - a STRING, - b STRING - )WITH( - type ='impala', - url ='jdbc:impala://172.16.101.252:21050/hxbho_pub', - userName ='root', - password ='pwd', - authMech ='3', - tableName ='tb_result_4', - parallelism ='1', - -- 指定分区 - partitionFields = 'pt=1001,name="name1001" ', - batchSize = '1000', - parallelism ='2' - ); - -CREATE TABLE MyResult1( - a STRING, - b STRING, - pt int, - name STRING - )WITH( - type ='impala', - url ='jdbc:impala://172.16.101.252:21050/hxbho_pub', - userName ='root', - password ='Wscabc123..@', - authMech ='3', - tableName ='tb_result_4', - parallelism ='1', - enablePartition ='true', - -- 动态分区 - partitionFields = 'pt,name ', - batchSize = '1000', - parallelism ='2' - ); - - -insert -into - MyResult1 - select - xctime AS b, - channel AS a, - pt, - name - from - MyTable; - - - -insert -into - MyResult - select - xctime AS b, - channel AS a - from - MyTable; - - - - - ``` diff --git a/docs/plugin/kafkaSink.md b/docs/plugin/kafkaSink.md deleted file mode 100644 index b3a1614bc..000000000 --- a/docs/plugin/kafkaSink.md +++ /dev/null @@ -1,249 +0,0 @@ -## 1.格式: -``` -CREATE TABLE tableName( - colName colType, - ... - function(colNameX) AS aliasName, - WATERMARK FOR colName AS withOffset( colName , delayTime ) - )WITH( - type ='kafka11', - bootstrapServers ='ip:port,ip:port...', - zookeeperQuorum ='ip:port,ip:port/zkparent', - offsetReset ='latest', - topic ='topicName', - groupId='test', - parallelism ='parllNum', - ); -``` - -## 2.支持的版本 - kafka09,kafka10,kafka11及以上版本 - **kafka读取和写入的版本必须一致,否则会有兼容性错误。** - -## 3.表结构定义 - -|参数名称|含义| -|----|---| -| tableName | 在 sql 中使用的名称;即注册到flink-table-env上的名称| -| colName | 列名称| -| colType | 列类型 [colType支持的类型](../colType.md)| - -## 4.参数: - -|参数名称|含义|是否必填|默认值| -|----|---|---|---| -|type | kafka09 | 是|kafka09、kafka10、kafka11、kafka(对应kafka1.0及以上版本)| -|groupId | 需要读取的 groupId 名称|否|| -|bootstrapServers | kafka bootstrap-server 地址信息(多个用逗号隔开)|是|| -|zookeeperQuorum | kafka zk地址信息(多个之间用逗号分隔)|是|| -|topic | 需要读取的 topic 名称|是|| -|parallelism | 并行度设置|否|1| -|partitionKeys | 用来分区的字段|否|| -|updateMode | 回溯流数据下发模式,append,upsert.upsert模式下会将是否为回溯信息以字段形式进行下发。|否|append| -|sinkdatatype | 写入kafka数据格式,json,avro,csv|否|json| -|fieldDelimiter | csv数据分隔符|否| , | - - -**kafka相关参数可以自定义,使用kafka.开头即可。** -``` -kafka.consumer.id -kafka.socket.timeout.ms -kafka.fetch.message.max.bytes -kafka.num.consumer.fetchers -kafka.auto.commit.enable -kafka.auto.commit.interval.ms -kafka.queued.max.message.chunks -kafka.rebalance.max.retries -kafka.fetch.min.bytes -kafka.fetch.wait.max.ms -kafka.rebalance.backoff.ms -kafka.refresh.leader.backoff.ms -kafka.consumer.timeout.ms -kafka.exclude.internal.topics -kafka.partition.assignment.strategy -kafka.client.id -kafka.zookeeper.session.timeout.ms -kafka.zookeeper.connection.timeout.ms -kafka.zookeeper.sync.time.ms -kafka.offsets.storage -kafka.offsets.channel.backoff.ms -kafka.offsets.channel.socket.timeout.ms -kafka.offsets.commit.max.retries -kafka.dual.commit.enabled -kafka.partition.assignment.strategy -kafka.socket.receive.buffer.bytes -kafka.fetch.min.bytes -``` - -## 5.样例: - -### json格式: -``` -CREATE TABLE MyResult( - channel varchar, - pv varchar - )WITH( - type='kafka', - bootstrapServers='172.16.8.107:9092', - topic='mqTest02', - parallelism ='2', - partitionKeys = 'channel,pv', - updateMode='upsert' - ); - -upsert模式下发的数据格式:{"channel":"zs","pv":"330",retract:true} -append模式下发的数据格式:{"channel":"zs","pv":"330"} - -``` - -### avro格式: - -如果updateMode='upsert',schemaInfo需要包含retract属性信息。 - -``` -CREATE TABLE MyTable( - channel varchar, - pv varchar - --xctime bigint - )WITH( - type='kafka', - bootstrapServers='172.16.8.107:9092', - groupId='mqTest01', - offsetReset='latest', - topic='mqTest01', - parallelism ='1', - topicIsPattern ='false' - ); - -create table sideTable( - channel varchar, - xccount int, - PRIMARY KEY(channel), - PERIOD FOR SYSTEM_TIME - )WITH( - type='mysql', - url='jdbc:mysql://172.16.8.109:3306/test?charset=utf8', - userName='dtstack', - password='abc123', - tableName='sidetest', - cache = 'LRU', - cacheTTLMs='10000', - parallelism ='1' - - ); - - -CREATE TABLE MyResult( - channel varchar, - pv varchar - )WITH( - --type='console' - type='kafka', - bootstrapServers='172.16.8.107:9092', - topic='mqTest02', - parallelism ='1', - updateMode='upsert', - sinkdatatype = 'avro', - schemaInfo = '{"type":"record","name":"MyResult","fields":[{"name":"channel","type":"string"} - ,{"name":"pv","type":"string"},{"name":"channel","type":"string"}, - {"name":"retract","type":"boolean"}]}' - - ); - - -insert -into - MyResult - select - a.channel as channel, - a.pv as pv - from - MyTable a -``` -### csv格式: - -``` -CREATE TABLE MyTable( - channel varchar, - pv varchar - --xctime bigint - )WITH( - type='kafka', - bootstrapServers='172.16.8.107:9092', - groupId='mqTest01', - offsetReset='latest', - topic='mqTest01', - parallelism ='2', - topicIsPattern ='false' - ); - -create table sideTable( - channel varchar, - xccount int, - PRIMARY KEY(channel), - PERIOD FOR SYSTEM_TIME - )WITH( - type='mysql', - url='jdbc:mysql://172.16.8.109:3306/test?charset=utf8', - userName='dtstack', - password='abc123', - tableName='sidetest', - cache = 'LRU', - cacheTTLMs='10000', - parallelism ='1' - - ); - - -CREATE TABLE MyResult( - channel varchar, - pv varchar - )WITH( - type='kafka', - bootstrapServers='172.16.8.107:9092', - topic='mqTest02', - parallelism ='2', - updateMode='upsert', - sinkdatatype = 'csv', - fieldDelimiter='*' - - - - ); - - -insert -into - MyResult - select - a.channel as channel, - a.pv as pv - from - MyTable a -``` -## MAP类型示例 -目前Kafka Sink支持Map类型 -```sql -CREATE TABLE ods( - id INT, - name STRING -) WITH ( - ... -); - -CREATE TABLE dwd ( - id INT, - dids MAP> -) WITH ( - type ='kafka', - bootstrapServers ='localhost:9092', - offsetReset ='latest', - groupId='wuren_foo', - topic ='luna_foo', - parallelism ='1' -); - -INSERT INTO dwd - SELECT ods.id, MAP['foo', 1, 'bar', 2] AS dids - FROM ods; -``` diff --git a/docs/plugin/kafkaSource.md b/docs/plugin/kafkaSource.md deleted file mode 100644 index c2f69e260..000000000 --- a/docs/plugin/kafkaSource.md +++ /dev/null @@ -1,317 +0,0 @@ -## 1.格式: -``` - -CREATE TABLE tableName( - colName colType, - ... - function(colNameX) AS aliasName, - WATERMARK FOR colName AS withOffset( colName , delayTime ) - )WITH( - type ='kafka09', - bootstrapServers ='ip:port,ip:port...', - zookeeperQuorum ='ip:port,ip:port/zkparent', - offsetReset ='latest', - topic ='topicName', - groupId='test', - parallelism ='parllNum', - timezone='Asia/Shanghai', - sourcedatatype ='dt_nest' #可不设置 - ); -``` - -## 2.支持的版本 - kafka09,kafka10,kafka11及以上版本 - **kafka读取和写入的版本必须一致,否则会有兼容性错误。** - -## 3.表结构定义 - -|参数名称|含义| -|----|---| -| tableName | 在 sql 中使用的名称;即注册到flink-table-env上的名称| -| colName | 列名称| -| colType | 列类型 [colType支持的类型](../colType.md)| -| function(colNameX) as aliasName | 支持在定义列信息的时候根据已有列类型生成新的列(函数可以使用系统函数和已经注册的UDF)| -| WATERMARK FOR colName AS withOffset( colName , delayTime ) | 标识输入流生的watermake生成规则,根据指定的colName(当前支持列的类型为Long | Timestamp) 和delayTime生成waterMark 同时会在注册表的使用附带上rowtime字段(如果未指定则默认添加proctime字段);注意:添加该标识的使用必须设置系统参数 time.characteristic:EventTime; delayTime: 数据最大延迟时间(ms)| - -## 4.参数: - -|参数名称|含义|是否必填|默认值| -|----|---|---|---| -|type | kafka09 | 是|kafka09、kafka10、kafka11、kafka(对应kafka1.0及以上版本)| -|groupId | 需要读取的 groupId 名称|否|| -|bootstrapServers | kafka bootstrap-server 地址信息(多个用逗号隔开)|是|| -|zookeeperQuorum | kafka zk地址信息(多个之间用逗号分隔)|是|| -|topic | 需要读取的 topic 名称|是|| -|topicIsPattern | topic是否是正则表达式格式(true|false) |否| false -|offsetReset | 读取的topic 的offset初始位置[latest|earliest|指定offset值({"0":12312,"1":12321,"2":12312},{"partition_no":offset_value})]|否|latest| -|offsetEnd | 任务停止时的offset位置|否|无| -|parallelism | 并行度设置|否|1| -|sourcedatatype | 数据类型,avro,csv,json,dt_nest。dt_nest为默认JSON解析器,能够解析嵌套JSON数据类型,其他仅支持非嵌套格式|否|dt_nest| -|schemaInfo | avro类型使用的schema信息|否|| -|fieldDelimiter |csv类型使用的数据分隔符|否| | | -|timezone|时区设置[timezone支持的参数](../timeZone.md)|否|'Asia/Shanghai' -**kafka相关参数可以自定义,使用kafka.开头即可。** -``` -kafka.consumer.id -kafka.socket.timeout.ms -kafka.fetch.message.max.bytes -kafka.num.consumer.fetchers -kafka.auto.commit.enable -kafka.auto.commit.interval.ms -kafka.queued.max.message.chunks -kafka.rebalance.max.retries -kafka.fetch.min.bytes -kafka.fetch.wait.max.ms -kafka.rebalance.backoff.ms -kafka.refresh.leader.backoff.ms -kafka.consumer.timeout.ms -kafka.exclude.internal.topics -kafka.partition.assignment.strategy -kafka.client.id -kafka.zookeeper.session.timeout.ms -kafka.zookeeper.connection.timeout.ms -kafka.zookeeper.sync.time.ms -kafka.offsets.storage -kafka.offsets.channel.backoff.ms -kafka.offsets.channel.socket.timeout.ms -kafka.offsets.commit.max.retries -kafka.dual.commit.enabled -kafka.partition.assignment.strategy -kafka.socket.receive.buffer.bytes -kafka.fetch.min.bytes - -###kerberos认证相关参数 -kafka.security.protocal -kafka.sasl.mechanism -kafka.sasl.kerberos.service.name -``` - -## 5.样例: -``` -CREATE TABLE MyTable( - name varchar, - channel varchar, - pv INT, - xctime bigint, - CHARACTER_LENGTH(channel) AS timeLeng - )WITH( - type ='kafka09', - bootstrapServers ='172.16.8.198:9092', - zookeeperQuorum ='172.16.8.198:2181/kafka', - offsetReset ='latest', - topic ='nbTest1,nbTest2,nbTest3', - --topic ='mqTest.*', - --topicIsPattern='true' - parallelism ='1', - sourcedatatype ='json' #可不设置 - ); - - CREATE TABLE two -( - id int, - name string, - message string -) WITH ( - type = 'kafka11', - bootstrapServers = 'kudu1:9092,kudu2:9092,kudu3:9092', - zookeeperQuorum = 'kudu1:2181,kudu2:2181,kudu3:2181/kafka', - offsetReset = '{"0": 0,"1": 0,"2":0}', --- offsetReset = '{"0": 34689}', --- offsetReset = 'earliest', - offsetEnd = '{"0": 100,"1": 100,"2":100}', --- offsetEnd = '{"0": 34789}', - topic = 'kafka' - ); -``` -## 6.支持嵌套json、数据类型字段解析 - -嵌套json解析示例 - -json: {"name":"tom", "obj":{"channel": "root"}, "pv": 4, "xctime":1572932485} -``` -CREATE TABLE MyTable( - name varchar, - obj.channel varchar as channel, - pv INT, - xctime bigint, - CHARACTER_LENGTH(channel) AS timeLeng - )WITH( - type ='kafka09', - bootstrapServers ='172.16.8.198:9092', - zookeeperQuorum ='172.16.8.198:2181/kafka', - offsetReset ='latest', - groupId='nbTest', - topic ='nbTest1,nbTest2,nbTest3', - --- topic ='mqTest.*', - ---topicIsPattern='true', - parallelism ='1' - ); -``` - -#### 数组类型字段解析示例 - -声明数据类型为Array可以使用CROSS JOIN UNNEST语句对Array类型进行展开。(新模式,推荐) - -json样例 -``` -{ - "id": 2, - "some_users": [ - "foo", - "bar" - ] -} -``` - -SQL样例 -``` -CREATE TABLE ods ( - id INT, - some_users ARRAY -) WITH ( - ... -); - -CREATE TABLE dwd ( - id INT, - user_no INT, - user_info VARCHAR -) WITH ( - type ='console', -); - -INSERT INTO dwd - SELECT id, user_info - FROM ods_foo - CROSS JOIN UNNEST(ods_foo.some_users) AS A (user_info); -``` - -json样例 -``` -{ - "id": 4, - "some_users": [ - { - "user_no": 12, - "user_info": "foo" - - }, - { - "user_no": 14, - "user_info": "bar" - } - ] -} -``` - -SQL样例 -``` -CREATE TABLE ods ( - id INT, - some_users ARRAY> -) WITH ( - ... -); - -CREATE TABLE dwd ( - id INT, - user_no INT, - user_info VARCHAR -) WITH ( - type ='console', -); - -INSERT INTO dwd - SELECT id, user_no, user_info - FROM ods_foo - CROSS JOIN UNNEST(ods_foo.some_users) AS A (user_no, user_info); -``` -##### 旧模式 - -json: {"name":"tom", "obj":{"channel": "root"}, "user": [{"pv": 4}, {"pv": 10}], "xctime":1572932485} -``` -CREATE TABLE MyTable( - name varchar, - obj.channel varchar as channel, - user[1].pv INT as pv, - xctime bigint, - CHARACTER_LENGTH(channel) AS timeLeng - )WITH( - type ='kafka09', - bootstrapServers ='172.16.8.198:9092', - zookeeperQuorum ='172.16.8.198:2181/kafka', - offsetReset ='latest', - groupId='nbTest', - topic ='nbTest1,nbTest2,nbTest3', - --- topic ='mqTest.*', - ---topicIsPattern='true', - parallelism ='1' - ); -``` -or - -json: {"name":"tom", "obj":{"channel": "root"}, "pv": [4, 7, 10], "xctime":1572932485} -``` -CREATE TABLE MyTable( - name varchar, - obj.channel varchar as channel, - pv[1] INT as pv, - xctime bigint, - CHARACTER_LENGTH(channel) AS timeLeng - )WITH( - type ='kafka09', - bootstrapServers ='172.16.8.198:9092', - zookeeperQuorum ='172.16.8.198:2181/kafka', - offsetReset ='latest', - groupId='nbTest', - topic ='nbTest1,nbTest2,nbTest3', - --- topic ='mqTest.*', - ---topicIsPattern='true', - parallelism ='1' - ); -``` - -## 7.csv格式数据源 - - -``` -CREATE TABLE MyTable( - name varchar, - channel varchar, - pv INT, - xctime bigint, - CHARACTER_LENGTH(channel) AS timeLeng - )WITH( - type ='kafka09', - bootstrapServers ='172.16.8.198:9092', - zookeeperQuorum ='172.16.8.198:2181/kafka', - offsetReset ='latest', - topic ='nbTest1', - --topic ='mqTest.*', - --topicIsPattern='true' - parallelism ='1', - sourceDatatype ='csv' - ); - ``` -## 8.avro格式数据源 - -``` -CREATE TABLE MyTable( - channel varchar, - pv varchar - --xctime bigint - )WITH( - type='kafka', - bootstrapServers='172.16.8.107:9092', - groupId='mqTest01', - offsetReset='latest', - topic='mqTest01', - parallelism ='1', - topicIsPattern ='false', - kafka.group.id='mqTest', - sourceDataType ='avro', - schemaInfo = '{"type":"record","name":"MyResult","fields":[{"name":"channel","type":"string"},{"name":"pv","type":"string"}]}' - ); - -``` - diff --git a/docs/plugin/kuduSide.md b/docs/plugin/kuduSide.md deleted file mode 100644 index 3075c3f35..000000000 --- a/docs/plugin/kuduSide.md +++ /dev/null @@ -1,187 +0,0 @@ -## 1.格式 - 通过建表语句中的` PERIOD FOR SYSTEM_TIME`将表标识为维表,其中`PRIMARY KEY(keyInfo)`中的keyInfo,表示用来和源表进行关联的字段, - 维表JOIN的条件必须与`keyInfo`字段一致。 -``` - CREATE TABLE tableName( - colName cloType, - ... - PRIMARY KEY(colName1,colName2) , - PERIOD FOR SYSTEM_TIME - )WITH( - type ='kudu', - kuduMasters ='ip1,ip2,ip3', - tableName ='impala::default.testSide', - primaryKey='id,xx', - lowerBoundPrimaryKey='10,xx', - upperBoundPrimaryKey='15,xx', - workerCount='1', - defaultOperationTimeoutMs='600000', - defaultSocketReadTimeoutMs='6000000', - batchSizeBytes='100000000', - limitNum='1000', - isFaultTolerant='false', - cache ='LRU', - cacheSize ='10000', - cacheTTLMs ='60000', - parallelism ='1', - partitionedJoin='false' - ); -``` -## 2.支持版本 - kudu 1.10.0+cdh6.2.0 - -## 3.表结构定义 - - |参数名称|含义| - |----|---| - | tableName | 注册到flink的表名称(可选填;不填默认和hbase对应的表名称相同)| - | colName | 列名称| - | colType | 列类型 [colType支持的类型](../colType.md)| - | PERIOD FOR SYSTEM_TIME | 关键字表明该定义的表为维表信息| - | PRIMARY KEY(keyInfo) | 维表主键定义;多个列之间用逗号隔开| - -## 4.参数 - -参数详细说明请看[参数详细说明](sideParams.md) - -|参数名称|含义|是否必填|默认值| -|----|---|---|-----| -| type | 表明维表的类型[hbase|mysql|kudu]|是|| -| kuduMasters | kudu master节点的地址;格式ip[ip,ip2]|是|| -| tableName | kudu 的表名称|是|| -| workerCount | 工作线程数 |否|| -| defaultOperationTimeoutMs | scan操作超时时间 |否|| -| defaultSocketReadTimeoutMs | socket读取超时时间 |否|| -| primaryKey | 需要过滤的主键 ALL模式独有 |否|| -| lowerBoundPrimaryKey | 需要过滤的主键的最小值 ALL模式独有 |否|| -| upperBoundPrimaryKey | 需要过滤的主键的最大值(不包含) ALL模式独有 |否|| -| batchSizeBytes |返回数据的大小 | 否|| -| limitNum |返回数据的条数 | 否|| -| isFaultTolerant |查询是否容错 查询失败是否扫描第二个副本 默认false 容错 | 否|| -| cache | 维表缓存策略(NONE/LRU/ALL)|否|NONE| -| partitionedJoin | 是否在維表join之前先根据 設定的key 做一次keyby操作(可以減少维表的数据缓存量)|否|false| -| principal |kerberos用于登录的principal | 否|| -| keytab |keytab文件的路径 | 否|| -| krb5conf |conf文件路径 | 否|| -Kerberos三个参数全部设置则开启Kerberos认证,如果缺少任何一个则会提示缺少参数错误。 -如果全部未设置则不开启Kerberos连接Kudu集群。 --------------- - -## 5.样例 -### LRU维表示例 -``` -create table sideTable( - id int, - tablename1 VARCHAR, - PRIMARY KEY(id), - PERIOD FOR SYSTEM_TIME - )WITH( - type='kudu', - kuduMasters ='ip1,ip2,ip3', - tableName ='impala::default.testSide', - cache ='LRU', - partitionedJoin='false' - ); -``` -### ALL维表示例 -``` -create table sideTable( - id int, - tablename1 VARCHAR, - PRIMARY KEY(id), - PERIOD FOR SYSTEM_TIME - )WITH( - type='kudu', - kuduMasters ='ip1,ip2,ip3', - tableName ='impala::default.testSide', - cache ='ALL', - primaryKey='id,xx', - lowerBoundPrimaryKey='10,xx', - upperBoundPrimaryKey='15,xx', - partitionedJoin='false' - ); -``` - -## 6.kudu异步关联完整样例 - -``` -CREATE TABLE MyTable( - id bigint, - name varchar, - address varchar -)WITH( - type = 'kafka10', - bootstrapServers = '172.16.101.224:9092', - zookeeperQuorm = '172.16.100.188:2181/kafka', - offsetReset = 'latest', - topic = 'tiezhu_test_in2', - timezone = 'Asia/Shanghai', - topicIsPattern = 'false', - parallelism = '1' -); - -CREATE TABLE sideTable( - id int, - message varchar, - PRIMARY KEY(id), - PERIOD FOR SYSTEM_TIME -)WITH( - type='kudu', - kuduMasters ='ip1,ip2,ip3', - tableName ='impala::default.testSide', - cache ='LRU', - partitionedJoin='false' -); - -CREATE TABLE MyResult( - id bigint, - name varchar, - address varchar, - message varchar -)WITH( - type ='console', - address ='192.168.80.106:9042,192.168.80.107:9042', - userName='cassandra', - password='cassandra', - database ='tiezhu', - tableName ='stu_out', - parallelism ='1' -); - -insert -into - MyResult - select - t1.id AS id, - t1.name AS name, - t1.address AS address, - t2.message AS message - from( - select - id, - name, - address - from - MyTable - ) t1 - join sideTable t2 - on t1.id = t2.id; -``` - -## 7.kerberos示例 -``` -create table dim ( - name varchar, - id int, - PERIOD FOR SYSTEM_TIME -) WITH ( - type='kudu', - kuduMasters='host1', - tableName='foo', - parallelism ='1', - cache ='ALL', - keytab='foo/foobar.keytab', - krb5conf='bar/krb5.conf', - principal='kudu/host1@DTSTACK.COM' -); -``` \ No newline at end of file diff --git a/docs/plugin/kuduSink.md b/docs/plugin/kuduSink.md deleted file mode 100644 index 9e407e3aa..000000000 --- a/docs/plugin/kuduSink.md +++ /dev/null @@ -1,147 +0,0 @@ -## 1.格式: -``` -CREATE TABLE tableName( - colName colType, - ... - colNameX colType - )WITH( - type ='kudu', - kuduMasters ='ip1,ip2,ip3', - tableName ='impala::default.test', - writeMode='upsert', - workerCount='1', - defaultOperationTimeoutMs='600000', - defaultSocketReadTimeoutMs='6000000', - parallelism ='parllNum' - ); - - -``` - -## 2.支持版本 -kudu 1.9.0+cdh6.2.0 - -## 3.表结构定义 - -|参数名称|含义| -|----|---| -| tableName | 在 sql 中使用的名称;即注册到flink-table-env上的名称 -| colName | 列名称,redis中存储为 表名:主键名:主键值:列名]| -| colType | 列类型 [colType支持的类型](../colType.md)| - - -## 4.参数: - -|参数名称|含义|是否必填|默认值| -|----|---|---|-----| -| type | 表名 输出表类型[mysq|hbase|elasticsearch|redis|kudu]|是|| -| kuduMasters | kudu master节点的地址;格式ip[ip,ip2]|是|| -| tableName | kudu 的表名称|是|| -| writeMode | 写入kudu的模式 insert|update|upsert |否 |upsert -| workerCount | 工作线程数 |否| -| defaultOperationTimeoutMs | 操作超时时间 |否| -| defaultSocketReadTimeoutMs | socket读取超时时间 |否| -| parallelism | 并行度设置|否|1| -| principal |kerberos用于登录的principal | 否|| -| keytab |keytab文件的路径 | 否|| -| krb5conf |conf文件路径 | 否|| -Kerberos三个参数全部设置则开启Kerberos认证,如果缺少任何一个则会提示缺少参数错误。 -如果全部未设置则不开启Kerberos连接Kudu集群。 - -## 5.样例: -``` -CREATE TABLE MyTable( - channel varchar, - name varchar, - pv varchar, - a varchar, - b varchar - )WITH( - type ='kafka11', - bootstrapServers ='172.16.8.107:9092', - zookeeperQuorum ='172.16.8.107:2181/kafka', - offsetReset ='latest', - topic ='es_test', - timezone='Asia/Shanghai', - updateMode ='append', - enableKeyPartitions ='false', - topicIsPattern ='false', - parallelism ='1' - ); - -CREATE TABLE MyResult( - a string, - b string, - c string, - d string - )WITH( - type ='kudu', - kuduMasters ='cdh03.cdhsite:7051', - tableName ='myresult', - writeMode='insert', - parallelism ='1' - ); - -CREATE TABLE sideTable( - c string, - d string, - PRIMARY KEY(c) , - PERIOD FOR SYSTEM_TIME - )WITH( - type ='kudu', - kuduMasters ='cdh03.cdhsite:7051', - tableName ='sidetest4', - partitionedJoin ='false', - cache ='LRU', - cacheSize ='10000', - cacheTTLMs ='60000', - parallelism ='1', - primaryKey ='c', - isFaultTolerant ='false' - ); - -insert -into - MyResult - select - MyTable.a, - MyTable.b, - s.c, - s.d - from - MyTable - join - sideTable s - on MyTable.a = s.c - where - MyTable.a='2' - and s.d='2' - - ``` - -## 6.数据示例 -### 输入数据 -``` -{"channel":"daishuyun","name":"roc","pv":"10","a":"2","b":"2"} -``` -### 结果数据 -``` -{"a":"2","b":"2","c":"3","d":"4"} -``` - -## 7.kerberos示例 -``` -create table dwd ( - name varchar, - id int -) WITH ( - type='kudu', - kuduMasters='host1', - tableName='foo', - writeMode='insert', - parallelism ='1', - keytab='foo/foobar.keytab', - krb5conf='bar/krb5.conf', - principal='kudu/host1@DTSTACK.COM' -); -``` diff --git a/docs/plugin/mongoSide.md b/docs/plugin/mongoSide.md deleted file mode 100644 index 9ff52b85c..000000000 --- a/docs/plugin/mongoSide.md +++ /dev/null @@ -1,148 +0,0 @@ - -## 1.格式: -``` - CREATE TABLE tableName( - colName cloType, - ... - PRIMARY KEY(keyInfo), - PERIOD FOR SYSTEM_TIME - )WITH( - type ='mongo', - address ='ip:port[,ip:port]', - userName='dbUserName', - password='dbPwd', - tableName='tableName', - database='database', - cache ='LRU', - cacheSize ='10000', - cacheTTLMs ='60000', - parallelism ='1', - partitionedJoin='false' - ); -``` - -# 2.支持版本 - mongo-3.8.2 - -## 3.表结构定义 - - [通用维表参数信息](sideParams.md) - - - mongo相关参数配置: - -|参数名称|含义|是否必填|默认值| -|----|---|---|----| -| type |表明 输出表类型 mongo|是|| -| address | 连接mongo数据库 jdbcUrl |是|| -| userName | mongo连接用户名|否|| -| password | mongo连接密码|否|| -| tableName | mongo表名称|是|| -| database | mongo表名称|是|| - -## 4.样例 - - -### 全量维表结构 - -```aidl -CREATE TABLE source2( - id int, - address VARCHAR, - PERIOD FOR SYSTEM_TIME -)WITH( - type ='mongo', - address ='172.16.8.193:27017', - database ='dtstack', - tableName ='userInfo', - cache ='ALL', - parallelism ='1', - partitionedJoin='false' -); -``` - -### 异步维表结构 - -```aidl -CREATE TABLE source2( - id int, - address VARCHAR, - PERIOD FOR SYSTEM_TIME -)WITH( - type ='mongo', - address ='172.16.8.193:27017', - database ='dtstack', - tableName ='userInfo', - cache ='LRU', - parallelism ='1', - partitionedJoin='false' -); - -``` - -### 异步维表关联样例 - -``` - -CREATE TABLE source1 ( - id int, - name VARCHAR -)WITH( - type ='kafka11', - bootstrapServers ='172.16.8.107:9092', - zookeeperQuorum ='172.16.8.107:2181/kafka', - offsetReset ='latest', - topic ='mqTest03', - timezone='Asia/Shanghai', - topicIsPattern ='false' - ); - - -CREATE TABLE source2( - id int, - address VARCHAR, - PERIOD FOR SYSTEM_TIME -)WITH( - type ='mongo', - address ='172.16.8.193:27017', - database ='dtstack', - tableName ='userInfo', - cache ='ALL', - parallelism ='1', - partitionedJoin='false' -); - - -CREATE TABLE MyResult( - id int, - name VARCHAR, - address VARCHAR, - primary key (id) -)WITH( - type='console' -); - -insert into MyResult -select - s1.id, - s1.name, - s2.address -from - source1 s1 -left join - source2 s2 -on - s1.id = s2.id - - -``` - - -维表数据:{"id": 1001,"address":"hz""} - -源表数据:{"name":"maqi","id":1001} - - -输出结果: (1001,maqi,hz) - - diff --git a/docs/plugin/mongoSink.md b/docs/plugin/mongoSink.md deleted file mode 100644 index 9eea6fd89..000000000 --- a/docs/plugin/mongoSink.md +++ /dev/null @@ -1,109 +0,0 @@ -## 1.格式: -``` -CREATE TABLE tableName( - colName colType, - ... - colNameX colType - )WITH( - type ='mongo', - address ='ip:port[,ip:port]', - userName ='userName', - password ='pwd', - database ='databaseName', - tableName ='tableName', - parallelism ='parllNum' - ); - -``` - -## 2.支持版本 - mongo-3.8.2 - -## 3.表结构定义 - -|参数名称|含义| -|----|---| -| tableName| 在 sql 中使用的名称;即注册到flink-table-env上的名称| -| colName | 列名称| -| colType | 列类型 [colType支持的类型](../colType.md)| - -## 4.参数: - -|参数名称|含义|是否必填|默认值| -|----|----|----|----| -|type |表明 输出表类型 mongo|是|| -|address | 连接mongo数据库 jdbcUrl |是|| -|userName | mongo连接用户名|否|| -|password | mongo连接密码|否|| -|tableName | mongo表名称|是|| -|database | mongo表名称|是|| -|parallelism | 并行度设置|否|1| - -## 5.样例: - -双流join并插入mongo - -``` - -CREATE TABLE source1 ( - id int, - name VARCHAR -)WITH( - type ='kafka11', - bootstrapServers ='172.16.8.107:9092', - zookeeperQuorum ='172.16.8.107:2181/kafka', - offsetReset ='latest', - topic ='mqTest03', - timezone='Asia/Shanghai', - topicIsPattern ='false' - ); - - - -CREATE TABLE source2( - id int, - address VARCHAR -)WITH( - type ='kafka11', - bootstrapServers ='172.16.8.107:9092', - zookeeperQuorum ='172.16.8.107:2181/kafka', - offsetReset ='latest', - topic ='mqTest04', - timezone='Asia/Shanghai', - topicIsPattern ='false' -); - - -CREATE TABLE MyResult( - id int, - name VARCHAR, - address VARCHAR, - primary key (id) -)WITH( - type ='mongo', - address ='172.16.8.193:27017', - database ='dtstack', - tableName ='userInfo' -); - -insert into MyResult -select - s1.id, - s1.name, - s2.address -from - source1 s1 -left join - source2 s2 -on - s1.id = s2.id - - - ``` - - - ## 数据结果示例 - - 向Topic mqTest03 发送数据 {"name":"maqi","id":1001} 插入 (1001,"maqi",null) - - 向Topic mqTest04 发送数据 {"address":"hz","id":1001} 插入 (1001,"maqi","hz") \ No newline at end of file diff --git a/docs/plugin/mysqlSide.md b/docs/plugin/mysqlSide.md deleted file mode 100644 index a4247ef0a..000000000 --- a/docs/plugin/mysqlSide.md +++ /dev/null @@ -1,156 +0,0 @@ - -## 1.格式: - - 通过建表语句中的` PERIOD FOR SYSTEM_TIME`将表标识为维表,其中`PRIMARY KEY(keyInfo)`中的keyInfo,表示用来和源表进行关联的字段, - 维表JOIN的条件必须与`keyInfo`字段一致。 - -``` - CREATE TABLE tableName( - colName cloType, - ... - PRIMARY KEY(keyInfo), - PERIOD FOR SYSTEM_TIME - )WITH( - type='mysql', - url='jdbcUrl', - userName='dbUserName', - password='dbPwd', - tableName='tableName', - cache ='LRU', - cacheSize ='10000', - cacheTTLMs ='60000', - parallelism ='1', - partitionedJoin='false' - ); -``` - -# 2.支持版本 - mysql-5.6.35 - -## 3.表结构定义 - - [维表参数信息](sideParams.md) - - mysql独有的参数配置: - - -|参数名称|含义|是否必填|默认值| -|----|---|---|----| -| type | 维表类型, mysql |是|| -| url | 连接数据库 jdbcUrl |是|| -| userName | 连接用户名 |是|| -| password | 连接密码|是|| - - - -## 4.样例 - -### ALL全量维表定义 -``` - // 定义全量维表 -CREATE TABLE sideTable( - id INT, - name VARCHAR, - PRIMARY KEY(id) , - PERIOD FOR SYSTEM_TIME - )WITH( - type ='mysql', - url ='jdbc:mysql://172.16.10.204:3306/mqtest', - userName ='dtstack', - password ='1abc123', - tableName ='test_mysql_10', - cache ='ALL', - cacheTTLMs ='60000', - parallelism ='2' - ); - -``` -### LRU异步维表定义 - -``` -CREATE TABLE sideTable( - id INT, - name VARCHAR, - PRIMARY KEY(id) , - PERIOD FOR SYSTEM_TIME - )WITH( - type ='mysql', - url ='jdbc:mysql://172.16.10.204:3306/mqtest', - userName ='dtstack', - password ='1abc123', - tableName ='yctest_mysql_10', - partitionedJoin ='false', - cache ='LRU', - cacheSize ='10000', - cacheTTLMs ='60000', - asyncPoolSize ='3', - parallelism ='2' - ); - -``` - - -### MySQL异步维表关联 -``` -CREATE TABLE MyTable( - id int, - name varchar - )WITH( - type ='kafka11', - bootstrapServers ='172.16.8.107:9092', - zookeeperQuorum ='172.16.8.107:2181/kafka', - offsetReset ='latest', - topic ='cannan_yctest01', - timezone='Asia/Shanghai', - enableKeyPartitions ='false', - topicIsPattern ='false', - parallelism ='1' - ); - -CREATE TABLE MyResult( - id INT, - name VARCHAR - )WITH( - type ='mysql', - url ='jdbc:mysql://172.16.10.204:3306/mqtest', - userName ='dtstack', - password ='1abc123', - tableName ='yctest_mysql_mq', - updateMode ='append', - parallelism ='1', - batchSize ='100', - batchWaitInterval ='1000' - ); - -CREATE TABLE sideTable( - id INT, - name VARCHAR, - PRIMARY KEY(id) , - PERIOD FOR SYSTEM_TIME - )WITH( - type ='mysql', - url ='jdbc:mysql://172.16.10.204:3306/mqtest', - userName ='dtstack', - password ='1abc123', - tableName ='yctest_mysql_10', - partitionedJoin ='false', - cache ='LRU', - cacheSize ='10000', - cacheTTLMs ='60000', - asyncPoolSize ='3', - parallelism ='1' - ); - -insert -into - MyResult - select - m.id, - s.name - from - MyTable m - join - sideTable s - on m.id=s.id; - -``` \ No newline at end of file diff --git a/docs/plugin/mysqlSink.md b/docs/plugin/mysqlSink.md deleted file mode 100644 index d54c36b28..000000000 --- a/docs/plugin/mysqlSink.md +++ /dev/null @@ -1,103 +0,0 @@ -## 1.格式: -``` -CREATE TABLE tableName( - colName colType, - ... - colNameX colType, - [primary key (colName)] - )WITH( - type ='mysql', - url ='jdbcUrl', - userName ='userName', - password ='pwd', - tableName ='tableName', - parallelism ='parllNum' - ); - -``` - -## 2.支持版本 - mysql-5.6.35 - -## 3.表结构定义 - -|参数名称|含义| -|----|---| -| tableName| 结果表名称| -| colName | 列名称| -| colType | 列类型 [colType支持的类型](../colType.md)| - -## 4.参数: - -|参数名称|含义|是否必填|默认值| -|----|----|----|----| -|type |表名 输出表类型[mysq|hbase|elasticsearch]|是|| -|url | 连接mysql数据库 jdbcUrl |是|| -|userName | mysql连接用户名 |是|| -|password | mysql连接密码|是|| -|tableName | mysql表名称|是|| -|parallelism | 并行度设置|否|1| -|batchSize | flush的大小|否|100| -|batchWaitInterval | flush的时间间隔,单位ms|否|1000| -|allReplace| true:新值替换旧值|否|false| -|updateMode| APPEND:不回撤数据,只下发增量数据,UPSERT:先删除回撤数据,然后更新|否|结果表设置主键则为UPSERT| - -## 5.完整样例: -``` -CREATE TABLE MyTable( - id int, - channel varchar, - pv varchar, - xctime varchar, - name varchar - )WITH( - type ='kafka10', - bootstrapServers ='172.16.8.107:9092', - zookeeperQuorum ='172.16.8.107:2181/kafka', - offsetReset ='latest', - topic ='es_test', - timezone='Asia/Shanghai', - topicIsPattern ='false', - parallelism ='1' - ); - -CREATE TABLE MyResult( - pv VARCHAR, - channel VARCHAR - )WITH( - type ='mysql', - url ='jdbc:mysql://172.16.10.134:3306/test', - userName ='dtstack', - password ='abc123', - tableName ='myresult', - parallelism ='1' - ); - - -insert -into - MyResult - select - channel, - pv - from - MyTable - ``` - -## 6.结果表数据示例: -``` -mysql> desc myresult; -+---------+--------------+------+-----+---------+-------+ -| Field | Type | Null | Key | Default | Extra | -+---------+--------------+------+-----+---------+-------+ -| channel | varchar(255) | YES | | NULL | | -| pv | varchar(11) | YES | | NULL | | -+---------+--------------+------+-----+---------+-------+ -2 rows in set (0.00 sec) - -mysql> select * from myresult limit 1; -+---------+------+ -| channel | pv | -+---------+------+ -| aa | mq6 | -``` \ No newline at end of file diff --git a/docs/plugin/oracleSide.md b/docs/plugin/oracleSide.md deleted file mode 100644 index feb99a1ee..000000000 --- a/docs/plugin/oracleSide.md +++ /dev/null @@ -1,159 +0,0 @@ - -## 1.格式: - - 通过建表语句中的` PERIOD FOR SYSTEM_TIME`将表标识为维表,其中`PRIMARY KEY(keyInfo)`中的keyInfo,表示用来和源表进行关联的字段, - 维表JOIN的条件必须与`keyInfo`字段一致。 - - 此外, 针对oracle char类型自动补齐的特性,我们允许为char指定长度,确保维表查询时能够匹配数据。 - - - 注意:Oracle维表使用的字段大小写,需要和Oracle中定义的保持一致。 -``` - CREATE TABLE tableName( - colName cloType, - ... - PRIMARY KEY(keyInfo), - PERIOD FOR SYSTEM_TIME - )WITH( - type='oracle', - url='jdbcUrl', - userName='dbUserName', - password='dbPwd', - tableName='tableName', - cache ='LRU', - schema = 'MQTEST', - parallelism ='1', - partitionedJoin='false' - ); -``` - -# 2.支持版本 - 10g 11g - -## 3. 表结构定义 - [维表参数](sideParams.md) - - - oracle独有的参数配置: - - |参数名称|含义|是否必填|默认值| - |----|---|---|----| - | type | 维表类型, oracle |是|| - | url | 连接数据库 jdbcUrl |是|| - | userName | 连接用户名 |是|| - | password | 连接密码|是|| - | schema| 表空间|否|| - -## 4.样例 - -### ALL全量维表定义 -``` -CREATE TABLE sideTable( - ID char(20), // oracle定义了char(20) - NAME varchar, - PRIMARY KEY (ID), - PERIOD FOR SYSTEM_TIME - )WITH( - type='oracle', - url = 'jdbc:oracle:thin:@172.16.8.178:1521:xe', - userName = 'system', - password = 'oracle', - tableName = 'SIDETEST1', - schema = 'dtstack', - cache = 'ALL', - cacheTTLMs ='60000' - ); -``` - -### LRU异步维表定义 - -``` -create table sideTable( - channel char, - xccount int, - PRIMARY KEY(channel), - PERIOD FOR SYSTEM_TIME - )WITH( - type='oracle', - url='jdbc:oracle:thin:@xx.xx.xx.xx:1521:orcl', - userName='xx', - password='xx', - tableName='sidetest', - cache ='LRU', - cacheSize ='10000', - cacheTTLMs ='60000', - cacheMode='unordered', - asyncCapacity='1000', - asyncTimeout='10000' - parallelism ='1', - partitionedJoin='false', - schema = 'MQTEST' - ); - -``` - -### Oracle异步维表关联 - -```aidl -CREATE TABLE MyTable( - id varchar, - name varchar - --ts timestamp, - --tsDate Date - )WITH( - type ='kafka11', - bootstrapServers ='172.16.8.107:9092', - zookeeperQuorum ='172.16.8.107:2181/kafka', - offsetReset ='latest', - topic ='mqTest01', - timezone='Asia/Shanghai', - topicIsPattern ='false', - parallelism ='1' - ); - - -CREATE TABLE sideTable( - ID char(20), - NAME varchar, - PRIMARY KEY (ID), - PERIOD FOR SYSTEM_TIME - )WITH( - type='oracle', - url = 'jdbc:oracle:thin:@172.16.8.178:1521:xe', - userName = 'system', - password = 'oracle', - tableName = 'SIDETEST1', - --schema = 'dtstack', - cache = 'LRU', - asyncPoolSize ='3' - ); - - -CREATE TABLE MyResult( - NAME varchar, - ID char(20), - PRIMARY KEY (ID) - )WITH( - --type ='console', - type='oracle', - url = 'jdbc:oracle:thin:@172.16.8.178:1521:xe', - userName = 'system', - password = 'oracle', - tableName = 'SINK_TEST', - batchSize='1' - ); - - - -INSERT INTO MyResult -SELECT - s.ID as ID, - m.name as NAME -FROM MyTable m -LEFT JOIN - sideTable s -ON - m.id=s.ID -``` - - diff --git a/docs/plugin/oracleSink.md b/docs/plugin/oracleSink.md deleted file mode 100644 index 40c5836e9..000000000 --- a/docs/plugin/oracleSink.md +++ /dev/null @@ -1,103 +0,0 @@ -## 1.格式: -``` -CREATE TABLE tableName( - colName colType, - ... - colNameX colType - )WITH( - type ='oracle', - url ='jdbcUrl', - userName ='userName', - password ='pwd', - tableName ='tableName', - parallelism ='parllNum' - ); - -``` - -## 2.支持版本 - 10g 11g - -## 3.表结构定义 - -|参数名称|含义| -|----|---| -| tableName| oracle表名称| -| colName | 列名称| -| colType | 列类型 [colType支持的类型](../colType.md)| - -## 4.参数: - -|参数名称|含义|是否必填|默认值| -|----|----|----|----| -|type |表名 输出表类型[mysq|hbase|elasticsearch|oracle]|是|| -|url | 连接oracle数据库 jdbcUrl |是|| -|userName | oracle连接用户名 |是|| -| password | oracle连接密码|是|| -| tableName | oracle表名称|是|| -| schema | oracle 的schema|否|当前登录用户| -| parallelism | 并行度设置|否|1| -| batchSize | flush的大小|否|100| -| batchWaitInterval | flush的时间间隔,单位ms|否|1000| -| allReplace | true:新值替换旧值|否|false| -| updateMode | APPEND:不回撤数据,只下发增量数据,UPSERT:先删除回撤数据,然后更新|否|结果表设置主键则为UPSERT| - - -## 5.样例: -``` -CREATE TABLE MyTable( - name varchar, - channel varchar, - id int - )WITH( - type ='kafka10', - bootstrapServers ='172.16.8.107:9092', - zookeeperQuorum ='172.16.8.107:2181/kafka', - offsetReset ='latest', - topic ='mqTest01', - timezone='Asia/Shanghai', - updateMode ='append', - enableKeyPartitions ='false', - topicIsPattern ='false', - parallelism ='1' - ); - - CREATE TABLE MyResult( - primarykey_id int , - name VARCHAR, - address VARCHAR - )WITH( - type ='oracle', - url ='jdbc:oracle:thin:@172.16.8.178', - userName ='system', - password ='oracle', - tableName ='YELUO_TEST_ORACLE_01', - updateMode ='append', - parallelism ='1', - batchSize ='100', - batchWaitInterval ='1000' - ); - -insert -into - MyResult - select - id as primarykey_id, - channel as address, - name - from - MyTable a - ``` - -## 6.数据示例 -### 输入数据 -``` -{"name":"roc","id":11,"channel":"daishuyun"} -``` -### 结果数据 -``` -+---------+------+------+-----------+ -| primarykey_id | name | address | -+---------+------+------+----------+ -| 11 | roc | daishuyun | -``` \ No newline at end of file diff --git a/docs/plugin/postgresqlSide.md b/docs/plugin/postgresqlSide.md deleted file mode 100644 index 43fdffeee..000000000 --- a/docs/plugin/postgresqlSide.md +++ /dev/null @@ -1,155 +0,0 @@ -## 1.格式: - -通过建表语句中的` PERIOD FOR SYSTEM_TIME`将表标识为维表,其中`PRIMARY KEY(keyInfo)`中的keyInfo,表示用来和源表进行关联的字段, - 维表JOIN的条件必须与`keyInfo`字段一致。 - -``` - CREATE TABLE tableName( - colName cloType, - ... - PRIMARY KEY(keyInfo), - PERIOD FOR SYSTEM_TIME - )WITH( - type='postgresql', - url='jdbcUrl', - userName='dbUserName', - password='dbPwd', - tableName='tableName', - cache ='LRU', - cacheSize ='10000', - cacheTTLMs ='60000', - parallelism ='1', - partitionedJoin='false' - ); -``` - -# 2.支持版本 - - postgresql-8.2+ - -## 3.表结构定义 - - [维表参数信息](sideParams.md) - -postgresql独有的参数配置 - -| 参数名称 | 含义 | 是否必填 | 默认值 | -| -------- | ------------------ | -------- | ------ | -| type | 维表类型, mysql | 是 | | -| url | 连接数据库 jdbcUrl | 是 | | -| userName | 连接用户名 | 是 | | -| password | 连接密码 | 是 | | - -## 4.样例 - -### ALL全量维表定义 - -```sql - // 定义全量维表 -CREATE TABLE sideTable( - id INT, - name VARCHAR, - PRIMARY KEY(id) , - PERIOD FOR SYSTEM_TIME - )WITH( - type ='postgresql', - url ='jdbc:postgresql://172.16.10.194:5432/zftest', - userName ='dtstack', - password ='abc123', - tableName ='all_test_postgresql', - cache ='ALL', - cacheTTLMs ='60000', - parallelism ='1' - ); -``` - -### LRU异步维表定义 - -```sql -CREATE TABLE sideTable( - id INT, - name VARCHAR, - PRIMARY KEY(id) , - PERIOD FOR SYSTEM_TIME - )WITH( - type ='postgresql', - url ='jdbc:postgresql://172.16.10.194:5432/zftest', - userName ='dtstack', - password ='abc123', - tableName ='lru_test_postgresql', - partitionedJoin ='false', - cache ='LRU', - cacheSize ='10000', - cacheTTLMs ='60000', - asyncPoolSize ='3', - parallelism ='1' - ); - -``` - -### PostgreSQL异步维表关联 - -```sql -CREATE TABLE MyTable( - id int, - name varchar - )WITH( - type ='kafka11', - bootstrapServers ='172.16.8.107:9092', - zookeeperQuorum ='172.16.8.107:2181/kafka', - offsetReset ='latest', - topic ='cannan_zftest01', - timezone='Asia/Shanghai', - enableKeyPartitions ='false', - topicIsPattern ='false', - parallelism ='1' - ); - -CREATE TABLE MyResult( - id INT, - name VARCHAR - )WITH( - type ='postgresql', - url ='jdbc:postgresql://172.16.10.194:5432/zftest', - userName ='dtstack', - password ='abc123', - tableName ='test_postgresql_zf', - updateMode ='append', - parallelism ='1', - batchSize ='100', - batchWaitInterval ='1000' - ); - -CREATE TABLE sideTable( - id INT, - name VARCHAR, - PRIMARY KEY(id) , - PERIOD FOR SYSTEM_TIME - )WITH( - type ='postgresql', - url ='jdbc:postgresql://172.16.10.194:5432/zftest', - userName ='dtstack', - password ='abc123', - tableName ='test_postgresql_10', - partitionedJoin ='false', - cache ='LRU', - cacheSize ='10000', - cacheTTLMs ='60000', - asyncPoolSize ='3', - parallelism ='1' - ); - -insert -into - MyResult - select - m.id, - s.name - from - MyTable m - join - sideTable s - on m.id=s.id; - -``` - diff --git a/docs/plugin/postgresqlSink.md b/docs/plugin/postgresqlSink.md deleted file mode 100644 index bc9f98fc0..000000000 --- a/docs/plugin/postgresqlSink.md +++ /dev/null @@ -1,120 +0,0 @@ -## 1.格式: -``` -CREATE TABLE tableName( - colName colType, - ... - colNameX colType, - primary key (colName) - )WITH( - type ='postgresql', - url ='jdbcUrl', - userName ='userName', - password ='pwd', - tableName ='tableName', - parallelism ='parllNum' - ); - -``` - -## 2.支持版本 - postgresql-9.5+ - -## 3.表结构定义 - -|参数名称|含义| -|----|---| -| tableName| 在 sql 中使用的名称;即注册到flink-table-env上的名称| -| colName | 列名称| -| colType | 列类型 [colType支持的类型](../colType.md)| -| primary key | updateMode为UPSERT时,需要指定的主键信息| - - -## 4.参数: - -|参数名称|含义|是否必填|默认值| -|----|----|----|----| -|type |结果表插件类型,必须为postgresql|是|| -|url | 连接postgresql数据库 jdbcUrl |是|| -|userName |postgresql连接用户名 |是|| -|password | postgresql连接密码|是|| -|tableName | postgresql表名称|是|| -|schema | postgresql表空间|否|| -|parallelism | 并行度设置|否|1| -|batchSize | flush的大小|否|100| -|batchWaitInterval | flush的时间间隔,单位ms|否|1000| -|allReplace| true:新值替换旧值|否|false| -|updateMode| APPEND:不回撤数据,只下发增量数据,UPSERT:先删除回撤数据,然后更新|否|结果表设置主键则为UPSERT| - -## 5.样例: - -回溯流删除 - -``` - -CREATE TABLE source1 ( - id int, - name VARCHAR -)WITH( - type ='kafka11', - bootstrapServers ='172.16.8.107:9092', - zookeeperQuorum ='172.16.8.107:2181/kafka', - offsetReset ='latest', - topic ='mqTest03', - timezone='Asia/Shanghai', - topicIsPattern ='false' - ); - - - -CREATE TABLE source2( - id int, - address VARCHAR -)WITH( - type ='kafka11', - bootstrapServers ='172.16.8.107:9092', - zookeeperQuorum ='172.16.8.107:2181/kafka', - offsetReset ='latest', - topic ='mqTest04', - timezone='Asia/Shanghai', - topicIsPattern ='false' -); - - -CREATE TABLE MyResult( - id int, - name VARCHAR, - address VARCHAR, - primary key (id) -)WITH( - type='postgresql', - url='jdbc:postgresql://172.16.8.193:5432/DTstack', - userName='root', - password='123456', - tableName='userInfo', - schema = 'aaa', - updateMode = 'upsert', - batchSize = '1' -); - -insert into MyResult -select - s1.id, - s1.name, - s2.address -from - source1 s1 -left join - source2 s2 -on - s1.id = s2.id - - - - ``` - - -数据结果: - -向Topic mqTest03 发送数据 {"name":"maqi","id":1001} 插入 (1001,"maqi",null) - -向Topic mqTest04 发送数据 {"address":"hz","id":1001} 删除 (1001,"maqi",null) 插入 (1001,"maqi","hz") diff --git a/docs/plugin/redisSide.md b/docs/plugin/redisSide.md deleted file mode 100644 index 5a037c763..000000000 --- a/docs/plugin/redisSide.md +++ /dev/null @@ -1,173 +0,0 @@ - -## 1.格式 -``` - CREATE TABLE tableName( - colName cloType, - ... - PRIMARY KEY(colName1,colName2) , - PERIOD FOR SYSTEM_TIME - )WITH( - type ='redis', - url = 'ip:port', - password = 'redisPwd', - database = 'dbName', - tableName ='sideTableName', - redisType = '1', - cache ='LRU', - cacheSize ='10000', - cacheTTLMs ='60000', - parallelism ='1', - partitionedJoin='false' - ); -``` -## 2.支持版本 - redis5.0 - -## 3.表结构定义 -注意:redis中没有表和schema的概念,参数中tableName是指符合命名规则的key,具体规则请看[缓存redis的存储命名规则] - -|参数名称|含义| -|----|---| -| tableName | 注册到flinkStreamSql的表名称(可选填;不填默认和redis对应的"表"名称相同)| -| colName | 列名称,对应redis对应"表"的field| -| colType | 列类型,当前只支持varchar| -| PRIMARY KEY |主键,多个字段做为联合主键时以逗号分隔| -| PERIOD FOR SYSTEM_TIME | 关键字,表明该定义的表为维表信息| - -## 4.参数 - -参数详细说明请看[参数详细说明](sideParams.md) - -|参数名称|含义|是否必填|默认值| -|----|---|---|----| -| type | 表明维表的类型[hbase|mysql|redis]|是|| -| url | redis 的地址;格式ip:port[,ip:port]|是|| -| password | redis 的密码 |否|空| -| redisType | redis模式(1 单机,2 哨兵, 3 集群)| 是 | -| masterName | 主节点名称(哨兵模式下为必填项) | 否 | -| database | reids 的数据库地址|否|0| -| tableName | redis 的“表”名称|是|| -| cache | 维表缓存策略(NONE/LRU/ALL)|否|NONE| -| partitionedJoin | 是否在維表join之前先根据 設定的key 做一次keyby操作(可以減少维表的数据缓存量)|否|false| --------------- - -## 5.样例 -### LRU维表示例 -``` -CREATE TABLE MyRedis( - id varchar, - message varchar, - PRIMARY KEY(id), - PERIOD FOR SYSTEM_TIME -)WITH( - type='redis', - url='172.16.10.79:6379', - password='abc123', - database='0', - redisType = '1', - tableName = 'sideTable', - cache = 'LRU', - cacheSize ='10000', - cacheTTLMs ='60000', - parallelism ='1', - partitionedJoin='false' -); -``` -### ALL维表示例 -``` -CREATE TABLE MyRedis( - id varchar, - message varchar, - PRIMARY KEY(id), - PERIOD FOR SYSTEM_TIME -)WITH( - type='redis', - url='172.16.10.79:6379', - password='abc123', - database='0', - redisType = '1', - tableName = 'sideTable', - cache = 'ALL', - cacheTTLMs ='60000', - parallelism ='1', - partitionedJoin='false' -); -``` - -## 6.redis完整样例 - -### redis数据说明 - -redis使用散列类型 hash 数据结构,key=tableName_primaryKey1_primaryKey2,value={column1=value1, column2=value2} -如果以班级class表为例,id和name作为联合主键,那么redis的结构为 - -在样例中,tableName为sideTable,主键为id,column为id,message,所以对应的redis数据插入语句为 - -数据在redis中对应的数据存储情况为: -``` -192.168.80.105:6379> hgetall sideTable_5 -1) "id" -2) "5" -3) "message" -4) "redis" -``` - -### redis异步维表关联完整案例 -``` -CREATE TABLE MyTable( - id varchar, - name varchar, - address varchar -)WITH( - type = 'kafka10', - bootstrapServers = '172.16.101.224:9092', - zookeeperQuorm = '172.16.100.188:2181/kafka', - offsetReset = 'latest', - topic = 'tiezhu_test_in2', - groupId = 'flink_sql', - timezone = 'Asia/Shanghai', - topicIsPattern = 'false', - parallelism = '1' -); - -CREATE TABLE MyRedis( - id varchar, - message varchar, - PRIMARY KEY(id), - PERIOD FOR SYSTEM_TIME -)WITH( - type='redis', - url='172.16.10.79:6379', - password='abc123', - database='0', - redisType = '1', - tableName = 'sideTable', - cache = 'LRU', - cacheSize ='10000', - cacheTTLMs ='60000', - parallelism ='1', - partitionedJoin='false' -); - -CREATE TABLE MyResult( - id varchar, - name varchar, - address varchar, - message varchar -)WITH( - type = 'console' -); - -insert into MyResult - select - t1.id AS id, - t1.name AS name, - t1.address AS address, - t2.message AS message - from( - select id, name, address - from MyTable - ) t1 join MyRedis t2 - on t1.id = t2.id; -``` - diff --git a/docs/plugin/redisSink.md b/docs/plugin/redisSink.md deleted file mode 100644 index 32e05f37e..000000000 --- a/docs/plugin/redisSink.md +++ /dev/null @@ -1,197 +0,0 @@ -## 1.格式: - -```sql -CREATE TABLE flinkTableName( - colName colType, - ... - colNameX colType, - PRIMARY KEY (colName, ..., colNameX) - )WITH( - type ='redis', - url = 'ip:port', - database ='dbName', - password ='pwd', - redisType='1/2/3', - tableName ='tableName', - parallelism ='parallelismNum' - ); -``` - -## 2.支持版本 - -redis5.x, redis6.x - -## 3.表结构定义 - -在redis结果表中,实际的数据使用hash的格式存储,其中,key的组合为tableName_primaryKeys。详细请看《7.Redis数据说明》 - -|参数名称|含义| -|----|---| -| flinkTableName | 在 sql 中使用的名称;即注册到flink-table-env上的名称 -| colName | 列名称| -| colType | 列类型| - -## 4.参数: - -|参数名称|含义|是否必填|默认值| -|----|---|---|-----| -| type | 表名 输出表类型[mysq|hbase|elasticsearch|redis]|是|| -| url | redis 的地址;格式ip:port[,ip:port]|是|| -| password | redis 的密码 |是|| -| redisType | redis模式(1 单机,2 哨兵, 3 集群)| 是 | -| masterName | 主节点名称(哨兵模式下为必填项) | 否 | -| database | redis 的数据库地址|否|| -| tableName | redis 的表名称|是|| -| parallelism | 并行度设置|否|1| -| timeout | 连接超时时间|否|10000| -| maxTotal |最大连接数|否|8| -| maxIdle |最大空闲连接数|否|8| -| minIdle |最小空闲连接数|否||0| -| masterName | 哨兵模式下的masterName|否|| -| keyExpiredTime |redis sink的key的过期时间。默认是0(永不过期),单位是s。|否|| - -## 5.样例: - -```sql - CREATE TABLE MyResult - ( - channel VARCHAR, - pv VARCHAR, - PRIMARY KEY (pv) - ) WITH ( - type = 'redis', - redisType = '1', - url = '172.16.8.109:6379', - tableName = 'resultTable', - partitionedJoin = 'false', - parallelism = '1', - database = '0', - timeout = '10000', - maxTotal = '60000', - maxIdle = '8', - minIdle = '0' - ); - -``` - -## 6.redis完整样例 - -```sql --- source -CREATE TABLE SourceOne -( - id INT, - age BIGINT, - birth TIMESTAMP, - todayTime TIME, - todayDate DATE, - price DECIMAL, - name VARCHAR, - phone VARCHAR, - wechat VARCHAR, - qq VARCHAR -) WITH ( - type = 'kafka11', - bootstrapServers = 'kudu1:9092', - zookeeperQuorum = 'kudu1:2181', - offsetReset = 'latest', - topic = 'tiezhu_in', - enableKeyPartitions = 'false', - topicIsPattern = 'false' - ); - - -CREATE TABLE SinkOne -( - id INT, - age BIGINT, - birth TIMESTAMP, - todayTime TIME, - todayDate DATE, - price DECIMAL, - name VARCHAR, - phone VARCHAR, - wechat VARCHAR, - qq VARCHAR, - PRIMARY KEY (id, name) -) WITH ( - type = 'redis', - url = 'kudu1:6379', - database = '0', - -- (1 单机,2 哨兵, 3 集群) - redisType = '1', - tableName = 'demo', - partitionedJoin = 'false' - ); - -CREATE VIEW ViewOne AS -SELECT id, - age, - birth, - todayTime, - todayDate, - price, - name, - phone, - wechat, - qq -FROM SourceOne SO; - -INSERT INTO SinkOne -SELECT * -FROM ViewOne; - -``` - -## 7.redis数据说明 - -redis使用散列类型 hash 数据结构,key=tableName_primaryKey1_primaryKey2,value={column1=value1, column2=value2} -如果以班级class表为例,id和name作为联合主键,那么redis的结构为 - -### 源表数据内容 - -```json -{ - "qq":63595541541, - "todayTime":"10:19:40", - "wechat":"微信号81850", - "birth":"2021-01-19 10:19:40.075", - "todayDate":"2021-01-19", - "phone":18649852461, - "price":1.4, - "name":"tiezhu2", - "id":2, - "age":19 -} -``` - -### redis实际数据内容 - -```shell -kudu1_redis_docker:0>keys * -1) "demo_2_tiezhu2" -2) "demo_4_tiezhu2" -3) "demo_3_yuange" -kudu1_redis_docker:0>hgetall demo_2_tiezhu2 -1) "qq" -2) "63595541541" -3) "todayTime" -4) "10:19:40" -5) "phone" -6) "18649852461" -7) "price" -8) "1.400000000000000000" -9) "name" -10) "tiezhu2" -11) "wechat" -12) "微信号81850" -13) "birth" -14) "2021-01-19 10:19:40.075" -15) "id" -16) "2" -17) "todayDate" -18) "2021-01-19" -19) "age" -20) "19" -kudu1_redis_docker:0> -``` \ No newline at end of file diff --git a/docs/plugin/sideParams.md b/docs/plugin/sideParams.md deleted file mode 100644 index 6059dcab8..000000000 --- a/docs/plugin/sideParams.md +++ /dev/null @@ -1,39 +0,0 @@ -## 维表参数 - - -### 维表参数 - -维表需要的基本属性,每个插件还需要提供连接所需的基本信息。 - -|参数名称|含义|是否必填|默认值| -|----|---|---|----| -| type | 维表类型, 例如:mysql |是|| -| tableName| 表名称|是|| -| cache | 维表缓存策略(NONE/LRU/ALL)|否|LRU| -| partitionedJoin | 是否在維表join之前先根据设定的key 做一次keyby操作(可以減少维表的数据缓存量)|否|false| -| parallelism | 处理后的数据流并行度|否|| - -### 缓存策略 - -- NONE:不做内存缓存。每条流数据触发一次维表查询操作。 -- ALL: 任务启动时,一次性加载所有数据到内存,并进行缓存。适用于维表数据量较小的情况。 -- LRU: 任务执行时,根据维表关联条件使用异步算子加载维表数据,并进行缓存。 - -#### ALL全量维表参数 - -|参数名称|含义|默认值| -|----|---|----| -| cacheTTLMs | 缓存周期刷新时间 |60,单位s| - -#### LRU异步维表参数 - -|参数名称|含义|默认值| -|----|---|----| -| cacheTTLMs | LRU缓存写入后超时时间 |60,单位s| -| cacheSize | LRU缓存大小 |10000| -| cacheMode | 异步请求处理有序还是无序,可选:ordered,unordered |ordered| -| asyncCapacity | 异步线程容量 |100| -| asyncTimeout | 异步处理超时时间 |10000,单位毫秒| -| asyncPoolSize | 异步查询DB最大线程池,上限20。适用于MYSQL,ORACLE,SQLSERVER,POSTGRESQL,DB2,POLARDB,CLICKHOUSE,IMPALA维表插件|min(20,Runtime.getRuntime().availableProcessors() * 2)| - - diff --git a/docs/plugin/sqlserverSide.md b/docs/plugin/sqlserverSide.md deleted file mode 100644 index 90d036fd2..000000000 --- a/docs/plugin/sqlserverSide.md +++ /dev/null @@ -1,156 +0,0 @@ -## 1.格式: - -通过建表语句中的` PERIOD FOR SYSTEM_TIME`将表标识为维表,其中`PRIMARY KEY(keyInfo)`中的keyInfo,表示用来和源表进行关联的字段, - 维表JOIN的条件必须与`keyInfo`字段一致。 - -```sql - CREATE TABLE tableName( - colName cloType, - ... - PRIMARY KEY(keyInfo), - PERIOD FOR SYSTEM_TIME - )WITH( - type='sqlserver', - url='jdbcUrl', - userName='dbUserName', - password='dbPwd', - tableName='tableName', - cache ='LRU', - cacheSize ='10000', - cacheTTLMs ='60000', - parallelism ='1', - partitionedJoin='false' - ); -``` - -## 2.支持版本 - - mysql-5.6.35 - -## 3.表结构定义 - - [维表参数信息](sideParams.md) - -sqlserver独有的参数配置 - -| 参数名称 | 含义 | 是否必填 | 默认值 | -| -------- | -------------------- | -------- | ------ | -| type | 维表类型, sqlserver | 是 | | -| url | 连接数据库 jdbcUrl | 是 | | -| userName | 连接用户名 | 是 | | -| password | 连接密码 | 是 | | - -## 4.样例 - -### ALL全量维表定义 - -```sql - // 定义全量维表 -CREATE TABLE sideTable( - id INT, - name VARCHAR, - PRIMARY KEY(id) , - PERIOD FOR SYSTEM_TIME - )WITH( - type ='sqlserver', - url ='jdbc:jtds:sqlserver://172.16.8.104:1433;DatabaseName=mytest', - userName ='dtstack', - password ='abc123', - tableName ='all_test_sqlserver', - cache ='ALL', - cacheTTLMs ='60000', - parallelism ='1' - ); -``` - - -### LRU异步维表定义 - -```sql -create table sideTable( - channel varchar, - xccount int, - PRIMARY KEY(channel), - PERIOD FOR SYSTEM_TIME - )WITH( - type='sqlserver', - url='jdbc:jtds:sqlserver://172.16.8.104:1433;DatabaseName=mytest', - userName='dtstack', - password='abc123', - tableName=',ru_test_sqlserver', - cache ='LRU', - cacheSize ='10000', - cacheTTLMs ='60000', - parallelism ='1', - partitionedJoin='false' - ); - - -``` - -### PostSQL异步维表关联 - -```sql -CREATE TABLE MyTable( - id int, - name varchar - )WITH( - type ='kafka11', - bootstrapServers ='172.16.8.107:9092', - zookeeperQuorum ='172.16.8.107:2181/kafka', - offsetReset ='latest', - topic ='cannan_yctest01', - timezone='Asia/Shanghai', - enableKeyPartitions ='false', - topicIsPattern ='false', - parallelism ='1' - ); - -CREATE TABLE MyResult( - id INT, - name VARCHAR - )WITH( - type='sqlserver', - url='jdbc:jtds:sqlserver://172.16.8.104:1433;DatabaseName=mytest', - userName='dtstack', - password='abc123', - tableName ='test_sqlserver_zf', - updateMode ='append', - parallelism ='1', - batchSize ='100', - batchWaitInterval ='1000' - ); - -CREATE TABLE sideTable( - id INT, - name VARCHAR, - PRIMARY KEY(id) , - PERIOD FOR SYSTEM_TIME - )WITH( - type='sqlserver', - url='jdbc:jtds:sqlserver://172.16.8.104:1433;DatabaseName=mytest', - userName='dtstack', - password='abc123', - tableName ='test_sqlserver_10', - partitionedJoin ='false', - cache ='LRU', - cacheSize ='10000', - cacheTTLMs ='60000', - asyncPoolSize ='3', - parallelism ='1' - ); - -insert -into - MyResult - select - m.id, - s.name - from - MyTable m - join - sideTable s - on m.id=s.id; - -``` - diff --git a/docs/plugin/sqlserverSink.md b/docs/plugin/sqlserverSink.md deleted file mode 100644 index 4b82898fd..000000000 --- a/docs/plugin/sqlserverSink.md +++ /dev/null @@ -1,115 +0,0 @@ -## 1.格式: -``` -CREATE TABLE tableName( - colName colType, - ... - colNameX colType, - primary key (colName) - )WITH( - type ='sqlserver', - url ='jdbcUrl', - userName ='userName', - password ='pwd', - tableName ='tableName', - parallelism ='parllNum' - ); - -``` - -## 2.支持版本 - sqlserver-5.6.35 - -## 3.表结构定义 - -|参数名称|含义| -|----|---| -| tableName| sqlserver表名称| -| colName | 列名称| -| colType | 列类型 [colType支持的类型](../colType.md)| -| primary key | updateMode为UPSERT时,需要指定的主键信息| - -## 4.参数: - -|参数名称|含义|是否必填|默认值| -|----|----|----|----| -|type |结果表插件类型,必须为sqlserver|是|| -|url | 连接sqlserver数据库 jdbcUrl |是|| -|userName |sqlserver连接用户名 |是|| -|password | sqlserver连接密码|是|| -|tableName | sqlserver表名称|是|| -|schema | sqlserver表空间|否|| -|parallelism | 并行度设置|否|1| -|batchSize | flush的大小|否|100| -|batchWaitInterval | flush的时间间隔,单位ms|否|1000| -|allReplace| true:新值替换旧值|否|false| -|updateMode| APPEND:不回撤数据,只下发增量数据,UPSERT:先删除回撤数据,然后更新|否|| - - -## 5.样例: - -回溯流删除 -``` - -CREATE TABLE source1 ( - id int, - name VARCHAR -)WITH( - type ='kafka11', - bootstrapServers ='172.16.8.107:9092', - zookeeperQuorum ='172.16.8.107:2181/kafka', - offsetReset ='latest', - topic ='mqTest03', - timezone='Asia/Shanghai', - topicIsPattern ='false' - ); - - -CREATE TABLE source2( - id int, - address VARCHAR -)WITH( - type ='kafka11', - bootstrapServers ='172.16.8.107:9092', - zookeeperQuorum ='172.16.8.107:2181/kafka', - offsetReset ='latest', - topic ='mqTest04', - timezone='Asia/Shanghai', - topicIsPattern ='false' -); - - -CREATE TABLE MyResult( - id int, - name VARCHAR, - address VARCHAR, - primary key (id) -)WITH( - type='sqlserver', - url='jdbc:jtds:sqlserver://172.16.8.149:1433;DatabaseName=DTstack', - userName='sa', - password='Dtstack2018', - tableName='user', - schema = 'aaa', - updateMode = 'upsert', - batchSize = '1' -); - -insert into MyResult -select - s1.id, - s1.name, - s2.address -from - source1 s1 -left join - source2 s2 -on - s1.id = s2.id - - ``` - -数据结果: - -向Topic mqTest03 发送数据 {"name":"maqi","id":1001} 插入 (1001,"maqi",null) - -向Topic mqTest04 发送数据 {"address":"hz","id":1001} 删除 (1001,"maqi",null) 插入 (1001,"maqi","hz") diff --git a/docs/pluginsInfo.md b/docs/pluginsInfo.md deleted file mode 100644 index 391cbb502..000000000 --- a/docs/pluginsInfo.md +++ /dev/null @@ -1,38 +0,0 @@ -### 1 插件列表 -#### 1.1 源表插件 -* [kafka 源表插件](plugin/kafkaSource.md) - -#### 1.2 结果表插件 -* [kafka 结果表插件](plugin/kafkaSink.md) -* [elasticsearch5 结果表插件](plugin/elasticsearch5Sink.md) -* [elasticsearch6 结果表插件](plugin/elasticsearch6Sink.md) -* [elasticsearch7 结果表插件](plugin/elasticsearch7Sink.md) -* [hbase 结果表插件](plugin/hbaseSink.md) -* [mysql 结果表插件](plugin/mysqlSink.md) -* [oracle 结果表插件](plugin/oracleSink.md) -* [mongo 结果表插件](plugin/mongoSink.md) -* [redis 结果表插件](plugin/redisSink.md) -* [cassandra 结果表插件](plugin/cassandraSink.md) -* [kudu 结果表插件](plugin/kuduSink.md) -* [postgresql 结果表插件](plugin/postgresqlSink.md) -* [clickhouse 结果表插件](plugin/clickhouseSink.md) -* [impala 结果表插件](plugin/impalaSink.md) -* [db2 结果表插件](plugin/db2Sink.md) -* [sqlserver 结果表插件](plugin/sqlserverSink.md) -* [http 结果表插件](plugin/httpSink.md) - -#### 1.3 维表插件 -* [hbase 维表插件](plugin/hbaseSide.md) -* [mysql 维表插件](plugin/mysqlSide.md) -* [elasticsearch6 维表插件](plugin/elasticsearch6Side.md) -* [elasticsearch7 维表插件](plugin/elasticsearch7Side.md) -* [oracle 维表插件](plugin/oracleSide.md) -* [mongo 维表插件](plugin/mongoSide.md) -* [redis 维表插件](plugin/redisSide.md) -* [cassandra 维表插件](plugin/cassandraSide.md) -* [kudu 维表插件](plugin/kuduSide.md) -* [postgresql 维表插件](plugin/postgresqlSide.md) -* [clickhouse 维表插件](plugin/clickhouseSide.md) -* [impala 维表插件](plugin/impalaSide.md) -* [db2 维表插件](plugin/db2Side.md) -* [sqlserver 维表插件](plugin/sqlserverSide.md) diff --git a/docs/postgresqlSide.md b/docs/postgresqlSide.md new file mode 100644 index 000000000..68d10b869 --- /dev/null +++ b/docs/postgresqlSide.md @@ -0,0 +1,80 @@ + +## 1.格式: +``` + CREATE TABLE tableName( + colName cloType, + ... + PRIMARY KEY(keyInfo), + PERIOD FOR SYSTEM_TIME + )WITH( + type='postgresql', + url='jdbcUrl', + userName='dbUserName', + password='dbPwd', + tableName='tableName', + cache ='LRU', + cacheSize ='10000', + cacheTTLMs ='60000', + parallelism ='1', + partitionedJoin='false' + ); +``` + +# 2.支持版本 + postgresql-8.2+ + +## 3.表结构定义 + + |参数名称|含义| + |----|---| + | tableName | 注册到flink的表名称(可选填;不填默认和hbase对应的表名称相同)| + | colName | 列名称| + | colType | 列类型 [colType支持的类型](colType.md)| + | PERIOD FOR SYSTEM_TIME | 关键字表明该定义的表为维表信息| + | PRIMARY KEY(keyInfo) | 维表主键定义;多个列之间用逗号隔开| + +## 4.参数 + + |参数名称|含义|是否必填|默认值| + |----|---|---|----| + | type | 表明维表的类型[postgresql] |是|| + | url | 连接postgresql数据库 jdbcUrl |是|| + | userName | postgresql连接用户名 |是|| + | password | postgresql连接密码|是|| + | tableName | postgresql表名称|是|| + | tableName | postgresql 的表名称|是|| + | cache | 维表缓存策略(NONE/LRU/ALL)|否|NONE| + | partitionedJoin | 是否在維表join之前先根据 設定的key 做一次keyby操作(可以減少维表的数据缓存量)|否|false| + + ---------- + > 缓存策略 + * NONE: 不做内存缓存 + * LRU: + * cacheSize: 缓存的条目数量 + * cacheTTLMs:缓存的过期时间(ms) + + +## 5.样例 +``` +create table sideTable( + channel varchar, + xccount int, + PRIMARY KEY(channel), + PERIOD FOR SYSTEM_TIME + )WITH( + type='postgresql', + url='jdbc:postgresql://localhost:9001/test?sslmode=disable', + userName='dtstack', + password='abc123', + tableName='sidetest', + cache ='LRU', + cacheSize ='10000', + cacheTTLMs ='60000', + parallelism ='1', + partitionedJoin='false' + ); + + +``` + + diff --git a/docs/postgresqlSink.md b/docs/postgresqlSink.md new file mode 100644 index 000000000..da09c4c34 --- /dev/null +++ b/docs/postgresqlSink.md @@ -0,0 +1,55 @@ +## 1.格式: +``` +CREATE TABLE tableName( + colName colType, + ... + colNameX colType + )WITH( + type ='postgresql', + url ='jdbcUrl', + userName ='userName', + password ='pwd', + tableName ='tableName', + parallelism ='parllNum' + ); + +``` + +## 2.支持版本 + postgresql-8.2+ + +## 3.表结构定义 + +|参数名称|含义| +|----|---| +| tableName| 在 sql 中使用的名称;即注册到flink-table-env上的名称| +| colName | 列名称| +| colType | 列类型 [colType支持的类型](colType.md)| + +## 4.参数: + +|参数名称|含义|是否必填|默认值| +|----|----|----|----| +| type |表明 输出表类型[postgresql]|是|| +| url | 连接postgresql数据库 jdbcUrl |是|| +| userName | postgresql连接用户名 |是|| +| password | postgresql连接密码|是|| +| tableName | postgresqll表名称|是|| +| parallelism | 并行度设置|否|1| +| isUpsert | 使用upsert模式插入数据(版本9.5之后才支持upsert) |否|false +| keyField | 设置更新主键字段名(isupsert为true时为必填项)|否| + +## 5.样例: +``` +CREATE TABLE MyResult( + channel VARCHAR, + pv VARCHAR + )WITH( + type ='postgresql', + url ='jdbc:postgresql://localhost:9001/test?sslmode=disable', + userName ='dtstack', + password ='abc123', + tableName ='pv2', + parallelism ='1' + ) + ``` diff --git a/docs/pr.md b/docs/pr.md deleted file mode 100644 index 18a902bb5..000000000 --- a/docs/pr.md +++ /dev/null @@ -1,20 +0,0 @@ -## PR规范 - -1. 建立issue,描述相关问题信息 -2. 基于对应的release分支拉取开发分支 -3. commit 信息:[type-issueid] [module] msg - 1. type 类别 - 2. feat:表示是一个新功能(feature) - 3. hotfix:hotfix,修补bug - 4. docs:改动、增加文档 - 5. opt:修改代码风格及opt imports这些,不改动原有执行的代码 - 6. test:增加测试 - -
- -eg: - [hotfix-31280][core] 修复bigdecimal转decimal运行失败问题 - [feat-31372][rdb] RDB结果表Upsert模式支持选择更新策略 - -1. 多次提交使用rebase 合并成一个。 -2. pr 名称:[flinkx-issueid][module名称] 标题 \ No newline at end of file diff --git a/docs/quickStart.md b/docs/quickStart.md deleted file mode 100644 index a5bf1fa9a..000000000 --- a/docs/quickStart.md +++ /dev/null @@ -1,107 +0,0 @@ -### 1.1 运行模式 - -* 本地模式:通常用于本地开发调试(--mode:local) -* standalone模式:Flink 本身提供到集群分布式模式(--mode:standalone) -* yarn-session模式:在yarn上已经预先启动了flink集群(--mode:yarn) -* yarn-perjob 模式:每个任务单独启动一个yarn application,推荐使用该模式.(--mode:yarnPer) - -### 1.2 执行环境 - -* Java: JDK8及以上 -* Flink集群: 1.4,1.5,1.8,1.9,1.10(单机模式不需要安装Flink集群) -* 操作系统:理论上不限 -* kerberos环境需要在flink-conf.yaml配置security.kerberos.login.keytab以及security.kerberos.login.principal参数,配置案例: -```yaml -#提交到hadoop环境一定要配置fs.hdfs.hadoopconf参数 -fs.hdfs.hadoopconf: /Users/maqi/tmp/hadoopconf/hadoop_250 -security.kerberos.login.use-ticket-cache: true -security.kerberos.login.keytab: /Users/maqi/tmp/hadoopconf/hadoop_250/maqi.keytab -security.kerberos.login.principal: maqi@DTSTACK.COM -security.kerberos.login.contexts: Client,KafkaClient -zookeeper.sasl.service-name: zookeeper -zookeeper.sasl.login-context-name: Client -``` - -### 1.3 打包 - -进入项目根目录,使用maven打包: -```shell script -mvn clean package -Dmaven.test.skip -``` - -####可运行的目录结构: -``` -| -|-----bin -| |--- submit.sh 任务启动脚本 -|-----lib: launcher包存储路径,是任务提交的入口 -| |--- sql.launcher.jar -|-----plugins: 插件包存储路径(mvn 打包之后会自动将jar移动到该目录下) -| |--- core.jar -| |--- xxxsource -| |--- xxxsink -| |--- xxxside -``` -### 1.4 快速启动命令 - -#### local模式命令 -```shell script -sh submit.sh - -mode local - -name local_test - -sql F:\dtstack\stressTest\flinkStreamSql\stressTest.sql - -localSqlPluginPath F:\dtstack\project\flinkStreamSQL\plugins -``` - -#### standalone模式命令 -```shell script -sh submit.sh - -mode standalone - -sql F:\dtstack\flinkStreamSql\tiezhu\twodimjoin.sql - -name wtz_standalone_flinkStreamSql - -localSqlPluginPath F:\dtstack\project\flinkStreamSQL\plugins - -remoteSqlPluginPath /home/admin/dtstack/flinkStreamSQL/plugins - -flinkconf F:\dtstack\flinkStreamSql\localhost\flinkConf - -yarnconf F:\dtstack\flinkStreamSql\localhost\hadoop - -flinkJarPath F:\Java\flink-1.8.2-bin-scala_2.12\flink-1.8.2\lib - -pluginLoadMode shipfile - -confProp {\"time.characteristic\":\"eventTime\",\"logLevel\":\"info\"} -``` - -#### yarn模式命令 -```shell script -sh submit.sh - -mode yarn - -name flink1.10_yarnSession - -sql F:\dtstack\stressTest\flinkStreamSql\1.10_dev\sql\flink1100.sql - -localSqlPluginPath F:\dtstack\project\flinkStreamSQL\plugins - -remoteSqlPluginPath F:\dtstack\project\flinkStreamSQL\plugins - -flinkconf F:\dtstack\flink\flink-1.10.0\conf - -yarnconf F:\dtstack\flinkStreamSql\yarnConf_node1 - -flinkJarPath F:\dtstack\flink\flink-1.10.0\lib - -pluginLoadMode shipfile - -yarnSessionConf {\"yid\":\"application_1586851105774_0014\"} -``` - -#### yarnPer模式命令 -```shell script -sh submit.sh - -mode yarnPer - -sql /home/wen/Desktop/flink_stream_sql_conf/sql/Test01.sql - -name TestAll - -localSqlPluginPath /home/wen/IdeaProjects/flinkStreamSQL/plugins - -remoteSqlPluginPath /home/wen/IdeaProjects/flinkStreamSQL/plugins - -flinkconf /home/wen/Desktop/flink_stream_sql_conf/flinkConf - -yarnconf /home/wen/Desktop/flink_stream_sql_conf/yarnConf_node1 - -flinkJarPath /home/wen/Desktop/dtstack/flink-1.8.1/lib - -pluginLoadMode shipfile - -confProp {\"time.characteristic\":\"eventTime\",\"logLevel\":\"info\"} - -queue c -``` -参数具体细节请看[命令参数说明](./config.md) - -任务sql详情请看[任务样例](./demo.md) - -### 招聘 -1.大数据平台开发工程师,想了解岗位详细信息可以添加本人微信号ysqwhiletrue,注明招聘,如有意者发送简历至sishu@dtstack.com。 - diff --git a/docs/redisSide.md b/docs/redisSide.md new file mode 100644 index 000000000..9c7f4b47e --- /dev/null +++ b/docs/redisSide.md @@ -0,0 +1,74 @@ + +## 1.格式: +``` + CREATE TABLE tableName( + colName cloType, + ... + PERIOD FOR SYSTEM_TIME + )WITH( + type ='redis', + url = 'ip:port', + password = 'redisPwd', + database = 'dbName', + tableName ='sideTableName', + redisType = '1', + cache ='LRU', + cacheSize ='10000', + cacheTTLMs ='60000' + ); +``` +## 2.支持版本 + redis5.0 + +## 3.表结构定义 + +|参数名称|含义| +|----|---| +| tableName | 注册到flink的表名称(可选填;不填默认和redis对应的表名称相同)| +| colName | 列名称,维表列名格式 表名:主键名:主键值:列名]| +| colType | 列类型,当前只支持varchar| +| PERIOD FOR SYSTEM_TIME | 关键字表明该定义的表为维表信息| + +## 3.参数 + +|参数名称|含义|是否必填|默认值| +|----|---|---|----| +| type | 表明维表的类型[hbase|mysql|redis]|是|| +| url | redis 的地址;格式ip:port[,ip:port]|是|| +| password | redis 的密码 |是|| +| redisType | redis模式(1 单机,2 哨兵, 3 集群)| 是 | +| masterName | 主节点名称(哨兵模式下为必填项) | 否 | +| database | reids 的数据库地址|否|| +| tableName | redis 的表名称|是|| +| cache | 维表缓存策略(NONE/LRU/ALL)|否|NONE| +| partitionedJoin | 是否在維表join之前先根据 設定的key 做一次keyby操作(可以減少维表的数据缓存量)|否|false| + +-------------- +> 缓存策略 + * NONE: 不做内存缓存 + * LRU: + * cacheSize: 缓存的条目数量 + * cacheTTLMs:缓存的过期时间(ms) + * ALL: 缓存全量表数据 + +## 4.样例 +``` +create table sideTable( + channel varchar, + xccount varchar, + PRIMARY KEY(channel), + PERIOD FOR SYSTEM_TIME + )WITH( + type='redis', + url='172.16.10.79:6379', + password='abc123', + database='0', + redisType = '1', + tableName='sidetest', + cache = 'LRU', + cacheTTLMs='10000' + ); + +``` + + diff --git a/docs/redisSink.md b/docs/redisSink.md new file mode 100644 index 000000000..6a754e5c6 --- /dev/null +++ b/docs/redisSink.md @@ -0,0 +1,61 @@ +## 1.格式: +``` +CREATE TABLE tableName( + colName colType, + ... + colNameX colType + )WITH( + type ='redis', + url = 'ip:port', + database ='dbName', + password ='pwd', + redisType='1', + tableName ='tableName', + parallelism ='parllNum' + ); + + +``` + +## 2.支持版本 +redis5.0 + +## 3.表结构定义 + +|参数名称|含义| +|----|---| +| tableName | 在 sql 中使用的名称;即注册到flink-table-env上的名称 +| colName | 列名称,redis中存储为 表名:主键名:主键值:列名]| +| colType | 列类型,当前只支持varchar| +| PRIMARY KEY(keyInfo) | 结果表主键定义;多个列之间用逗号隔开| + +## 4.参数: + +|参数名称|含义|是否必填|默认值| +|----|---|---|-----| +| type | 表名 输出表类型[mysq|hbase|elasticsearch|redis]|是|| +| url | redis 的地址;格式ip:port[,ip:port]|是|| +| password | redis 的密码 |是|| +| redisType | redis模式(1 单机,2 哨兵, 3 集群)| 是 | +| masterName | 主节点名称(哨兵模式下为必填项) | 否 | +| database | reids 的数据库地址|否|| +| tableName | redis 的表名称|是|| +| parallelism | 并行度设置|否|1| + + +## 5.样例: +``` + CREATE TABLE MyResult( + channel varchar, + pv varchar, + PRIMARY KEY(channel) + )WITH( + type='redis', + url='172.16.10.79:6379', + password='abc123', + database='0', + redisType='1', + tableName='sinktoredis' + ); + + ``` \ No newline at end of file diff --git a/docs/plugin/serverSocketSource.md b/docs/serverSocketSource.md similarity index 100% rename from docs/plugin/serverSocketSource.md rename to docs/serverSocketSource.md diff --git a/elasticsearch5-xh/elasticsearch5-xh-sink/pom.xml b/elasticsearch5-xh/elasticsearch5-xh-sink/pom.xml deleted file mode 100644 index f1a684856..000000000 --- a/elasticsearch5-xh/elasticsearch5-xh-sink/pom.xml +++ /dev/null @@ -1,124 +0,0 @@ - - - - sql.elasticsearch5-xh - com.dtstack.flink - 1.0-SNAPSHOT - - 4.0.0 - - sql.sink.elasticsearch5-xh - elasticsearch-xh-sink - - - - - - org.slf4j - slf4j-log4j12 - 1.6.1 - - - - org.apache.logging.log4j - log4j-to-slf4j - 2.7 - - - - io.transwarp.elasticsearch - elasticsearch-client - 5.4.1 - - - - io.transwarp.sasl - guardian-sasl-transwarp - 6.2.1 - - - - - com.google.protobuf - protobuf-java - 3.15.0 - - - - - - org.apache.flink - flink-table-planner_2.11 - ${flink.version} - provided - true - - - - - - - - - org.apache.maven.plugins - maven-shade-plugin - 1.4 - - - package - - shade - - - - - - - - - - *:* - - META-INF/*.SF - META-INF/*.DSA - META-INF/*.RSA - - - - - - - - - - maven-antrun-plugin - 1.2 - - - copy-resources - - package - - run - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/CustomerSinkFunc.java b/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/CustomerSinkFunc.java deleted file mode 100644 index 75bae1e2f..000000000 --- a/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/CustomerSinkFunc.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.elasticsearch; - -import org.apache.commons.lang3.StringUtils; -import org.apache.flink.api.common.functions.RuntimeContext; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.metrics.Counter; -import org.apache.flink.streaming.connectors.elasticsearch.ElasticsearchSinkFunction; -import org.apache.flink.streaming.connectors.elasticsearch.RequestIndexer; -import org.apache.flink.types.Row; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import transwarp.org.elasticsearch.action.index.IndexRequest; -import transwarp.org.elasticsearch.client.Requests; - -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -/** - * Reason: - * Date: 2017/7/19 - * Company: www.dtstack.com - * @author xuchao - */ - -public class CustomerSinkFunc implements ElasticsearchSinkFunction { - - private final Logger logger = LoggerFactory.getLogger(CustomerSinkFunc.class); - - private static final String ID_VALUE_SPLIT = "_"; - - private String index; - - private String type; - - private List idFieldIndexList; - - private List fieldNames; - - private List fieldTypes; - - public transient Counter outRecords; - - public transient Counter outDirtyRecords; - - /** 默认分隔符为'_' */ - private char sp = '_'; - - public CustomerSinkFunc(String index, String type, List fieldNames, List fieldTypes, List idFieldIndexes){ - this.index = index; - this.type = type; - this.fieldNames = fieldNames; - this.fieldTypes = fieldTypes; - this.idFieldIndexList = idFieldIndexes; - } - - @Override - public void process(Tuple2 tuple2, RuntimeContext ctx, RequestIndexer indexer) { - try{ - Tuple2 tupleTrans = tuple2; - Boolean retract = tupleTrans.getField(0); - Row element = tupleTrans.getField(1); - if(!retract){ - return; - } - - indexer.add(createIndexRequest(element)); - outRecords.inc(); - }catch (Exception e){ - outDirtyRecords.inc(); - logger.error("Failed to store source data {}. ", tuple2.getField(1)); - logger.error("Failed to create index request exception. ", e); - } - } - - public void setOutRecords(Counter outRecords) { - this.outRecords = outRecords; - } - - public void setOutDirtyRecords(Counter outDirtyRecords) { - this.outDirtyRecords = outDirtyRecords; - } - - private IndexRequest createIndexRequest(Row element) { - String idFieldStr = ""; - if (null != idFieldIndexList) { - // index start at 1, - idFieldStr = idFieldIndexList.stream() - .filter(index -> index > 0 && index <= element.getArity()) - .map(index -> element.getField(index - 1).toString()) - .collect(Collectors.joining(ID_VALUE_SPLIT)); - } - - Map dataMap = EsUtil.rowToJsonMap(element,fieldNames,fieldTypes); - int length = Math.min(element.getArity(), fieldNames.size()); - for(int i=0; i, IStreamSinkGener { - - private final Logger logger = LoggerFactory.getLogger(ElasticsearchSink.class); - - private String clusterName; - - private int bulkFlushMaxActions = 1; - - private List esAddressList; - - private String index = ""; - - private String type = ""; - - private List idIndexList; - - protected String[] fieldNames; - - protected String[] columnTypes; - - private TypeInformation[] fieldTypes; - - private int parallelism = 1; - - protected String registerTableName; - - private ElasticsearchTableInfo esTableInfo; - - //kerberos - boolean enableKrb; - private String principal; - private String keytab; - private String krb5conf; - - // es cluster name - private static final String CLUSTER_NAME = "cluster.name"; - - @Override - public TableSink> configure(String[] fieldNames, TypeInformation[] fieldTypes) { - this.fieldNames = fieldNames; - this.fieldTypes = fieldTypes; - return this; - } - - @Override - public TupleTypeInfo> getOutputType() { - return new TupleTypeInfo(org.apache.flink.table.api.Types.BOOLEAN(), getRecordType()); - } - - @Override - public TypeInformation getRecordType() { - return new RowTypeInfo(fieldTypes, fieldNames); - } - - @Override - public String[] getFieldNames() { - return fieldNames; - } - - @Override - public TypeInformation[] getFieldTypes() { - return fieldTypes; - } - - - private RichSinkFunction createEsSinkFunction(){ - - // elasticsearch client settings - Map userConfig = new HashMap<>(); - userConfig.put(CLUSTER_NAME, clusterName); - - // This instructs the sink to emit after every element, otherwise they would be buffered - userConfig.put(ElasticsearchSinkBase.CONFIG_KEY_BULK_FLUSH_MAX_ACTIONS, "" + bulkFlushMaxActions); - - // elasticsearch hosts - List transports = new ArrayList<>(); - for(String address : esAddressList){ - String[] infoArray = StringUtils.split(address, ":"); - int port = 9300; - String host = infoArray[0]; - if(infoArray.length > 1){ - port = Integer.valueOf(infoArray[1].trim()); - } - - try { - transports.add(new InetSocketAddress(InetAddress.getByName(host), port)); - }catch (Exception e){ - logger.error("", e); - throw new RuntimeException(e); - } - } - - CustomerSinkFunc customerSinkFunc = new CustomerSinkFunc(index, type, Arrays.asList(fieldNames), Arrays.asList(columnTypes), idIndexList); - - return new MetricElasticsearchSink(userConfig, transports, customerSinkFunc, esTableInfo); - } - - @Override - public void emitDataStream(DataStream> dataStream) { - consumeDataStream(dataStream); - } - - @Override - public DataStreamSink> consumeDataStream(DataStream> dataStream) { - RichSinkFunction richSinkFunction = createEsSinkFunction(); - DataStreamSink streamSink = dataStream.addSink(richSinkFunction).name(registerTableName); - if(parallelism > 0){ - streamSink.setParallelism(parallelism); - } - - return streamSink; - } - - public void setBulkFlushMaxActions(int bulkFlushMaxActions) { - this.bulkFlushMaxActions = bulkFlushMaxActions; - } - - @Override - public ElasticsearchSink genStreamSink(AbstractTargetTableInfo targetTableInfo) { - ElasticsearchTableInfo elasticsearchTableInfo = (ElasticsearchTableInfo) targetTableInfo; - esTableInfo = elasticsearchTableInfo; - clusterName = elasticsearchTableInfo.getClusterName(); - String address = elasticsearchTableInfo.getAddress(); - String[] addr = StringUtils.split(address, ","); - esAddressList = Arrays.asList(addr); - index = elasticsearchTableInfo.getIndex(); - type = elasticsearchTableInfo.getEsType(); - String id = elasticsearchTableInfo.getId(); - String[] idField = StringUtils.split(id, ","); - idIndexList = new ArrayList<>(); - registerTableName = elasticsearchTableInfo.getName(); - parallelism = Objects.isNull(elasticsearchTableInfo.getParallelism()) ? - parallelism : elasticsearchTableInfo.getParallelism(); - - //kerberos - principal = elasticsearchTableInfo.getPrincipal(); - keytab = elasticsearchTableInfo.getKeytab(); - krb5conf = elasticsearchTableInfo.getKrb5conf(); - enableKrb = elasticsearchTableInfo.isEnableKrb(); - - for(int i = 0; i < idField.length; ++i) { - idIndexList.add(Integer.valueOf(idField[i])); - } - - columnTypes = elasticsearchTableInfo.getFieldTypes(); - - return this; - } -} diff --git a/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/EsUtil.java b/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/EsUtil.java deleted file mode 100644 index 26d7827da..000000000 --- a/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/EsUtil.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.elasticsearch; - -import com.dtstack.flink.sql.util.DtStringUtil; -import org.apache.flink.types.Row; -import org.apache.flink.util.Preconditions; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Utilities for ElasticSearch - * - * Company: www.dtstack.com - * @author huyifan.zju@163.com - */ -public class EsUtil { - - public static Map rowToJsonMap(Row row, List fields, List types) { - Preconditions.checkArgument(row.getArity() == fields.size()); - Map jsonMap = new HashMap<>(); - int i = 0; - for(; i < fields.size(); ++i) { - String field = fields.get(i); - String[] parts = field.split("\\."); - Map currMap = jsonMap; - for(int j = 0; j < parts.length - 1; ++j) { - String key = parts[j]; - if(currMap.get(key) == null) { - currMap.put(key, new HashMap()); - } - currMap = (Map) currMap.get(key); - } - String key = parts[parts.length - 1]; - Object col = row.getField(i); - if(col != null) { - Object value = DtStringUtil.col2string(col, types.get(i)); - currMap.put(key, value); - } - - } - - return jsonMap; - } - - -} diff --git a/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/ExtendES5ApiCallBridge.java b/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/ExtendES5ApiCallBridge.java deleted file mode 100644 index 26dbaf496..000000000 --- a/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/ExtendES5ApiCallBridge.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.elasticsearch; - -import com.dtstack.flink.sql.sink.elasticsearch.table.ElasticsearchTableInfo; -import com.dtstack.flink.sql.util.KrbUtils; -import io.transwarp.plugin.doorkeeper.client.DoorKeeperClientPlugin; -import org.apache.flink.streaming.connectors.elasticsearch.ElasticsearchApiCallBridge; -import org.apache.flink.streaming.connectors.elasticsearch.ElasticsearchSinkBase; -import org.apache.flink.streaming.connectors.elasticsearch.util.ElasticsearchUtils; -import org.apache.flink.util.IOUtils; -import org.apache.flink.util.Preconditions; -import org.apache.hadoop.security.UserGroupInformation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import transwarp.org.elasticsearch.action.bulk.BackoffPolicy; -import transwarp.org.elasticsearch.action.bulk.BulkItemResponse; -import transwarp.org.elasticsearch.action.bulk.BulkProcessor; -import transwarp.org.elasticsearch.client.transport.TransportClient; -import transwarp.org.elasticsearch.common.network.NetworkModule; -import transwarp.org.elasticsearch.common.settings.Setting; -import transwarp.org.elasticsearch.common.settings.Settings; -import transwarp.org.elasticsearch.common.transport.TransportAddress; -import transwarp.org.elasticsearch.common.unit.TimeValue; -import transwarp.org.elasticsearch.transport.client.PreBuiltTransportClient; - -import javax.annotation.Nullable; -import java.io.IOException; -import java.net.InetSocketAddress; -import java.security.PrivilegedAction; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -/** - * @date 2019/11/16 - * @author xiuzhu - * @Company: www.dtstack.com - */ - -public class ExtendES5ApiCallBridge implements ElasticsearchApiCallBridge { - private static final long serialVersionUID = -5222683870097809633L; - - private static final Logger LOG = LoggerFactory.getLogger(ExtendES5ApiCallBridge.class); - - private final List transportAddresses; - - protected ElasticsearchTableInfo esTableInfo; - - public ExtendES5ApiCallBridge(List transportAddresses, ElasticsearchTableInfo esTableInfo) { - Preconditions.checkArgument(transportAddresses != null && !transportAddresses.isEmpty()); - this.transportAddresses = transportAddresses; - this.esTableInfo = esTableInfo; - } - - @Override - public TransportClient createClient(Map clientConfig) throws IOException{ - - TransportClient transportClient; - - if (esTableInfo.isEnableKrb()) { - //1. login kdc with keytab and krb5 conf - UserGroupInformation ugi = KrbUtils.loginAndReturnUgi( - esTableInfo.getPrincipal(), - esTableInfo.getKeytab(), - esTableInfo.getKrb5conf()); - - //2. set transwarp attributes - Settings settings = Settings.builder().put(clientConfig) - .put("client.transport.sniff", true) - .put("security.enable", true) - .put(NetworkModule.TRANSPORT_TYPE_KEY, "security-netty3") - .build(); - - //3. build transport client with transwarp plugins - transportClient = ugi.doAs((PrivilegedAction) () -> { - TransportClient tmpClient = new PreBuiltTransportClient(settings, - Collections.singletonList(DoorKeeperClientPlugin.class)); - for (TransportAddress transport : ElasticsearchUtils.convertInetSocketAddresses(transportAddresses)) { - tmpClient.addTransportAddress(transport); - } - return tmpClient; - }); - } else { - Settings settings = Settings.builder().put(clientConfig) - .put("client.transport.sniff", true) - .build(); - - transportClient = new PreBuiltTransportClient(settings); - for (TransportAddress transport : ElasticsearchUtils.convertInetSocketAddresses(transportAddresses)) { - transportClient.addTransportAddress(transport); - } - } - - return transportClient; - } - - @Override - public BulkProcessor.Builder createBulkProcessorBuilder(TransportClient client, BulkProcessor.Listener listener) { - return BulkProcessor.builder(client, listener); - } - - - @Override - public Throwable extractFailureCauseFromBulkItemResponse(BulkItemResponse bulkItemResponse) { - if (!bulkItemResponse.isFailed()) { - return null; - } else { - return bulkItemResponse.getFailure().getCause(); - } - } - - @Override - public void configureBulkProcessorBackoff( - BulkProcessor.Builder builder, - @Nullable ElasticsearchSinkBase.BulkFlushBackoffPolicy flushBackoffPolicy) { - - BackoffPolicy backoffPolicy; - if (flushBackoffPolicy != null) { - switch (flushBackoffPolicy.getBackoffType()) { - case CONSTANT: - backoffPolicy = BackoffPolicy.constantBackoff( - new TimeValue(flushBackoffPolicy.getDelayMillis()), - flushBackoffPolicy.getMaxRetryCount()); - break; - case EXPONENTIAL: - default: - backoffPolicy = BackoffPolicy.exponentialBackoff( - new TimeValue(flushBackoffPolicy.getDelayMillis()), - flushBackoffPolicy.getMaxRetryCount()); - } - } else { - backoffPolicy = BackoffPolicy.noBackoff(); - } - - builder.setBackoffPolicy(backoffPolicy); - } - - @Override - public boolean verifyClientConnection(TransportClient client) throws IOException { - - - boolean verifyResult = false; - - if (esTableInfo.isEnableKrb()) { - //1. login kdc with keytab and krb5 conf - UserGroupInformation ugi = KrbUtils.loginAndReturnUgi( - esTableInfo.getPrincipal(), - esTableInfo.getKeytab(), - esTableInfo.getKrb5conf()); - - //2. refresh availableNodes. - verifyResult = ugi.doAs((PrivilegedAction) () -> { - LOG.info("Refresh client available nodes."); - client.refreshAvailableNodes(); - return client.connectedNodes().isEmpty(); - }); - } else { - client.refreshAvailableNodes(); - verifyResult = client.connectedNodes().isEmpty(); - } - - - if (!verifyResult) { - return true; - } - - // close the transportClient here - IOUtils.closeQuietly(client); - throw new RuntimeException("Elasticsearch client is not connected to any Elasticsearch nodes!"); - } -} diff --git a/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/MetricElasticsearchSink.java b/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/MetricElasticsearchSink.java deleted file mode 100644 index 170582503..000000000 --- a/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/MetricElasticsearchSink.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.elasticsearch; - -import com.dtstack.flink.sql.metric.MetricConstant; -import com.dtstack.flink.sql.sink.elasticsearch.table.ElasticsearchTableInfo; -import org.apache.flink.configuration.Configuration; -import org.apache.flink.metrics.Counter; -import org.apache.flink.metrics.Meter; -import org.apache.flink.metrics.MeterView; -import org.apache.flink.streaming.connectors.elasticsearch.ElasticsearchSinkBase; -import org.apache.flink.streaming.connectors.elasticsearch.ElasticsearchSinkFunction; -import org.apache.flink.streaming.connectors.elasticsearch.util.NoOpFailureHandler; - -import java.util.List; -import java.util.Map; - -/** - * @Auther: jiangjunjie - * @Date: 2018/11/29 14:15 - * @Description: - * - */ -public class MetricElasticsearchSink extends ElasticsearchSinkBase { - - protected CustomerSinkFunc customerSinkFunc; - - protected transient Meter outRecordsRate; - - protected Map userConfig; - - - public MetricElasticsearchSink(Map userConfig, List transportAddresses, - ElasticsearchSinkFunction elasticsearchSinkFunction, - ElasticsearchTableInfo esTableInfo) { - super(new ExtendES5ApiCallBridge(transportAddresses, esTableInfo), userConfig, elasticsearchSinkFunction, new NoOpFailureHandler()); - this.customerSinkFunc = (CustomerSinkFunc) elasticsearchSinkFunction; - this.userConfig = userConfig; - } - - @Override - public void open(Configuration parameters) throws Exception { - super.open(parameters); - initMetric(); - } - - public void initMetric() { - Counter counter = getRuntimeContext().getMetricGroup().counter(MetricConstant.DT_NUM_RECORDS_OUT); - Counter outDirtyRecords = getRuntimeContext().getMetricGroup().counter(MetricConstant.DT_NUM_DIRTY_RECORDS_OUT); - - customerSinkFunc.setOutRecords(counter); - customerSinkFunc.setOutDirtyRecords(outDirtyRecords); - outRecordsRate = getRuntimeContext().getMetricGroup().meter(MetricConstant.DT_NUM_RECORDS_OUT_RATE, new MeterView(counter, 20)); - } -} diff --git a/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/table/ElasticsearchSinkParser.java b/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/table/ElasticsearchSinkParser.java deleted file mode 100644 index 67f38d064..000000000 --- a/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/table/ElasticsearchSinkParser.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.elasticsearch.table; - - -import com.dtstack.flink.sql.constant.PluginParamConsts; -import com.dtstack.flink.sql.table.AbstractTableInfo; -import com.dtstack.flink.sql.table.AbstractTableParser; -import com.dtstack.flink.sql.util.MathUtil; - -import java.util.Map; - -/** - * @date 2018/09/12 - * @author sishu.yss - * @Company: www.dtstack.com - */ -public class ElasticsearchSinkParser extends AbstractTableParser { - - private static final String KEY_ES_ADDRESS = "address"; - - private static final String KEY_ES_CLUSTER = "cluster"; - - private static final String KEY_ES_INDEX = "index"; - - private static final String KEY_ES_TYPE = "estype"; - - private static final String KEY_ES_ID_FIELD_INDEX_LIST = "id"; - - private static final String KEY_ES_PARALLELISM = "parallelism"; - - @Override - protected boolean fieldNameNeedsUpperCase() { - return false; - } - - @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { - ElasticsearchTableInfo elasticsearchTableInfo = new ElasticsearchTableInfo(); - elasticsearchTableInfo.setName(tableName); - parseFieldsInfo(fieldsInfo, elasticsearchTableInfo); - elasticsearchTableInfo.setAddress((String) props.get(KEY_ES_ADDRESS.toLowerCase())); - elasticsearchTableInfo.setClusterName((String) props.get(KEY_ES_CLUSTER.toLowerCase())); - elasticsearchTableInfo.setId((String) props.get(KEY_ES_ID_FIELD_INDEX_LIST.toLowerCase())); - elasticsearchTableInfo.setIndex((String) props.get(KEY_ES_INDEX.toLowerCase())); - elasticsearchTableInfo.setEsType((String) props.get(KEY_ES_TYPE.toLowerCase())); - elasticsearchTableInfo.setParallelism(MathUtil.getIntegerVal(props.getOrDefault(KEY_ES_PARALLELISM.toLowerCase(), 1))); - - //kerberos - elasticsearchTableInfo.setKrb5conf(MathUtil.getString(props.get(PluginParamConsts.KRB5_CONF))); - elasticsearchTableInfo.setKeytab(MathUtil.getString(props.get(PluginParamConsts.KEYTAB))); - elasticsearchTableInfo.setPrincipal(MathUtil.getString(props.get(PluginParamConsts.PRINCIPAL))); - elasticsearchTableInfo.judgeKrbEnable(); - - elasticsearchTableInfo.check(); - return elasticsearchTableInfo; - } -} diff --git a/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/table/ElasticsearchTableInfo.java b/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/table/ElasticsearchTableInfo.java deleted file mode 100644 index 41857e989..000000000 --- a/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/table/ElasticsearchTableInfo.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.elasticsearch.table; - - -import com.dtstack.flink.sql.krb.KerberosTable; -import com.dtstack.flink.sql.table.AbstractTargetTableInfo; -import com.google.common.base.Preconditions; -import com.google.common.base.Strings; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang3.math.NumberUtils; - -import java.util.Arrays; - -/** - * @date 2018/09/12 - * @author sishu.yss - * @Company: www.dtstack.com - */ -public class ElasticsearchTableInfo extends AbstractTargetTableInfo implements KerberosTable { - - private static final String CURR_TYPE = "elasticsearch-xh"; - - private String address; - - private String index; - - private String id; - - private String clusterName; - - private String esType; - - - /** - * kerberos - */ - private String principal; - private String keytab; - private String krb5conf; - boolean enableKrb; - - @Override - public String getPrincipal() { - return principal; - } - - @Override - public void setPrincipal(String principal) { - this.principal = principal; - } - - @Override - public String getKeytab() { - return keytab; - } - - @Override - public void setKeytab(String keytab) { - this.keytab = keytab; - } - - @Override - public String getKrb5conf() { - return krb5conf; - } - - @Override - public void setKrb5conf(String krb5conf) { - this.krb5conf = krb5conf; - } - - @Override - public boolean isEnableKrb() { - return enableKrb; - } - - @Override - public void setEnableKrb(boolean enableKrb) { - this.enableKrb = enableKrb; - } - - public String getEsType() { - return esType; - } - - public void setEsType(String esType) { - this.esType = esType; - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getAddress() { - return address; - } - - public void setAddress(String address) { - this.address = address; - } - - public String getIndex() { - return index; - } - - public void setIndex(String index) { - this.index = index; - } - - @Override - public String getType() { - //return super.getType().toLowerCase() + TARGET_SUFFIX; - return super.getType().toLowerCase(); - } - - public String getClusterName() { - return clusterName; - } - - public void setClusterName(String clusterName) { - this.clusterName = clusterName; - } - - public ElasticsearchTableInfo() { - setType(CURR_TYPE); - } - - @Override - public boolean check() { - Preconditions.checkNotNull(address, "elasticsearch type of address is required"); - Preconditions.checkNotNull(index, "elasticsearch type of index is required"); - Preconditions.checkNotNull(esType, "elasticsearch type of type is required"); - Preconditions.checkNotNull(clusterName, "elasticsearch type of clusterName is required"); - - if (!StringUtils.isEmpty(id)) { - Arrays.stream(StringUtils.split(id, ",")).forEach(number -> { - Preconditions.checkArgument(NumberUtils.isNumber(number), "id must be a numeric type"); - }); - } - return true; - } - -} diff --git a/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/ActionRequestFailureHandler.java b/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/ActionRequestFailureHandler.java deleted file mode 100644 index 48182f2af..000000000 --- a/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/ActionRequestFailureHandler.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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.streaming.connectors.elasticsearch; - -import org.apache.flink.annotation.PublicEvolving; -import transwarp.org.elasticsearch.action.ActionRequest; - - -import java.io.Serializable; - -/** - * An implementation of {@link ActionRequestFailureHandler} is provided by the user to define how failed - * {@link ActionRequest ActionRequests} should be handled, e.g. dropping them, reprocessing malformed documents, or - * simply requesting them to be sent to Elasticsearch again if the failure is only temporary. - * - *

Example: - * - *

{@code
- *
- *	private static class ExampleActionRequestFailureHandler implements ActionRequestFailureHandler {
- *
- *		@Override
- *		void onFailure(ActionRequest action, Throwable failure, int restStatusCode, RequestIndexer indexer) throws Throwable {
- *			if (ExceptionUtils.findThrowable(failure, EsRejectedExecutionException.class).isPresent()) {
- *				// full queue; re-add document for indexing
- *				indexer.add(action);
- *			} else if (ExceptionUtils.findThrowable(failure, ElasticsearchParseException.class).isPresent()) {
- *				// malformed document; simply drop request without failing sink
- *			} else {
- *				// for all other failures, fail the sink;
- *				// here the failure is simply rethrown, but users can also choose to throw custom exceptions
- *				throw failure;
- *			}
- *		}
- *	}
- *
- * }
- * - *

The above example will let the sink re-add requests that failed due to queue capacity saturation and drop requests - * with malformed documents, without failing the sink. For all other failures, the sink will fail. - * - *

Note: For Elasticsearch 1.x, it is not feasible to match the type of the failure because the exact type - * could not be retrieved through the older version Java client APIs (thus, the types will be general {@link Exception}s - * and only differ in the failure message). In this case, it is recommended to match on the provided REST status code. - */ -@PublicEvolving -public interface ActionRequestFailureHandler extends Serializable { - - /** - * Handle a failed {@link ActionRequest}. - * - * @param action the {@link ActionRequest} that failed due to the failure - * @param failure the cause of failure - * @param restStatusCode the REST status code of the failure (-1 if none can be retrieved) - * @param indexer request indexer to re-add the failed action, if intended to do so - * - * @throws Throwable if the sink should fail on this failure, the implementation should rethrow - * the exception or a custom one - */ - void onFailure(ActionRequest action, Throwable failure, int restStatusCode, RequestIndexer indexer) throws Throwable; - -} diff --git a/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/BufferingNoOpRequestIndexer.java b/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/BufferingNoOpRequestIndexer.java deleted file mode 100644 index e0733692e..000000000 --- a/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/BufferingNoOpRequestIndexer.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * 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.streaming.connectors.elasticsearch; - -import org.apache.flink.annotation.Internal; -import transwarp.org.elasticsearch.action.ActionRequest; -import transwarp.org.elasticsearch.action.delete.DeleteRequest; -import transwarp.org.elasticsearch.action.index.IndexRequest; -import transwarp.org.elasticsearch.action.update.UpdateRequest; - - -import javax.annotation.concurrent.NotThreadSafe; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * Implementation of a {@link RequestIndexer} that buffers {@link ActionRequest ActionRequests} - * before re-sending them to the Elasticsearch cluster upon request. - */ -@Internal -@NotThreadSafe -class BufferingNoOpRequestIndexer implements RequestIndexer { - - private List bufferedRequests; - - BufferingNoOpRequestIndexer() { - this.bufferedRequests = new ArrayList<>(10); - } - - @Override - public void add(DeleteRequest... deleteRequests) { - Collections.addAll(bufferedRequests, deleteRequests); - } - - @Override - public void add(IndexRequest... indexRequests) { - Collections.addAll(bufferedRequests, indexRequests); - } - - @Override - public void add(UpdateRequest... updateRequests) { - Collections.addAll(bufferedRequests, updateRequests); - } - - void processBufferedRequests(RequestIndexer actualIndexer) { - for (ActionRequest request : bufferedRequests) { - if (request instanceof IndexRequest) { - actualIndexer.add((IndexRequest) request); - } else if (request instanceof DeleteRequest) { - actualIndexer.add((DeleteRequest) request); - } else if (request instanceof UpdateRequest) { - actualIndexer.add((UpdateRequest) request); - } - } - - bufferedRequests.clear(); - } -} diff --git a/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/ElasticsearchApiCallBridge.java b/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/ElasticsearchApiCallBridge.java deleted file mode 100644 index fc3e06d97..000000000 --- a/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/ElasticsearchApiCallBridge.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * 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.streaming.connectors.elasticsearch; - -import org.apache.flink.annotation.Internal; -import transwarp.org.elasticsearch.action.bulk.BulkItemResponse; -import transwarp.org.elasticsearch.action.bulk.BulkProcessor; - -import javax.annotation.Nullable; -import java.io.IOException; -import java.io.Serializable; -import java.util.Map; -import java.util.concurrent.atomic.AtomicLong; - -/** - * An {@link org.apache.flink.streaming.connectors.elasticsearch.ElasticsearchApiCallBridge} is used to bridge incompatible Elasticsearch Java API calls across different versions. - * This includes calls to create Elasticsearch clients, handle failed item responses, etc. Any incompatible Elasticsearch - * Java APIs should be bridged using this interface. - * - *

Implementations are allowed to be stateful. For example, for Elasticsearch 1.x, since connecting via an embedded node - * is allowed, the call bridge will hold reference to the created embedded node. Each instance of the sink will hold - * exactly one instance of the call bridge, and state cleanup is performed when the sink is closed. - * - * @param The Elasticsearch client, that implements {@link AutoCloseable}. - */ -@Internal -public interface ElasticsearchApiCallBridge extends Serializable { - - /** - * Creates an Elasticsearch client implementing {@link AutoCloseable}. - * - * @param clientConfig The configuration to use when constructing the client. - * @return The created client. - */ - C createClient(Map clientConfig) throws IOException; - - /** - * Creates a {@link BulkProcessor.Builder} for creating the bulk processor. - * - * @param client the Elasticsearch client. - * @param listener the bulk processor listender. - * @return the bulk processor builder. - */ - BulkProcessor.Builder createBulkProcessorBuilder(C client, BulkProcessor.Listener listener); - - /** - * Extracts the cause of failure of a bulk item action. - * - * @param bulkItemResponse the bulk item response to extract cause of failure - * @return the extracted {@link Throwable} from the response ({@code null} is the response is successful). - */ - @Nullable Throwable extractFailureCauseFromBulkItemResponse(BulkItemResponse bulkItemResponse); - - /** - * Set backoff-related configurations on the provided {@link BulkProcessor.Builder}. - * The builder will be later on used to instantiate the actual {@link BulkProcessor}. - * - * @param builder the {@link BulkProcessor.Builder} to configure. - * @param flushBackoffPolicy user-provided backoff retry settings ({@code null} if the user disabled backoff retries). - */ - void configureBulkProcessorBackoff( - BulkProcessor.Builder builder, - @Nullable ElasticsearchSinkBase.BulkFlushBackoffPolicy flushBackoffPolicy); - - /** - * Verify the client connection by making a test request/ping to the Elasticsearch cluster. - * - *

Called by {@link ElasticsearchSinkBase#open(org.apache.flink.configuration.Configuration)} after creating the client. This makes sure the underlying - * client is closed if the connection is not successful and preventing thread leak. - * - * @param client the Elasticsearch client. - */ - boolean verifyClientConnection(C client) throws IOException; - - /** - * Creates a {@link RequestIndexer} that is able to work with {@link BulkProcessor} binary compatible. - */ - default RequestIndexer createBulkProcessorIndexer( - BulkProcessor bulkProcessor, - boolean flushOnCheckpoint, - AtomicLong numPendingRequestsRef) { - return new org.apache.flink.streaming.connectors.elasticsearch.PreElasticsearch6BulkProcessorIndexer( - bulkProcessor, - flushOnCheckpoint, - numPendingRequestsRef); - } - - /** - * Perform any necessary state cleanup. - */ - default void cleanup() { - // nothing to cleanup by default - } - -} diff --git a/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/ElasticsearchSinkBase.java b/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/ElasticsearchSinkBase.java deleted file mode 100644 index 30d5b2791..000000000 --- a/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/ElasticsearchSinkBase.java +++ /dev/null @@ -1,484 +0,0 @@ -/* - * 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.streaming.connectors.elasticsearch; - -import org.apache.flink.annotation.Internal; -import org.apache.flink.annotation.PublicEvolving; -import org.apache.flink.annotation.VisibleForTesting; -import org.apache.flink.api.java.utils.ParameterTool; -import org.apache.flink.configuration.Configuration; -import org.apache.flink.runtime.state.FunctionInitializationContext; -import org.apache.flink.runtime.state.FunctionSnapshotContext; -import org.apache.flink.streaming.api.checkpoint.CheckpointedFunction; -import org.apache.flink.streaming.api.functions.sink.RichSinkFunction; -import org.apache.flink.util.InstantiationUtil; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import transwarp.org.elasticsearch.action.ActionRequest; -import transwarp.org.elasticsearch.action.DocWriteRequest; -import transwarp.org.elasticsearch.action.bulk.BulkItemResponse; -import transwarp.org.elasticsearch.action.bulk.BulkProcessor; -import transwarp.org.elasticsearch.action.bulk.BulkRequest; -import transwarp.org.elasticsearch.action.bulk.BulkResponse; -import transwarp.org.elasticsearch.client.Client; -import transwarp.org.elasticsearch.client.transport.TransportClient; -import transwarp.org.elasticsearch.common.unit.ByteSizeUnit; -import transwarp.org.elasticsearch.common.unit.ByteSizeValue; -import transwarp.org.elasticsearch.common.unit.TimeValue; -import transwarp.org.elasticsearch.rest.RestStatus; - -import java.io.IOException; -import java.io.Serializable; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.atomic.AtomicReference; - -import static org.apache.flink.util.Preconditions.checkArgument; -import static org.apache.flink.util.Preconditions.checkNotNull; - -/** - * Base class for all Flink Elasticsearch Sinks. - * - *

This class implements the common behaviour across Elasticsearch versions, such as - * the use of an internal {@link BulkProcessor} to buffer multiple {@link ActionRequest}s before - * sending the requests to the cluster, as well as passing input records to the user provided - * {@link ElasticsearchSinkFunction} for processing. - * - *

The version specific API calls for different Elasticsearch versions should be defined by a concrete implementation of - * a {@link ElasticsearchApiCallBridge}, which is provided to the constructor of this class. This call bridge is used, - * for example, to create a Elasticsearch {@link Client}, handle failed item responses, etc. - * - * @param Type of the elements handled by this sink - * @param Type of the Elasticsearch client, which implements {@link AutoCloseable} - */ -@Internal -public abstract class ElasticsearchSinkBase extends RichSinkFunction implements CheckpointedFunction { - - private static final long serialVersionUID = -1007596293618451942L; - - private static final Logger LOG = LoggerFactory.getLogger(ElasticsearchSinkBase.class); - - // ------------------------------------------------------------------------ - // Internal bulk processor configuration - // ------------------------------------------------------------------------ - - public static final String CONFIG_KEY_BULK_FLUSH_MAX_ACTIONS = "bulk.flush.max.actions"; - public static final String CONFIG_KEY_BULK_FLUSH_MAX_SIZE_MB = "bulk.flush.max.size.mb"; - public static final String CONFIG_KEY_BULK_FLUSH_INTERVAL_MS = "bulk.flush.interval.ms"; - public static final String CONFIG_KEY_BULK_FLUSH_BACKOFF_ENABLE = "bulk.flush.backoff.enable"; - public static final String CONFIG_KEY_BULK_FLUSH_BACKOFF_TYPE = "bulk.flush.backoff.type"; - public static final String CONFIG_KEY_BULK_FLUSH_BACKOFF_RETRIES = "bulk.flush.backoff.retries"; - public static final String CONFIG_KEY_BULK_FLUSH_BACKOFF_DELAY = "bulk.flush.backoff.delay"; - - /** - * Used to control whether the retry delay should increase exponentially or remain constant. - */ - @PublicEvolving - public enum FlushBackoffType { - CONSTANT, - EXPONENTIAL - } - - /** - * Provides a backoff policy for bulk requests. Whenever a bulk request is rejected due to resource constraints - * (i.e. the client's internal thread pool is full), the backoff policy decides how long the bulk processor will - * wait before the operation is retried internally. - * - *

This is a proxy for version specific backoff policies. - */ - public static class BulkFlushBackoffPolicy implements Serializable { - - private static final long serialVersionUID = -6022851996101826049L; - - // the default values follow the Elasticsearch default settings for BulkProcessor - private FlushBackoffType backoffType = FlushBackoffType.EXPONENTIAL; - private int maxRetryCount = 8; - private long delayMillis = 50; - - public FlushBackoffType getBackoffType() { - return backoffType; - } - - public int getMaxRetryCount() { - return maxRetryCount; - } - - public long getDelayMillis() { - return delayMillis; - } - - public void setBackoffType(FlushBackoffType backoffType) { - this.backoffType = checkNotNull(backoffType); - } - - public void setMaxRetryCount(int maxRetryCount) { - checkArgument(maxRetryCount >= 0); - this.maxRetryCount = maxRetryCount; - } - - public void setDelayMillis(long delayMillis) { - checkArgument(delayMillis >= 0); - this.delayMillis = delayMillis; - } - } - - private final Integer bulkProcessorFlushMaxActions; - private final Integer bulkProcessorFlushMaxSizeMb; - private final Long bulkProcessorFlushIntervalMillis; - private final BulkFlushBackoffPolicy bulkProcessorFlushBackoffPolicy; - - // ------------------------------------------------------------------------ - // User-facing API and configuration - // ------------------------------------------------------------------------ - - /** - * The config map that contains configuration for the bulk flushing behaviours. - * - *

For {@link TransportClient} based implementations, this config - * map would also contain Elasticsearch-shipped configuration, and therefore this config map - * would also be forwarded when creating the Elasticsearch client. - */ - private final Map userConfig; - - /** The function that is used to construct multiple {@link ActionRequest ActionRequests} from each incoming element. */ - private final ElasticsearchSinkFunction elasticsearchSinkFunction; - - /** User-provided handler for failed {@link ActionRequest ActionRequests}. */ - private final ActionRequestFailureHandler failureHandler; - - /** If true, the producer will wait until all outstanding action requests have been sent to Elasticsearch. */ - private boolean flushOnCheckpoint = true; - - /** Provided to the user via the {@link ElasticsearchSinkFunction} to add {@link ActionRequest ActionRequests}. */ - private transient RequestIndexer requestIndexer; - - /** Provided to the {@link ActionRequestFailureHandler} to allow users to re-index failed requests. */ - private transient BufferingNoOpRequestIndexer failureRequestIndexer; - - // ------------------------------------------------------------------------ - // Internals for the Flink Elasticsearch Sink - // ------------------------------------------------------------------------ - - /** Call bridge for different version-specific. */ - private final ElasticsearchApiCallBridge callBridge; - - /** - * Number of pending action requests not yet acknowledged by Elasticsearch. - * This value is maintained only if {@link ElasticsearchSinkBase#flushOnCheckpoint} is {@code true}. - * - *

This is incremented whenever the user adds (or re-adds through the {@link ActionRequestFailureHandler}) requests - * to the {@link RequestIndexer}. It is decremented for each completed request of a bulk request, in - * {@link BulkProcessor.Listener#afterBulk(long, BulkRequest, BulkResponse)} and - * {@link BulkProcessor.Listener#afterBulk(long, BulkRequest, Throwable)}. - */ - private AtomicLong numPendingRequests = new AtomicLong(0); - - /** Elasticsearch client created using the call bridge. */ - private transient C client; - - /** Bulk processor to buffer and send requests to Elasticsearch, created using the client. */ - private transient BulkProcessor bulkProcessor; - - /** - * This is set from inside the {@link BulkProcessor.Listener} if a {@link Throwable} was thrown in callbacks and - * the user considered it should fail the sink via the - * {@link ActionRequestFailureHandler#onFailure(ActionRequest, Throwable, int, RequestIndexer)} method. - * - *

Errors will be checked and rethrown before processing each input element, and when the sink is closed. - */ - private final AtomicReference failureThrowable = new AtomicReference<>(); - - public ElasticsearchSinkBase( - ElasticsearchApiCallBridge callBridge, - Map userConfig, - ElasticsearchSinkFunction elasticsearchSinkFunction, - ActionRequestFailureHandler failureHandler) { - - this.callBridge = checkNotNull(callBridge); - this.elasticsearchSinkFunction = checkNotNull(elasticsearchSinkFunction); - this.failureHandler = checkNotNull(failureHandler); - - // we eagerly check if the user-provided sink function and failure handler is serializable; - // otherwise, if they aren't serializable, users will merely get a non-informative error message - // "ElasticsearchSinkBase is not serializable" - - checkArgument(InstantiationUtil.isSerializable(elasticsearchSinkFunction), - "The implementation of the provided ElasticsearchSinkFunction is not serializable. " + - "The object probably contains or references non-serializable fields."); - - checkArgument(InstantiationUtil.isSerializable(failureHandler), - "The implementation of the provided ActionRequestFailureHandler is not serializable. " + - "The object probably contains or references non-serializable fields."); - - // extract and remove bulk processor related configuration from the user-provided config, - // so that the resulting user config only contains configuration related to the Elasticsearch client. - - checkNotNull(userConfig); - - // copy config so we can remove entries without side-effects - userConfig = new HashMap<>(userConfig); - - ParameterTool params = ParameterTool.fromMap(userConfig); - - if (params.has(CONFIG_KEY_BULK_FLUSH_MAX_ACTIONS)) { - bulkProcessorFlushMaxActions = params.getInt(CONFIG_KEY_BULK_FLUSH_MAX_ACTIONS); - userConfig.remove(CONFIG_KEY_BULK_FLUSH_MAX_ACTIONS); - } else { - bulkProcessorFlushMaxActions = null; - } - - if (params.has(CONFIG_KEY_BULK_FLUSH_MAX_SIZE_MB)) { - bulkProcessorFlushMaxSizeMb = params.getInt(CONFIG_KEY_BULK_FLUSH_MAX_SIZE_MB); - userConfig.remove(CONFIG_KEY_BULK_FLUSH_MAX_SIZE_MB); - } else { - bulkProcessorFlushMaxSizeMb = null; - } - - if (params.has(CONFIG_KEY_BULK_FLUSH_INTERVAL_MS)) { - bulkProcessorFlushIntervalMillis = params.getLong(CONFIG_KEY_BULK_FLUSH_INTERVAL_MS); - userConfig.remove(CONFIG_KEY_BULK_FLUSH_INTERVAL_MS); - } else { - bulkProcessorFlushIntervalMillis = null; - } - - boolean bulkProcessorFlushBackoffEnable = params.getBoolean(CONFIG_KEY_BULK_FLUSH_BACKOFF_ENABLE, true); - userConfig.remove(CONFIG_KEY_BULK_FLUSH_BACKOFF_ENABLE); - - if (bulkProcessorFlushBackoffEnable) { - this.bulkProcessorFlushBackoffPolicy = new BulkFlushBackoffPolicy(); - - if (params.has(CONFIG_KEY_BULK_FLUSH_BACKOFF_TYPE)) { - bulkProcessorFlushBackoffPolicy.setBackoffType(FlushBackoffType.valueOf(params.get(CONFIG_KEY_BULK_FLUSH_BACKOFF_TYPE))); - userConfig.remove(CONFIG_KEY_BULK_FLUSH_BACKOFF_TYPE); - } - - if (params.has(CONFIG_KEY_BULK_FLUSH_BACKOFF_RETRIES)) { - bulkProcessorFlushBackoffPolicy.setMaxRetryCount(params.getInt(CONFIG_KEY_BULK_FLUSH_BACKOFF_RETRIES)); - userConfig.remove(CONFIG_KEY_BULK_FLUSH_BACKOFF_RETRIES); - } - - if (params.has(CONFIG_KEY_BULK_FLUSH_BACKOFF_DELAY)) { - bulkProcessorFlushBackoffPolicy.setDelayMillis(params.getLong(CONFIG_KEY_BULK_FLUSH_BACKOFF_DELAY)); - userConfig.remove(CONFIG_KEY_BULK_FLUSH_BACKOFF_DELAY); - } - - } else { - bulkProcessorFlushBackoffPolicy = null; - } - - this.userConfig = userConfig; - } - - /** - * Disable flushing on checkpoint. When disabled, the sink will not wait for all - * pending action requests to be acknowledged by Elasticsearch on checkpoints. - * - *

NOTE: If flushing on checkpoint is disabled, the Flink Elasticsearch Sink does NOT - * provide any strong guarantees for at-least-once delivery of action requests. - */ - public void disableFlushOnCheckpoint() { - this.flushOnCheckpoint = false; - } - - @Override - public void open(Configuration parameters) throws Exception { - client = callBridge.createClient(userConfig); - callBridge.verifyClientConnection(client); - bulkProcessor = buildBulkProcessor(new BulkProcessorListener()); - requestIndexer = callBridge.createBulkProcessorIndexer(bulkProcessor, flushOnCheckpoint, numPendingRequests); - failureRequestIndexer = new BufferingNoOpRequestIndexer(); - } - - @Override - public void invoke(T value, Context context) throws Exception { - checkAsyncErrorsAndRequests(); - elasticsearchSinkFunction.process(value, getRuntimeContext(), requestIndexer); - } - - @Override - public void initializeState(FunctionInitializationContext context) throws Exception { - // no initialization needed - } - - @Override - public void snapshotState(FunctionSnapshotContext context) throws Exception { - checkAsyncErrorsAndRequests(); - - if (flushOnCheckpoint) { - while (numPendingRequests.get() != 0) { - bulkProcessor.flush(); - checkAsyncErrorsAndRequests(); - } - } - } - - @Override - public void close() throws Exception { - if (bulkProcessor != null) { - bulkProcessor.close(); - bulkProcessor = null; - } - - if (client != null) { - client.close(); - client = null; - } - - callBridge.cleanup(); - - // make sure any errors from callbacks are rethrown - checkErrorAndRethrow(); - } - - /** - * Build the {@link BulkProcessor}. - * - *

Note: this is exposed for testing purposes. - */ - @VisibleForTesting - protected BulkProcessor buildBulkProcessor(BulkProcessor.Listener listener) { - checkNotNull(listener); - - BulkProcessor.Builder bulkProcessorBuilder = callBridge.createBulkProcessorBuilder(client, listener); - - // This makes flush() blocking - bulkProcessorBuilder.setConcurrentRequests(0); - - if (bulkProcessorFlushMaxActions != null) { - bulkProcessorBuilder.setBulkActions(bulkProcessorFlushMaxActions); - } - - if (bulkProcessorFlushMaxSizeMb != null) { - bulkProcessorBuilder.setBulkSize(new ByteSizeValue(bulkProcessorFlushMaxSizeMb, ByteSizeUnit.MB)); - } - - if (bulkProcessorFlushIntervalMillis != null) { - bulkProcessorBuilder.setFlushInterval(TimeValue.timeValueMillis(bulkProcessorFlushIntervalMillis)); - } - - // if backoff retrying is disabled, bulkProcessorFlushBackoffPolicy will be null - callBridge.configureBulkProcessorBackoff(bulkProcessorBuilder, bulkProcessorFlushBackoffPolicy); - - return bulkProcessorBuilder.build(); - } - - private void checkErrorAndRethrow() { - Throwable cause = failureThrowable.get(); - if (cause != null) { - throw new RuntimeException("An error occurred in ElasticsearchSink.", cause); - } - } - - private void checkAsyncErrorsAndRequests() { - checkErrorAndRethrow(); - failureRequestIndexer.processBufferedRequests(requestIndexer); - } - - private class BulkProcessorListener implements BulkProcessor.Listener { - - - private long lastVerifyTime = 0L; - - /** - * The interval time which check client whether available. - */ - private static final long verifyInterval = 22 * 60 * 60 * 1000L; - - @Override - public void beforeBulk(long executionId, BulkRequest request) { - - // verify client connection. - if ((System.currentTimeMillis() - lastVerifyTime) >= verifyInterval) { - try { - long currentTimeMillis = System.currentTimeMillis(); - callBridge.verifyClientConnection(client); - lastVerifyTime = currentTimeMillis; - } catch (IOException e) { - LOG.error("Verify and Refresh ClientConnection failed. Reason: {}", e.getMessage()); - failureThrowable.compareAndSet(null, e); - } - } - - } - - @Override - public void afterBulk(long executionId, BulkRequest request, BulkResponse response) { - if (response.hasFailures()) { - BulkItemResponse itemResponse; - Throwable failure; - RestStatus restStatus; - - try { - for (int i = 0; i < response.getItems().length; i++) { - itemResponse = response.getItems()[i]; - failure = callBridge.extractFailureCauseFromBulkItemResponse(itemResponse); - if (failure != null) { - LOG.error("Failed Elasticsearch item request: {}", itemResponse.getFailureMessage(), failure); - - restStatus = itemResponse.getFailure().getStatus(); - if (restStatus == null) { - failureHandler.onFailure((ActionRequest) request.requests().get(i), failure, -1, failureRequestIndexer); - } else { - failureHandler.onFailure((ActionRequest) request.requests().get(i), failure, restStatus.getStatus(), failureRequestIndexer); - } - } - } - } catch (Throwable t) { - // fail the sink and skip the rest of the items - // if the failure handler decides to throw an exception - failureThrowable.compareAndSet(null, t); - } - } - - if (flushOnCheckpoint) { - numPendingRequests.getAndAdd(-request.numberOfActions()); - } - } - - @Override - public void afterBulk(long executionId, BulkRequest request, Throwable failure) { - LOG.error("Failed Elasticsearch bulk request: {}", failure.getMessage(), failure); - - try { - for (DocWriteRequest action : request.requests()) { - failureHandler.onFailure((ActionRequest) action, failure, -1, failureRequestIndexer); - } - } catch (Throwable t) { - // fail the sink and skip the rest of the items - // if the failure handler decides to throw an exception - failureThrowable.compareAndSet(null, t); - } - - if (flushOnCheckpoint) { - numPendingRequests.getAndAdd(-request.numberOfActions()); - } - } - } - - @VisibleForTesting - long getNumPendingRequests() { - if (flushOnCheckpoint) { - return numPendingRequests.get(); - } else { - throw new UnsupportedOperationException( - "The number of pending requests is not maintained when flushing on checkpoint is disabled."); - } - } -} diff --git a/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/ElasticsearchSinkFunction.java b/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/ElasticsearchSinkFunction.java deleted file mode 100644 index 49790014b..000000000 --- a/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/ElasticsearchSinkFunction.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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.streaming.connectors.elasticsearch; - -import org.apache.flink.annotation.PublicEvolving; -import org.apache.flink.api.common.functions.Function; -import org.apache.flink.api.common.functions.RuntimeContext; -import transwarp.org.elasticsearch.action.ActionRequest; - - -import java.io.Serializable; - -/** - * Creates multiple {@link ActionRequest ActionRequests} from an element in a stream. - * - *

This is used by sinks to prepare elements for sending them to Elasticsearch. - * - *

Example: - * - *

{@code
- *					private static class TestElasticSearchSinkFunction implements
- *						ElasticsearchSinkFunction> {
- *
- *					public IndexRequest createIndexRequest(Tuple2 element) {
- *						Map json = new HashMap<>();
- *						json.put("data", element.f1);
- *
- *						return Requests.indexRequest()
- *							.index("my-index")
- *							.type("my-type")
- *							.id(element.f0.toString())
- *							.source(json);
- *						}
- *
- *				public void process(Tuple2 element, RuntimeContext ctx, RequestIndexer indexer) {
- *					indexer.add(createIndexRequest(element));
- *				}
- *		}
- *
- * }
- * - * @param The type of the element handled by this {@code ElasticsearchSinkFunction} - */ -@PublicEvolving -public interface ElasticsearchSinkFunction extends Serializable, Function { - - /** - * Process the incoming element to produce multiple {@link ActionRequest ActionsRequests}. - * The produced requests should be added to the provided {@link RequestIndexer}. - * - * @param element incoming element to process - * @param ctx runtime context containing information about the sink instance - * @param indexer request indexer that {@code ActionRequest} should be added to - */ - void process(T element, RuntimeContext ctx, RequestIndexer indexer); -} diff --git a/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/ElasticsearchUpsertTableSinkBase.java b/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/ElasticsearchUpsertTableSinkBase.java deleted file mode 100644 index e46c720d5..000000000 --- a/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/ElasticsearchUpsertTableSinkBase.java +++ /dev/null @@ -1,539 +0,0 @@ -/* - * 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.streaming.connectors.elasticsearch; - -import org.apache.flink.annotation.Internal; -import org.apache.flink.api.common.functions.RuntimeContext; -import org.apache.flink.api.common.serialization.SerializationSchema; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.common.typeinfo.Types; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.streaming.api.datastream.DataStream; -import org.apache.flink.streaming.api.datastream.DataStreamSink; -import org.apache.flink.streaming.api.functions.sink.SinkFunction; -import org.apache.flink.table.api.TableSchema; -import org.apache.flink.table.api.ValidationException; -import org.apache.flink.table.sinks.TableSink; -import org.apache.flink.table.sinks.UpsertStreamTableSink; -import org.apache.flink.table.typeutils.TypeCheckUtils; -import org.apache.flink.table.utils.TableConnectorUtils; -import org.apache.flink.table.utils.TableSchemaUtils; -import org.apache.flink.types.Row; -import org.apache.flink.util.Preconditions; -import transwarp.org.elasticsearch.action.ActionRequest; -import transwarp.org.elasticsearch.action.delete.DeleteRequest; -import transwarp.org.elasticsearch.action.index.IndexRequest; -import transwarp.org.elasticsearch.action.update.UpdateRequest; -import transwarp.org.elasticsearch.common.xcontent.XContentType; - -import java.io.Serializable; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -/** - * A version-agnostic Elasticsearch {@link UpsertStreamTableSink}. - */ -@Internal -public abstract class ElasticsearchUpsertTableSinkBase implements UpsertStreamTableSink { - - /** Flag that indicates that only inserts are accepted. */ - private final boolean isAppendOnly; - - /** Schema of the table. */ - private final TableSchema schema; - - /** Version-agnostic hosts configuration. */ - private final List hosts; - - /** Default index for all requests. */ - private final String index; - - /** Default document type for all requests. */ - private final String docType; - - /** Delimiter for composite keys. */ - private final String keyDelimiter; - - /** String literal for null keys. */ - private final String keyNullLiteral; - - /** Serialization schema used for the document. */ - private final SerializationSchema serializationSchema; - - /** Content type describing the serialization schema. */ - private final XContentType contentType; - - /** Failure handler for failing {@link ActionRequest}s. */ - private final ActionRequestFailureHandler failureHandler; - - /** - * Map of optional configuration parameters for the Elasticsearch sink. The config is - * internal and can change at any time. - */ - private final Map sinkOptions; - - /** - * Version-agnostic creation of {@link ActionRequest}s. - */ - private final RequestFactory requestFactory; - - /** Key field indices determined by the query. */ - private int[] keyFieldIndices = new int[0]; - - public ElasticsearchUpsertTableSinkBase( - boolean isAppendOnly, - TableSchema schema, - List hosts, - String index, - String docType, - String keyDelimiter, - String keyNullLiteral, - SerializationSchema serializationSchema, - XContentType contentType, - ActionRequestFailureHandler failureHandler, - Map sinkOptions, - RequestFactory requestFactory) { - - this.isAppendOnly = isAppendOnly; - this.schema = TableSchemaUtils.checkNoGeneratedColumns(schema); - this.hosts = Preconditions.checkNotNull(hosts); - this.index = Preconditions.checkNotNull(index); - this.keyDelimiter = Preconditions.checkNotNull(keyDelimiter); - this.keyNullLiteral = Preconditions.checkNotNull(keyNullLiteral); - this.docType = Preconditions.checkNotNull(docType); - this.serializationSchema = Preconditions.checkNotNull(serializationSchema); - this.contentType = Preconditions.checkNotNull(contentType); - this.failureHandler = Preconditions.checkNotNull(failureHandler); - this.sinkOptions = Preconditions.checkNotNull(sinkOptions); - this.requestFactory = Preconditions.checkNotNull(requestFactory); - } - - @Override - public void setKeyFields(String[] keyNames) { - if (keyNames == null) { - this.keyFieldIndices = new int[0]; - return; - } - - final String[] fieldNames = getFieldNames(); - final int[] keyFieldIndices = new int[keyNames.length]; - for (int i = 0; i < keyNames.length; i++) { - keyFieldIndices[i] = -1; - for (int j = 0; j < fieldNames.length; j++) { - if (keyNames[i].equals(fieldNames[j])) { - keyFieldIndices[i] = j; - break; - } - } - if (keyFieldIndices[i] == -1) { - throw new RuntimeException("Invalid key fields: " + Arrays.toString(keyNames)); - } - } - - validateKeyTypes(keyFieldIndices); - - this.keyFieldIndices = keyFieldIndices; - } - - @Override - public void setIsAppendOnly(Boolean isAppendOnly) { - if (this.isAppendOnly && !isAppendOnly) { - throw new ValidationException( - "The given query is not supported by this sink because the sink is configured to " + - "operate in append mode only. Thus, it only support insertions (no queries " + - "with updating results)."); - } - } - - @Override - public TypeInformation getRecordType() { - return schema.toRowType(); - } - - @Override - public DataStreamSink consumeDataStream(DataStream> dataStream) { - final ElasticsearchUpsertSinkFunction upsertFunction = - new ElasticsearchUpsertSinkFunction( - index, - docType, - keyDelimiter, - keyNullLiteral, - serializationSchema, - contentType, - requestFactory, - keyFieldIndices); - final SinkFunction> sinkFunction = createSinkFunction( - hosts, - failureHandler, - sinkOptions, - upsertFunction); - return dataStream.addSink(sinkFunction) - .setParallelism(dataStream.getParallelism()) - .name(TableConnectorUtils.generateRuntimeName(this.getClass(), getFieldNames())); - } - - @Override - public void emitDataStream(DataStream> dataStream) { - consumeDataStream(dataStream); - } - - @Override - public TypeInformation> getOutputType() { - return Types.TUPLE(Types.BOOLEAN, getRecordType()); - } - - @Override - public String[] getFieldNames() { - return schema.getFieldNames(); - } - - @Override - public TypeInformation[] getFieldTypes() { - return schema.getFieldTypes(); - } - - @Override - public TableSink> configure(String[] fieldNames, TypeInformation[] fieldTypes) { - if (!Arrays.equals(getFieldNames(), fieldNames) || !Arrays.equals(getFieldTypes(), fieldTypes)) { - throw new ValidationException("Reconfiguration with different fields is not allowed. " + - "Expected: " + Arrays.toString(getFieldNames()) + " / " + Arrays.toString(getFieldTypes()) + ". " + - "But was: " + Arrays.toString(fieldNames) + " / " + Arrays.toString(fieldTypes)); - } - return copy( - isAppendOnly, - schema, - hosts, - index, - docType, - keyDelimiter, - keyNullLiteral, - serializationSchema, - contentType, - failureHandler, - sinkOptions, - requestFactory); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - org.apache.flink.streaming.connectors.elasticsearch.ElasticsearchUpsertTableSinkBase that = (org.apache.flink.streaming.connectors.elasticsearch.ElasticsearchUpsertTableSinkBase) o; - return Objects.equals(isAppendOnly, that.isAppendOnly) && - Objects.equals(schema, that.schema) && - Objects.equals(hosts, that.hosts) && - Objects.equals(index, that.index) && - Objects.equals(docType, that.docType) && - Objects.equals(keyDelimiter, that.keyDelimiter) && - Objects.equals(keyNullLiteral, that.keyNullLiteral) && - Objects.equals(serializationSchema, that.serializationSchema) && - Objects.equals(contentType, that.contentType) && - Objects.equals(failureHandler, that.failureHandler) && - Objects.equals(sinkOptions, that.sinkOptions); - } - - @Override - public int hashCode() { - return Objects.hash( - isAppendOnly, - schema, - hosts, - index, - docType, - keyDelimiter, - keyNullLiteral, - serializationSchema, - contentType, - failureHandler, - sinkOptions); - } - - // -------------------------------------------------------------------------------------------- - // For version-specific implementations - // -------------------------------------------------------------------------------------------- - - protected abstract org.apache.flink.streaming.connectors.elasticsearch.ElasticsearchUpsertTableSinkBase copy( - boolean isAppendOnly, - TableSchema schema, - List hosts, - String index, - String docType, - String keyDelimiter, - String keyNullLiteral, - SerializationSchema serializationSchema, - XContentType contentType, - ActionRequestFailureHandler failureHandler, - Map sinkOptions, - RequestFactory requestFactory); - - protected abstract SinkFunction> createSinkFunction( - List hosts, - ActionRequestFailureHandler failureHandler, - Map sinkOptions, - ElasticsearchUpsertSinkFunction upsertFunction); - - // -------------------------------------------------------------------------------------------- - // Helper methods - // -------------------------------------------------------------------------------------------- - - /** - * Validate the types that are used for conversion to string. - */ - private void validateKeyTypes(int[] keyFieldIndices) { - final TypeInformation[] types = getFieldTypes(); - for (int keyFieldIndex : keyFieldIndices) { - final TypeInformation type = types[keyFieldIndex]; - if (!TypeCheckUtils.isSimpleStringRepresentation(type)) { - throw new ValidationException( - "Only simple types that can be safely converted into a string representation " + - "can be used as keys. But was: " + type); - } - } - } - - // -------------------------------------------------------------------------------------------- - // Helper classes - // -------------------------------------------------------------------------------------------- - - /** - * Keys for optional parameterization of the sink. - */ - public enum SinkOption { - DISABLE_FLUSH_ON_CHECKPOINT, - BULK_FLUSH_MAX_ACTIONS, - BULK_FLUSH_MAX_SIZE, - BULK_FLUSH_INTERVAL, - BULK_FLUSH_BACKOFF_ENABLED, - BULK_FLUSH_BACKOFF_TYPE, - BULK_FLUSH_BACKOFF_RETRIES, - BULK_FLUSH_BACKOFF_DELAY, - REST_MAX_RETRY_TIMEOUT, - REST_PATH_PREFIX - } - - /** - * Entity for describing a host of Elasticsearch. - */ - public static class Host { - public final String hostname; - public final int port; - public final String protocol; - - public Host(String hostname, int port, String protocol) { - this.hostname = hostname; - this.port = port; - this.protocol = protocol; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - Host host = (Host) o; - return port == host.port && - Objects.equals(hostname, host.hostname) && - Objects.equals(protocol, host.protocol); - } - - @Override - public int hashCode() { - return Objects.hash( - hostname, - port, - protocol); - } - - @Override - public String toString() { - return protocol + "://" - + hostname + ":" - + port; - } - } - - /** - * For version-agnostic creating of {@link ActionRequest}s. - */ - public interface RequestFactory extends Serializable { - - /** - * Creates an update request to be added to a {@link RequestIndexer}. - * Note: the type field has been deprecated since Elasticsearch 7.x and it would not take any effort. - */ - UpdateRequest createUpdateRequest( - String index, - String docType, - String key, - XContentType contentType, - byte[] document); - - /** - * Creates an index request to be added to a {@link RequestIndexer}. - * Note: the type field has been deprecated since Elasticsearch 7.x and it would not take any effort. - */ - IndexRequest createIndexRequest( - String index, - String docType, - XContentType contentType, - byte[] document); - - /** - * Creates a delete request to be added to a {@link RequestIndexer}. - * Note: the type field has been deprecated since Elasticsearch 7.x and it would not take any effort. - */ - DeleteRequest createDeleteRequest( - String index, - String docType, - String key); - } - - /** - * Sink function for converting upserts into Elasticsearch {@link ActionRequest}s. - */ - public static class ElasticsearchUpsertSinkFunction implements ElasticsearchSinkFunction> { - - private final String index; - private final String docType; - private final String keyDelimiter; - private final String keyNullLiteral; - private final SerializationSchema serializationSchema; - private final XContentType contentType; - private final RequestFactory requestFactory; - private final int[] keyFieldIndices; - - public ElasticsearchUpsertSinkFunction( - String index, - String docType, - String keyDelimiter, - String keyNullLiteral, - SerializationSchema serializationSchema, - XContentType contentType, - RequestFactory requestFactory, - int[] keyFieldIndices) { - - this.index = Preconditions.checkNotNull(index); - this.docType = Preconditions.checkNotNull(docType); - this.keyDelimiter = Preconditions.checkNotNull(keyDelimiter); - this.serializationSchema = Preconditions.checkNotNull(serializationSchema); - this.contentType = Preconditions.checkNotNull(contentType); - this.keyFieldIndices = Preconditions.checkNotNull(keyFieldIndices); - this.requestFactory = Preconditions.checkNotNull(requestFactory); - this.keyNullLiteral = Preconditions.checkNotNull(keyNullLiteral); - } - - @Override - public void process(Tuple2 element, RuntimeContext ctx, RequestIndexer indexer) { - if (element.f0) { - processUpsert(element.f1, indexer); - } else { - processDelete(element.f1, indexer); - } - } - - private void processUpsert(Row row, RequestIndexer indexer) { - final byte[] document = serializationSchema.serialize(row); - if (keyFieldIndices.length == 0) { - final IndexRequest indexRequest = requestFactory.createIndexRequest( - index, - docType, - contentType, - document); - indexer.add(indexRequest); - } else { - final String key = createKey(row); - final UpdateRequest updateRequest = requestFactory.createUpdateRequest( - index, - docType, - key, - contentType, - document); - indexer.add(updateRequest); - } - } - - private void processDelete(Row row, RequestIndexer indexer) { - final String key = createKey(row); - final DeleteRequest deleteRequest = requestFactory.createDeleteRequest( - index, - docType, - key); - indexer.add(deleteRequest); - } - - private String createKey(Row row) { - final StringBuilder builder = new StringBuilder(); - for (int i = 0; i < keyFieldIndices.length; i++) { - final int keyFieldIndex = keyFieldIndices[i]; - if (i > 0) { - builder.append(keyDelimiter); - } - final Object value = row.getField(keyFieldIndex); - if (value == null) { - builder.append(keyNullLiteral); - } else { - builder.append(value.toString()); - } - } - return builder.toString(); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - ElasticsearchUpsertSinkFunction that = (ElasticsearchUpsertSinkFunction) o; - return Objects.equals(index, that.index) && - Objects.equals(docType, that.docType) && - Objects.equals(keyDelimiter, that.keyDelimiter) && - Objects.equals(keyNullLiteral, that.keyNullLiteral) && - Objects.equals(serializationSchema, that.serializationSchema) && - contentType == that.contentType && - Objects.equals(requestFactory, that.requestFactory) && - Arrays.equals(keyFieldIndices, that.keyFieldIndices); - } - - @Override - public int hashCode() { - int result = Objects.hash( - index, - docType, - keyDelimiter, - keyNullLiteral, - serializationSchema, - contentType, - requestFactory); - result = 31 * result + Arrays.hashCode(keyFieldIndices); - return result; - } - } -} diff --git a/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/ElasticsearchUpsertTableSinkFactoryBase.java b/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/ElasticsearchUpsertTableSinkFactoryBase.java deleted file mode 100644 index d13a19580..000000000 --- a/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/ElasticsearchUpsertTableSinkFactoryBase.java +++ /dev/null @@ -1,316 +0,0 @@ -/* - * 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.streaming.connectors.elasticsearch; - -import org.apache.flink.annotation.Internal; -import org.apache.flink.api.common.serialization.SerializationSchema; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.streaming.connectors.elasticsearch.ElasticsearchUpsertTableSinkBase.Host; -import org.apache.flink.streaming.connectors.elasticsearch.ElasticsearchUpsertTableSinkBase.SinkOption; -import org.apache.flink.streaming.connectors.elasticsearch.util.IgnoringFailureHandler; -import org.apache.flink.streaming.connectors.elasticsearch.util.NoOpFailureHandler; -import org.apache.flink.streaming.connectors.elasticsearch.util.RetryRejectedExecutionFailureHandler; -import org.apache.flink.table.api.TableSchema; -import org.apache.flink.table.api.ValidationException; -import org.apache.flink.table.descriptors.DescriptorProperties; -import org.apache.flink.table.descriptors.ElasticsearchValidator; -import org.apache.flink.table.descriptors.SchemaValidator; -import org.apache.flink.table.descriptors.StreamTableDescriptorValidator; -import org.apache.flink.table.factories.SerializationSchemaFactory; -import org.apache.flink.table.factories.StreamTableSinkFactory; -import org.apache.flink.table.factories.TableFactoryService; -import org.apache.flink.table.sinks.StreamTableSink; -import org.apache.flink.table.sinks.UpsertStreamTableSink; -import org.apache.flink.table.utils.TableSchemaUtils; -import org.apache.flink.types.Row; -import org.apache.flink.util.InstantiationUtil; -import transwarp.org.elasticsearch.common.xcontent.XContentType; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import static org.apache.flink.table.descriptors.ConnectorDescriptorValidator.CONNECTOR_PROPERTY_VERSION; -import static org.apache.flink.table.descriptors.ConnectorDescriptorValidator.CONNECTOR_TYPE; -import static org.apache.flink.table.descriptors.ConnectorDescriptorValidator.CONNECTOR_VERSION; -import static org.apache.flink.table.descriptors.DescriptorProperties.TABLE_SCHEMA_EXPR; -import static org.apache.flink.table.descriptors.DescriptorProperties.WATERMARK; -import static org.apache.flink.table.descriptors.DescriptorProperties.WATERMARK_ROWTIME; -import static org.apache.flink.table.descriptors.DescriptorProperties.WATERMARK_STRATEGY_DATA_TYPE; -import static org.apache.flink.table.descriptors.DescriptorProperties.WATERMARK_STRATEGY_EXPR; -import static org.apache.flink.table.descriptors.ElasticsearchValidator.CONNECTOR_BULK_FLUSH_BACKOFF_DELAY; -import static org.apache.flink.table.descriptors.ElasticsearchValidator.CONNECTOR_BULK_FLUSH_BACKOFF_MAX_RETRIES; -import static org.apache.flink.table.descriptors.ElasticsearchValidator.CONNECTOR_BULK_FLUSH_BACKOFF_TYPE; -import static org.apache.flink.table.descriptors.ElasticsearchValidator.CONNECTOR_BULK_FLUSH_BACKOFF_TYPE_VALUE_CONSTANT; -import static org.apache.flink.table.descriptors.ElasticsearchValidator.CONNECTOR_BULK_FLUSH_BACKOFF_TYPE_VALUE_DISABLED; -import static org.apache.flink.table.descriptors.ElasticsearchValidator.CONNECTOR_BULK_FLUSH_BACKOFF_TYPE_VALUE_EXPONENTIAL; -import static org.apache.flink.table.descriptors.ElasticsearchValidator.CONNECTOR_BULK_FLUSH_INTERVAL; -import static org.apache.flink.table.descriptors.ElasticsearchValidator.CONNECTOR_BULK_FLUSH_MAX_ACTIONS; -import static org.apache.flink.table.descriptors.ElasticsearchValidator.CONNECTOR_BULK_FLUSH_MAX_SIZE; -import static org.apache.flink.table.descriptors.ElasticsearchValidator.CONNECTOR_CONNECTION_MAX_RETRY_TIMEOUT; -import static org.apache.flink.table.descriptors.ElasticsearchValidator.CONNECTOR_CONNECTION_PATH_PREFIX; -import static org.apache.flink.table.descriptors.ElasticsearchValidator.CONNECTOR_DOCUMENT_TYPE; -import static org.apache.flink.table.descriptors.ElasticsearchValidator.CONNECTOR_FAILURE_HANDLER; -import static org.apache.flink.table.descriptors.ElasticsearchValidator.CONNECTOR_FAILURE_HANDLER_CLASS; -import static org.apache.flink.table.descriptors.ElasticsearchValidator.CONNECTOR_FAILURE_HANDLER_VALUE_CUSTOM; -import static org.apache.flink.table.descriptors.ElasticsearchValidator.CONNECTOR_FAILURE_HANDLER_VALUE_FAIL; -import static org.apache.flink.table.descriptors.ElasticsearchValidator.CONNECTOR_FAILURE_HANDLER_VALUE_IGNORE; -import static org.apache.flink.table.descriptors.ElasticsearchValidator.CONNECTOR_FAILURE_HANDLER_VALUE_RETRY; -import static org.apache.flink.table.descriptors.ElasticsearchValidator.CONNECTOR_FLUSH_ON_CHECKPOINT; -import static org.apache.flink.table.descriptors.ElasticsearchValidator.CONNECTOR_HOSTS; -import static org.apache.flink.table.descriptors.ElasticsearchValidator.CONNECTOR_HOSTS_HOSTNAME; -import static org.apache.flink.table.descriptors.ElasticsearchValidator.CONNECTOR_HOSTS_PORT; -import static org.apache.flink.table.descriptors.ElasticsearchValidator.CONNECTOR_HOSTS_PROTOCOL; -import static org.apache.flink.table.descriptors.ElasticsearchValidator.CONNECTOR_INDEX; -import static org.apache.flink.table.descriptors.ElasticsearchValidator.CONNECTOR_KEY_DELIMITER; -import static org.apache.flink.table.descriptors.ElasticsearchValidator.CONNECTOR_KEY_NULL_LITERAL; -import static org.apache.flink.table.descriptors.ElasticsearchValidator.CONNECTOR_TYPE_VALUE_ELASTICSEARCH; -import static org.apache.flink.table.descriptors.ElasticsearchValidator.validateAndParseHostsString; -import static org.apache.flink.table.descriptors.FormatDescriptorValidator.FORMAT; -import static org.apache.flink.table.descriptors.FormatDescriptorValidator.FORMAT_TYPE; -import static org.apache.flink.table.descriptors.Schema.SCHEMA; -import static org.apache.flink.table.descriptors.Schema.SCHEMA_DATA_TYPE; -import static org.apache.flink.table.descriptors.Schema.SCHEMA_NAME; -import static org.apache.flink.table.descriptors.Schema.SCHEMA_TYPE; -import static org.apache.flink.table.descriptors.StreamTableDescriptorValidator.UPDATE_MODE; -import static org.apache.flink.table.descriptors.StreamTableDescriptorValidator.UPDATE_MODE_VALUE_APPEND; - -/** - * Version-agnostic table factory for creating an {@link UpsertStreamTableSink} for Elasticsearch. - */ -@Internal -public abstract class ElasticsearchUpsertTableSinkFactoryBase implements StreamTableSinkFactory> { - - private static final String SUPPORTED_FORMAT_TYPE = "json"; - private static final XContentType SUPPORTED_CONTENT_TYPE = XContentType.JSON; - private static final String DEFAULT_KEY_DELIMITER = "_"; - private static final String DEFAULT_KEY_NULL_LITERAL = "null"; - private static final String DEFAULT_FAILURE_HANDLER = CONNECTOR_FAILURE_HANDLER_VALUE_FAIL; - - @Override - public Map requiredContext() { - final Map context = new HashMap<>(); - context.put(CONNECTOR_TYPE, CONNECTOR_TYPE_VALUE_ELASTICSEARCH); - context.put(CONNECTOR_VERSION, elasticsearchVersion()); - context.put(CONNECTOR_PROPERTY_VERSION, "1"); - return context; - } - - @Override - public List supportedProperties() { - final List properties = new ArrayList<>(); - - // streaming properties - properties.add(UPDATE_MODE); - - // Elasticsearch - properties.add(CONNECTOR_HOSTS); - properties.add(CONNECTOR_HOSTS + ".#." + CONNECTOR_HOSTS_HOSTNAME); - properties.add(CONNECTOR_HOSTS + ".#." + CONNECTOR_HOSTS_PORT); - properties.add(CONNECTOR_HOSTS + ".#." + CONNECTOR_HOSTS_PROTOCOL); - properties.add(CONNECTOR_INDEX); - properties.add(CONNECTOR_DOCUMENT_TYPE); - properties.add(CONNECTOR_KEY_DELIMITER); - properties.add(CONNECTOR_KEY_NULL_LITERAL); - properties.add(CONNECTOR_FAILURE_HANDLER); - properties.add(CONNECTOR_FAILURE_HANDLER_CLASS); - properties.add(CONNECTOR_FLUSH_ON_CHECKPOINT); - properties.add(CONNECTOR_BULK_FLUSH_MAX_ACTIONS); - properties.add(CONNECTOR_BULK_FLUSH_MAX_SIZE); - properties.add(CONNECTOR_BULK_FLUSH_INTERVAL); - properties.add(CONNECTOR_BULK_FLUSH_BACKOFF_TYPE); - properties.add(CONNECTOR_BULK_FLUSH_BACKOFF_MAX_RETRIES); - properties.add(CONNECTOR_BULK_FLUSH_BACKOFF_DELAY); - properties.add(CONNECTOR_CONNECTION_MAX_RETRY_TIMEOUT); - properties.add(CONNECTOR_CONNECTION_PATH_PREFIX); - - // schema - properties.add(SCHEMA + ".#." + SCHEMA_DATA_TYPE); - properties.add(SCHEMA + ".#." + SCHEMA_TYPE); - properties.add(SCHEMA + ".#." + SCHEMA_NAME); - // computed column - properties.add(SCHEMA + ".#." + TABLE_SCHEMA_EXPR); - - // watermark - properties.add(SCHEMA + "." + WATERMARK + ".#." + WATERMARK_ROWTIME); - properties.add(SCHEMA + "." + WATERMARK + ".#." + WATERMARK_STRATEGY_EXPR); - properties.add(SCHEMA + "." + WATERMARK + ".#." + WATERMARK_STRATEGY_DATA_TYPE); - - // format wildcard - properties.add(FORMAT + ".*"); - - return properties; - } - - @Override - public StreamTableSink> createStreamTableSink(Map properties) { - final DescriptorProperties descriptorProperties = getValidatedProperties(properties); - - return createElasticsearchUpsertTableSink( - descriptorProperties.isValue(UPDATE_MODE, UPDATE_MODE_VALUE_APPEND), - TableSchemaUtils.getPhysicalSchema(descriptorProperties.getTableSchema(SCHEMA)), - getHosts(descriptorProperties), - descriptorProperties.getString(CONNECTOR_INDEX), - descriptorProperties.getString(CONNECTOR_DOCUMENT_TYPE), - descriptorProperties.getOptionalString(CONNECTOR_KEY_DELIMITER).orElse(DEFAULT_KEY_DELIMITER), - descriptorProperties.getOptionalString(CONNECTOR_KEY_NULL_LITERAL).orElse(DEFAULT_KEY_NULL_LITERAL), - getSerializationSchema(properties), - SUPPORTED_CONTENT_TYPE, - getFailureHandler(descriptorProperties), - getSinkOptions(descriptorProperties)); - } - - // -------------------------------------------------------------------------------------------- - // For version-specific factories - // -------------------------------------------------------------------------------------------- - - protected abstract String elasticsearchVersion(); - - protected abstract ElasticsearchUpsertTableSinkBase createElasticsearchUpsertTableSink( - boolean isAppendOnly, - TableSchema schema, - List hosts, - String index, - String docType, - String keyDelimiter, - String keyNullLiteral, - SerializationSchema serializationSchema, - XContentType contentType, - ActionRequestFailureHandler failureHandler, - Map sinkOptions); - - // -------------------------------------------------------------------------------------------- - // Helper methods - // -------------------------------------------------------------------------------------------- - - private DescriptorProperties getValidatedProperties(Map properties) { - final DescriptorProperties descriptorProperties = new DescriptorProperties(true); - descriptorProperties.putProperties(properties); - - new StreamTableDescriptorValidator(true, false, true).validate(descriptorProperties); - new SchemaValidator(true, false, false).validate(descriptorProperties); - new ElasticsearchValidator().validate(descriptorProperties); - - return descriptorProperties; - } - - private List getHosts(DescriptorProperties descriptorProperties) { - if (descriptorProperties.containsKey(CONNECTOR_HOSTS)) { - return validateAndParseHostsString(descriptorProperties); - } else { - final List> hosts = descriptorProperties.getFixedIndexedProperties( - CONNECTOR_HOSTS, - Arrays.asList(CONNECTOR_HOSTS_HOSTNAME, CONNECTOR_HOSTS_PORT, CONNECTOR_HOSTS_PROTOCOL)); - return hosts.stream() - .map(host -> new Host( - descriptorProperties.getString(host.get(CONNECTOR_HOSTS_HOSTNAME)), - descriptorProperties.getInt(host.get(CONNECTOR_HOSTS_PORT)), - descriptorProperties.getString(host.get(CONNECTOR_HOSTS_PROTOCOL)))) - .collect(Collectors.toList()); - } - } - - private SerializationSchema getSerializationSchema(Map properties) { - final String formatType = properties.get(FORMAT_TYPE); - // we could have added this check to the table factory context - // but this approach allows to throw more helpful error messages - // if the supported format has not been added - if (formatType == null || !formatType.equals(SUPPORTED_FORMAT_TYPE)) { - throw new ValidationException( - "The Elasticsearch sink requires a '" + SUPPORTED_FORMAT_TYPE + "' format."); - } - - @SuppressWarnings("unchecked") - final SerializationSchemaFactory formatFactory = TableFactoryService.find( - SerializationSchemaFactory.class, - properties, - this.getClass().getClassLoader()); - return formatFactory.createSerializationSchema(properties); - } - - private ActionRequestFailureHandler getFailureHandler(DescriptorProperties descriptorProperties) { - final String failureHandler = descriptorProperties - .getOptionalString(CONNECTOR_FAILURE_HANDLER) - .orElse(DEFAULT_FAILURE_HANDLER); - switch (failureHandler) { - case CONNECTOR_FAILURE_HANDLER_VALUE_FAIL: - return new NoOpFailureHandler(); - case CONNECTOR_FAILURE_HANDLER_VALUE_IGNORE: - return new IgnoringFailureHandler(); - case CONNECTOR_FAILURE_HANDLER_VALUE_RETRY: - return new RetryRejectedExecutionFailureHandler(); - case CONNECTOR_FAILURE_HANDLER_VALUE_CUSTOM: - final Class clazz = descriptorProperties - .getClass(CONNECTOR_FAILURE_HANDLER_CLASS, ActionRequestFailureHandler.class); - return InstantiationUtil.instantiate(clazz); - default: - throw new IllegalArgumentException("Unknown failure handler."); - } - } - - private Map getSinkOptions(DescriptorProperties descriptorProperties) { - final Map options = new HashMap<>(); - - descriptorProperties.getOptionalBoolean(CONNECTOR_FLUSH_ON_CHECKPOINT) - .ifPresent(v -> options.put(SinkOption.DISABLE_FLUSH_ON_CHECKPOINT, String.valueOf(!v))); - - mapSinkOption(descriptorProperties, options, CONNECTOR_BULK_FLUSH_MAX_ACTIONS, SinkOption.BULK_FLUSH_MAX_ACTIONS); - mapSinkOption(descriptorProperties, options, CONNECTOR_BULK_FLUSH_MAX_SIZE, SinkOption.BULK_FLUSH_MAX_SIZE); - mapSinkOption(descriptorProperties, options, CONNECTOR_BULK_FLUSH_INTERVAL, SinkOption.BULK_FLUSH_INTERVAL); - - descriptorProperties.getOptionalString(CONNECTOR_BULK_FLUSH_BACKOFF_TYPE) - .ifPresent(v -> { - options.put( - SinkOption.BULK_FLUSH_BACKOFF_ENABLED, - String.valueOf(!v.equals(CONNECTOR_BULK_FLUSH_BACKOFF_TYPE_VALUE_DISABLED))); - switch (v) { - case CONNECTOR_BULK_FLUSH_BACKOFF_TYPE_VALUE_CONSTANT: - options.put( - SinkOption.BULK_FLUSH_BACKOFF_TYPE, - ElasticsearchSinkBase.FlushBackoffType.CONSTANT.toString()); - break; - case CONNECTOR_BULK_FLUSH_BACKOFF_TYPE_VALUE_EXPONENTIAL: - options.put( - SinkOption.BULK_FLUSH_BACKOFF_TYPE, - ElasticsearchSinkBase.FlushBackoffType.EXPONENTIAL.toString()); - break; - default: - throw new IllegalArgumentException("Unknown backoff type."); - } - }); - - mapSinkOption(descriptorProperties, options, CONNECTOR_BULK_FLUSH_BACKOFF_MAX_RETRIES, SinkOption.BULK_FLUSH_BACKOFF_RETRIES); - mapSinkOption(descriptorProperties, options, CONNECTOR_BULK_FLUSH_BACKOFF_DELAY, SinkOption.BULK_FLUSH_BACKOFF_DELAY); - mapSinkOption(descriptorProperties, options, CONNECTOR_CONNECTION_MAX_RETRY_TIMEOUT, SinkOption.REST_MAX_RETRY_TIMEOUT); - mapSinkOption(descriptorProperties, options, CONNECTOR_CONNECTION_PATH_PREFIX, SinkOption.REST_PATH_PREFIX); - - return options; - } - - private void mapSinkOption( - DescriptorProperties descriptorProperties, - Map options, - String fromKey, - SinkOption toKey) { - descriptorProperties.getOptionalString(fromKey).ifPresent(v -> options.put(toKey, v)); - } -} diff --git a/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/PreElasticsearch6BulkProcessorIndexer.java b/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/PreElasticsearch6BulkProcessorIndexer.java deleted file mode 100644 index 9de123bd5..000000000 --- a/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/PreElasticsearch6BulkProcessorIndexer.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * 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.streaming.connectors.elasticsearch; - -import org.apache.flink.annotation.Internal; -import transwarp.org.elasticsearch.action.ActionRequest; -import transwarp.org.elasticsearch.action.bulk.BulkProcessor; -import transwarp.org.elasticsearch.action.delete.DeleteRequest; -import transwarp.org.elasticsearch.action.index.IndexRequest; -import transwarp.org.elasticsearch.action.update.UpdateRequest; - - -import java.util.concurrent.atomic.AtomicLong; - -import static org.apache.flink.util.Preconditions.checkNotNull; - -/** - * Implementation of a {@link RequestIndexer}, using a {@link BulkProcessor}. - * {@link ActionRequest ActionRequests} will be buffered before sending a bulk request to the Elasticsearch cluster. - * - * @deprecated This class is not binary compatible with newer Elasticsearch 6+ versions - * (i.e. the {@link #add(UpdateRequest...)} ). However, this module is currently - * compiled against a very old Elasticsearch version. - */ -@Deprecated -@Internal -class PreElasticsearch6BulkProcessorIndexer implements RequestIndexer { - - private final BulkProcessor bulkProcessor; - private final boolean flushOnCheckpoint; - private final AtomicLong numPendingRequestsRef; - - PreElasticsearch6BulkProcessorIndexer(BulkProcessor bulkProcessor, boolean flushOnCheckpoint, AtomicLong numPendingRequestsRef) { - this.bulkProcessor = checkNotNull(bulkProcessor); - this.flushOnCheckpoint = flushOnCheckpoint; - this.numPendingRequestsRef = checkNotNull(numPendingRequestsRef); - } - - @Override - public void add(DeleteRequest... deleteRequests) { - for (DeleteRequest deleteRequest : deleteRequests) { - if (flushOnCheckpoint) { - numPendingRequestsRef.getAndIncrement(); - } - this.bulkProcessor.add(deleteRequest); - } - } - - @Override - public void add(IndexRequest... indexRequests) { - for (IndexRequest indexRequest : indexRequests) { - if (flushOnCheckpoint) { - numPendingRequestsRef.getAndIncrement(); - } - this.bulkProcessor.add(indexRequest); - } - } - - @Override - public void add(UpdateRequest... updateRequests) { - for (UpdateRequest updateRequest : updateRequests) { - if (flushOnCheckpoint) { - numPendingRequestsRef.getAndIncrement(); - } - this.bulkProcessor.add(updateRequest); - } - } -} diff --git a/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/RequestIndexer.java b/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/RequestIndexer.java deleted file mode 100644 index 11a451546..000000000 --- a/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/RequestIndexer.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * 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.streaming.connectors.elasticsearch; - -import org.apache.flink.annotation.PublicEvolving; -import transwarp.org.elasticsearch.action.ActionRequest; -import transwarp.org.elasticsearch.action.delete.DeleteRequest; -import transwarp.org.elasticsearch.action.index.IndexRequest; -import transwarp.org.elasticsearch.action.update.UpdateRequest; - - -/** - * Users add multiple delete, index or update requests to a {@link org.apache.flink.streaming.connectors.elasticsearch.RequestIndexer} to prepare - * them for sending to an Elasticsearch cluster. - */ -@PublicEvolving -public interface RequestIndexer { - - /** - * Add multiple {@link ActionRequest} to the indexer to prepare for sending requests to Elasticsearch. - * - * @param actionRequests The multiple {@link ActionRequest} to add. - * @deprecated use the {@link DeleteRequest}, {@link IndexRequest} or {@link UpdateRequest} - */ - @Deprecated - default void add(ActionRequest... actionRequests) { - for (ActionRequest actionRequest : actionRequests) { - if (actionRequest instanceof IndexRequest) { - add((IndexRequest) actionRequest); - } else if (actionRequest instanceof DeleteRequest) { - add((DeleteRequest) actionRequest); - } else if (actionRequest instanceof UpdateRequest) { - add((UpdateRequest) actionRequest); - } else { - throw new IllegalArgumentException("RequestIndexer only supports Index, Delete and Update requests"); - } - } - } - - /** - * Add multiple {@link DeleteRequest} to the indexer to prepare for sending requests to Elasticsearch. - * - * @param deleteRequests The multiple {@link DeleteRequest} to add. - */ - void add(DeleteRequest... deleteRequests); - - /** - * Add multiple {@link IndexRequest} to the indexer to prepare for sending requests to Elasticsearch. - * - * @param indexRequests The multiple {@link IndexRequest} to add. - */ - void add(IndexRequest... indexRequests); - - /** - * Add multiple {@link UpdateRequest} to the indexer to prepare for sending requests to Elasticsearch. - * - * @param updateRequests The multiple {@link UpdateRequest} to add. - */ - void add(UpdateRequest... updateRequests); -} diff --git a/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/util/ElasticsearchUtils.java b/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/util/ElasticsearchUtils.java deleted file mode 100644 index 008bed990..000000000 --- a/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/util/ElasticsearchUtils.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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.streaming.connectors.elasticsearch.util; - -import org.apache.flink.annotation.Internal; -import transwarp.org.elasticsearch.common.transport.InetSocketTransportAddress; -import transwarp.org.elasticsearch.common.transport.TransportAddress; - - -import java.net.InetSocketAddress; -import java.util.ArrayList; -import java.util.List; - -/** - * Suite of utility methods for Elasticsearch. - */ -@Internal -public class ElasticsearchUtils { - - /** - * Utility method to convert a {@link List} of {@link InetSocketAddress} to Elasticsearch {@link TransportAddress}. - * - * @param inetSocketAddresses The list of {@link InetSocketAddress} to convert. - */ - public static List convertInetSocketAddresses(List inetSocketAddresses) { - if (inetSocketAddresses == null) { - return null; - } else { - List converted; - converted = new ArrayList<>(inetSocketAddresses.size()); - for (InetSocketAddress address : inetSocketAddresses) { - converted.add(new InetSocketTransportAddress(address)); - } - return converted; - } - } - -} diff --git a/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/util/IgnoringFailureHandler.java b/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/util/IgnoringFailureHandler.java deleted file mode 100644 index ed33e319c..000000000 --- a/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/util/IgnoringFailureHandler.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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.streaming.connectors.elasticsearch.util; - -import org.apache.flink.annotation.Internal; -import org.apache.flink.streaming.connectors.elasticsearch.ActionRequestFailureHandler; -import org.apache.flink.streaming.connectors.elasticsearch.RequestIndexer; -import transwarp.org.elasticsearch.action.ActionRequest; - - -/** - * Ignores all kinds of failures and drops the affected {@link ActionRequest}. - */ -@Internal -public class IgnoringFailureHandler implements ActionRequestFailureHandler { - - private static final long serialVersionUID = 1662846593501L; - - @Override - public void onFailure(ActionRequest action, Throwable failure, int restStatusCode, RequestIndexer indexer) { - // ignore failure - } -} diff --git a/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/util/NoOpFailureHandler.java b/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/util/NoOpFailureHandler.java deleted file mode 100644 index e909defbf..000000000 --- a/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/util/NoOpFailureHandler.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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.streaming.connectors.elasticsearch.util; - -import org.apache.flink.annotation.Internal; -import org.apache.flink.streaming.connectors.elasticsearch.ActionRequestFailureHandler; -import org.apache.flink.streaming.connectors.elasticsearch.RequestIndexer; -import transwarp.org.elasticsearch.action.ActionRequest; - - -/** - * An {@link ActionRequestFailureHandler} that simply fails the sink on any failures. - */ -@Internal -public class NoOpFailureHandler implements ActionRequestFailureHandler { - - private static final long serialVersionUID = 737941343410827885L; - - @Override - public void onFailure(ActionRequest action, Throwable failure, int restStatusCode, RequestIndexer indexer) throws Throwable { - // simply fail the sink - throw failure; - } - -} diff --git a/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/util/RetryRejectedExecutionFailureHandler.java b/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/util/RetryRejectedExecutionFailureHandler.java deleted file mode 100644 index 035961774..000000000 --- a/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/util/RetryRejectedExecutionFailureHandler.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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.streaming.connectors.elasticsearch.util; - -import org.apache.flink.annotation.PublicEvolving; -import org.apache.flink.streaming.connectors.elasticsearch.ActionRequestFailureHandler; -import org.apache.flink.streaming.connectors.elasticsearch.RequestIndexer; -import org.apache.flink.util.ExceptionUtils; - -import transwarp.org.elasticsearch.action.ActionRequest; -import transwarp.org.elasticsearch.common.util.concurrent.EsRejectedExecutionException; - -/** - * An {@link ActionRequestFailureHandler} that re-adds requests that failed due to temporary - * {@link EsRejectedExecutionException}s (which means that Elasticsearch node queues are currently full), - * and fails for all other failures. - */ -@PublicEvolving -public class RetryRejectedExecutionFailureHandler implements ActionRequestFailureHandler { - - private static final long serialVersionUID = -7423562912824511906L; - - @Override - public void onFailure(ActionRequest action, Throwable failure, int restStatusCode, RequestIndexer indexer) throws Throwable { - if (ExceptionUtils.findThrowable(failure, EsRejectedExecutionException.class).isPresent()) { - indexer.add(action); - } else { - // rethrow all other failures - throw failure; - } - } - -} diff --git a/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/org/apache/flink/table/descriptors/Elasticsearch.java b/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/org/apache/flink/table/descriptors/Elasticsearch.java deleted file mode 100644 index e2cf2eeb0..000000000 --- a/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/org/apache/flink/table/descriptors/Elasticsearch.java +++ /dev/null @@ -1,316 +0,0 @@ -/* - * 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.descriptors; - -import org.apache.flink.annotation.PublicEvolving; -import org.apache.flink.configuration.MemorySize; -import org.apache.flink.streaming.connectors.elasticsearch.ActionRequestFailureHandler; -import org.apache.flink.streaming.connectors.elasticsearch.ElasticsearchUpsertTableSinkBase.Host; -import org.apache.flink.util.Preconditions; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import static org.apache.flink.table.descriptors.ConnectorDescriptorValidator.CONNECTOR_VERSION; -import static org.apache.flink.table.descriptors.ElasticsearchValidator.CONNECTOR_BULK_FLUSH_BACKOFF_DELAY; -import static org.apache.flink.table.descriptors.ElasticsearchValidator.CONNECTOR_BULK_FLUSH_BACKOFF_MAX_RETRIES; -import static org.apache.flink.table.descriptors.ElasticsearchValidator.CONNECTOR_BULK_FLUSH_BACKOFF_TYPE; -import static org.apache.flink.table.descriptors.ElasticsearchValidator.CONNECTOR_BULK_FLUSH_INTERVAL; -import static org.apache.flink.table.descriptors.ElasticsearchValidator.CONNECTOR_BULK_FLUSH_MAX_ACTIONS; -import static org.apache.flink.table.descriptors.ElasticsearchValidator.CONNECTOR_BULK_FLUSH_MAX_SIZE; -import static org.apache.flink.table.descriptors.ElasticsearchValidator.CONNECTOR_CONNECTION_MAX_RETRY_TIMEOUT; -import static org.apache.flink.table.descriptors.ElasticsearchValidator.CONNECTOR_CONNECTION_PATH_PREFIX; -import static org.apache.flink.table.descriptors.ElasticsearchValidator.CONNECTOR_DOCUMENT_TYPE; -import static org.apache.flink.table.descriptors.ElasticsearchValidator.CONNECTOR_FAILURE_HANDLER; -import static org.apache.flink.table.descriptors.ElasticsearchValidator.CONNECTOR_FAILURE_HANDLER_CLASS; -import static org.apache.flink.table.descriptors.ElasticsearchValidator.CONNECTOR_FLUSH_ON_CHECKPOINT; -import static org.apache.flink.table.descriptors.ElasticsearchValidator.CONNECTOR_HOSTS; -import static org.apache.flink.table.descriptors.ElasticsearchValidator.CONNECTOR_INDEX; -import static org.apache.flink.table.descriptors.ElasticsearchValidator.CONNECTOR_KEY_DELIMITER; -import static org.apache.flink.table.descriptors.ElasticsearchValidator.CONNECTOR_KEY_NULL_LITERAL; -import static org.apache.flink.table.descriptors.ElasticsearchValidator.CONNECTOR_TYPE_VALUE_ELASTICSEARCH; - -/** - * Connector descriptor for the Elasticsearch search engine. - */ -@PublicEvolving -public class Elasticsearch extends ConnectorDescriptor { - - private DescriptorProperties internalProperties = new DescriptorProperties(true); - private List hosts = new ArrayList<>(); - - /** - * Connector descriptor for the Elasticsearch search engine. - */ - public Elasticsearch() { - super(CONNECTOR_TYPE_VALUE_ELASTICSEARCH, 1, true); - } - - /** - * Sets the Elasticsearch version to be used. Required. - * - * @param version Elasticsearch version. E.g., "6". - */ - public org.apache.flink.table.descriptors.Elasticsearch version(String version) { - internalProperties.putString(CONNECTOR_VERSION, version); - return this; - } - - /** - * Adds an Elasticsearch host to connect to. Required. - * - *

Multiple hosts can be declared by calling this method multiple times. - * - * @param hostname connection hostname - * @param port connection port - * @param protocol connection protocol; e.g. "http" - */ - public org.apache.flink.table.descriptors.Elasticsearch host(String hostname, int port, String protocol) { - final Host host = - new Host( - Preconditions.checkNotNull(hostname), - port, - Preconditions.checkNotNull(protocol)); - hosts.add(host); - return this; - } - - /** - * Declares the Elasticsearch index for every record. Required. - * - * @param index Elasticsearch index - */ - public org.apache.flink.table.descriptors.Elasticsearch index(String index) { - internalProperties.putString(CONNECTOR_INDEX, index); - return this; - } - - /** - * Declares the Elasticsearch document type for every record. Required. - * - * @param documentType Elasticsearch document type - */ - public org.apache.flink.table.descriptors.Elasticsearch documentType(String documentType) { - internalProperties.putString(CONNECTOR_DOCUMENT_TYPE, documentType); - return this; - } - - /** - * Sets a custom key delimiter in case the Elasticsearch ID needs to be constructed from - * multiple fields. Optional. - * - * @param keyDelimiter key delimiter; e.g., "$" would result in IDs "KEY1$KEY2$KEY3" - */ - public org.apache.flink.table.descriptors.Elasticsearch keyDelimiter(String keyDelimiter) { - internalProperties.putString(CONNECTOR_KEY_DELIMITER, keyDelimiter); - return this; - } - - /** - * Sets a custom representation for null fields in keys. Optional. - * - * @param keyNullLiteral key null literal string; e.g. "N/A" would result in IDs "KEY1_N/A_KEY3" - */ - public org.apache.flink.table.descriptors.Elasticsearch keyNullLiteral(String keyNullLiteral) { - internalProperties.putString(CONNECTOR_KEY_NULL_LITERAL, keyNullLiteral); - return this; - } - - /** - * Configures a failure handling strategy in case a request to Elasticsearch fails. - * - *

This strategy throws an exception if a request fails and thus causes a job failure. - */ - public org.apache.flink.table.descriptors.Elasticsearch failureHandlerFail() { - internalProperties.putString(CONNECTOR_FAILURE_HANDLER, ElasticsearchValidator.CONNECTOR_FAILURE_HANDLER_VALUE_FAIL); - return this; - } - - /** - * Configures a failure handling strategy in case a request to Elasticsearch fails. - * - *

This strategy ignores failures and drops the request. - */ - public org.apache.flink.table.descriptors.Elasticsearch failureHandlerIgnore() { - internalProperties.putString(CONNECTOR_FAILURE_HANDLER, ElasticsearchValidator.CONNECTOR_FAILURE_HANDLER_VALUE_IGNORE); - return this; - } - - /** - * Configures a failure handling strategy in case a request to Elasticsearch fails. - * - *

This strategy re-adds requests that have failed due to queue capacity saturation. - */ - public org.apache.flink.table.descriptors.Elasticsearch failureHandlerRetryRejected() { - internalProperties.putString(CONNECTOR_FAILURE_HANDLER, ElasticsearchValidator.CONNECTOR_FAILURE_HANDLER_VALUE_RETRY); - return this; - } - - /** - * Configures a failure handling strategy in case a request to Elasticsearch fails. - * - *

This strategy allows for custom failure handling using a {@link ActionRequestFailureHandler}. - */ - public org.apache.flink.table.descriptors.Elasticsearch failureHandlerCustom(Class failureHandlerClass) { - internalProperties.putString(CONNECTOR_FAILURE_HANDLER, ElasticsearchValidator.CONNECTOR_FAILURE_HANDLER_VALUE_CUSTOM); - internalProperties.putClass(CONNECTOR_FAILURE_HANDLER_CLASS, failureHandlerClass); - return this; - } - - /** - * Disables flushing on checkpoint. When disabled, a sink will not wait for all pending action - * requests to be acknowledged by Elasticsearch on checkpoints. - * - *

Note: If flushing on checkpoint is disabled, a Elasticsearch sink does NOT - * provide any strong guarantees for at-least-once delivery of action requests. - */ - public org.apache.flink.table.descriptors.Elasticsearch disableFlushOnCheckpoint() { - internalProperties.putBoolean(CONNECTOR_FLUSH_ON_CHECKPOINT, false); - return this; - } - - /** - * Configures how to buffer elements before sending them in bulk to the cluster for efficiency. - * - *

Sets the maximum number of actions to buffer for each bulk request. - * - * @param maxActions the maximum number of actions to buffer per bulk request. - */ - public org.apache.flink.table.descriptors.Elasticsearch bulkFlushMaxActions(int maxActions) { - internalProperties.putInt(CONNECTOR_BULK_FLUSH_MAX_ACTIONS, maxActions); - return this; - } - - /** - * Configures how to buffer elements before sending them in bulk to the cluster for efficiency. - * - *

Sets the maximum size of buffered actions per bulk request (using the syntax of {@link MemorySize}). - */ - public org.apache.flink.table.descriptors.Elasticsearch bulkFlushMaxSize(String maxSize) { - internalProperties.putMemorySize(CONNECTOR_BULK_FLUSH_MAX_SIZE, MemorySize.parse(maxSize, MemorySize.MemoryUnit.BYTES)); - return this; - } - - /** - * Configures how to buffer elements before sending them in bulk to the cluster for efficiency. - * - *

Sets the bulk flush interval (in milliseconds). - * - * @param interval bulk flush interval (in milliseconds). - */ - public org.apache.flink.table.descriptors.Elasticsearch bulkFlushInterval(long interval) { - internalProperties.putLong(CONNECTOR_BULK_FLUSH_INTERVAL, interval); - return this; - } - - /** - * Configures how to buffer elements before sending them in bulk to the cluster for efficiency. - * - *

Sets a constant backoff type to use when flushing bulk requests. - */ - public org.apache.flink.table.descriptors.Elasticsearch bulkFlushBackoffConstant() { - internalProperties.putString( - CONNECTOR_BULK_FLUSH_BACKOFF_TYPE, - ElasticsearchValidator.CONNECTOR_BULK_FLUSH_BACKOFF_TYPE_VALUE_CONSTANT); - return this; - } - - /** - * Configures how to buffer elements before sending them in bulk to the cluster for efficiency. - * - *

Sets an exponential backoff type to use when flushing bulk requests. - */ - public org.apache.flink.table.descriptors.Elasticsearch bulkFlushBackoffExponential() { - internalProperties.putString( - CONNECTOR_BULK_FLUSH_BACKOFF_TYPE, - ElasticsearchValidator.CONNECTOR_BULK_FLUSH_BACKOFF_TYPE_VALUE_EXPONENTIAL); - return this; - } - - /** - * Configures how to buffer elements before sending them in bulk to the cluster for efficiency. - * - *

Sets the maximum number of retries for a backoff attempt when flushing bulk requests. - * - *

Make sure to enable backoff by selecting a strategy ({@link #bulkFlushBackoffConstant()} or - * {@link #bulkFlushBackoffExponential()}). - * - * @param maxRetries the maximum number of retries. - */ - public org.apache.flink.table.descriptors.Elasticsearch bulkFlushBackoffMaxRetries(int maxRetries) { - internalProperties.putInt(CONNECTOR_BULK_FLUSH_BACKOFF_MAX_RETRIES, maxRetries); - return this; - } - - /** - * Configures how to buffer elements before sending them in bulk to the cluster for efficiency. - * - *

Sets the amount of delay between each backoff attempt when flushing bulk requests (in milliseconds). - * - *

Make sure to enable backoff by selecting a strategy ({@link #bulkFlushBackoffConstant()} or - * {@link #bulkFlushBackoffExponential()}). - * - * @param delay delay between each backoff attempt (in milliseconds). - */ - public org.apache.flink.table.descriptors.Elasticsearch bulkFlushBackoffDelay(long delay) { - internalProperties.putLong(CONNECTOR_BULK_FLUSH_BACKOFF_DELAY, delay); - return this; - } - - /** - * Sets connection properties to be used during REST communication to Elasticsearch. - * - *

Sets the maximum timeout (in milliseconds) in case of multiple retries of the same request. - * - * @param maxRetryTimeout maximum timeout (in milliseconds) - */ - public org.apache.flink.table.descriptors.Elasticsearch connectionMaxRetryTimeout(int maxRetryTimeout) { - internalProperties.putInt(CONNECTOR_CONNECTION_MAX_RETRY_TIMEOUT, maxRetryTimeout); - return this; - } - - /** - * Sets connection properties to be used during REST communication to Elasticsearch. - * - *

Adds a path prefix to every REST communication. - * - * @param pathPrefix prefix string to be added to every REST communication - */ - public org.apache.flink.table.descriptors.Elasticsearch connectionPathPrefix(String pathPrefix) { - internalProperties.putString(CONNECTOR_CONNECTION_PATH_PREFIX, pathPrefix); - return this; - } - - @Override - protected Map toConnectorProperties() { - final DescriptorProperties properties = new DescriptorProperties(); - properties.putProperties(internalProperties); - - if (hosts.size() > 0) { - properties.putString( - CONNECTOR_HOSTS, - hosts.stream() - .map(Host::toString) - .collect(Collectors.joining(";"))); - } - return properties.asMap(); - } -} diff --git a/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/org/apache/flink/table/descriptors/ElasticsearchValidator.java b/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/org/apache/flink/table/descriptors/ElasticsearchValidator.java deleted file mode 100644 index b8f233182..000000000 --- a/elasticsearch5-xh/elasticsearch5-xh-sink/src/main/java/org/apache/flink/table/descriptors/ElasticsearchValidator.java +++ /dev/null @@ -1,184 +0,0 @@ -/* - * 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.descriptors; - -import org.apache.flink.annotation.Internal; -import org.apache.flink.streaming.connectors.elasticsearch.ElasticsearchUpsertTableSinkBase.Host; -import org.apache.flink.table.api.ValidationException; -import org.apache.flink.util.StringUtils; - -import java.net.MalformedURLException; -import java.net.URL; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.Consumer; - -import static org.apache.flink.table.descriptors.DescriptorProperties.noValidation; - -/** - * The validator for {@link Elasticsearch}. - */ -@Internal -public class ElasticsearchValidator extends ConnectorDescriptorValidator { - - public static final String CONNECTOR_TYPE_VALUE_ELASTICSEARCH = "elasticsearch"; - public static final String CONNECTOR_VERSION_VALUE_6 = "6"; - public static final String CONNECTOR_VERSION_VALUE_7 = "7"; - public static final String CONNECTOR_HOSTS = "connector.hosts"; - public static final String CONNECTOR_HOSTS_HOSTNAME = "hostname"; - public static final String CONNECTOR_HOSTS_PORT = "port"; - public static final String CONNECTOR_HOSTS_PROTOCOL = "protocol"; - public static final String CONNECTOR_INDEX = "connector.index"; - public static final String CONNECTOR_DOCUMENT_TYPE = "connector.document-type"; - public static final String CONNECTOR_KEY_DELIMITER = "connector.key-delimiter"; - public static final String CONNECTOR_KEY_NULL_LITERAL = "connector.key-null-literal"; - public static final String CONNECTOR_FAILURE_HANDLER = "connector.failure-handler"; - public static final String CONNECTOR_FAILURE_HANDLER_VALUE_FAIL = "fail"; - public static final String CONNECTOR_FAILURE_HANDLER_VALUE_IGNORE = "ignore"; - public static final String CONNECTOR_FAILURE_HANDLER_VALUE_RETRY = "retry-rejected"; - public static final String CONNECTOR_FAILURE_HANDLER_VALUE_CUSTOM = "custom"; - public static final String CONNECTOR_FAILURE_HANDLER_CLASS = "connector.failure-handler-class"; - public static final String CONNECTOR_FLUSH_ON_CHECKPOINT = "connector.flush-on-checkpoint"; - public static final String CONNECTOR_BULK_FLUSH_MAX_ACTIONS = "connector.bulk-flush.max-actions"; - public static final String CONNECTOR_BULK_FLUSH_MAX_SIZE = "connector.bulk-flush.max-size"; - public static final String CONNECTOR_BULK_FLUSH_INTERVAL = "connector.bulk-flush.interval"; - public static final String CONNECTOR_BULK_FLUSH_BACKOFF_TYPE = "connector.bulk-flush.backoff.type"; - public static final String CONNECTOR_BULK_FLUSH_BACKOFF_TYPE_VALUE_DISABLED = "disabled"; - public static final String CONNECTOR_BULK_FLUSH_BACKOFF_TYPE_VALUE_CONSTANT = "constant"; - public static final String CONNECTOR_BULK_FLUSH_BACKOFF_TYPE_VALUE_EXPONENTIAL = "exponential"; - public static final String CONNECTOR_BULK_FLUSH_BACKOFF_MAX_RETRIES = "connector.bulk-flush.backoff.max-retries"; - public static final String CONNECTOR_BULK_FLUSH_BACKOFF_DELAY = "connector.bulk-flush.backoff.delay"; - public static final String CONNECTOR_CONNECTION_MAX_RETRY_TIMEOUT = "connector.connection-max-retry-timeout"; - public static final String CONNECTOR_CONNECTION_PATH_PREFIX = "connector.connection-path-prefix"; - - @Override - public void validate(DescriptorProperties properties) { - super.validate(properties); - properties.validateValue(CONNECTOR_TYPE, CONNECTOR_TYPE_VALUE_ELASTICSEARCH, false); - validateVersion(properties); - validateHosts(properties); - validateGeneralProperties(properties); - validateFailureHandler(properties); - validateBulkFlush(properties); - validateConnectionProperties(properties); - } - - private void validateVersion(DescriptorProperties properties) { - properties.validateEnumValues( - CONNECTOR_VERSION, - false, - Arrays.asList(CONNECTOR_VERSION_VALUE_6, CONNECTOR_VERSION_VALUE_7)); - } - - private void validateHosts(DescriptorProperties properties) { - if (properties.containsKey(CONNECTOR_HOSTS)) { - validateAndParseHostsString(properties); - } else { - final Map> hostsValidators = new HashMap<>(); - hostsValidators.put(CONNECTOR_HOSTS_HOSTNAME, (key) -> properties.validateString(key, false, 1)); - hostsValidators.put(CONNECTOR_HOSTS_PORT, (key) -> properties.validateInt(key, false, 0, 65535)); - hostsValidators.put(CONNECTOR_HOSTS_PROTOCOL, (key) -> properties.validateString(key, false, 1)); - - properties.validateFixedIndexedProperties(CONNECTOR_HOSTS, false, hostsValidators); - } - } - - private void validateGeneralProperties(DescriptorProperties properties) { - properties.validateString(CONNECTOR_INDEX, false, 1); - properties.validateString(CONNECTOR_DOCUMENT_TYPE, false, 1); - properties.validateString(CONNECTOR_KEY_DELIMITER, true); - properties.validateString(CONNECTOR_KEY_NULL_LITERAL, true); - } - - private void validateFailureHandler(DescriptorProperties properties) { - final Map> failureHandlerValidators = new HashMap<>(); - failureHandlerValidators.put(CONNECTOR_FAILURE_HANDLER_VALUE_FAIL, noValidation()); - failureHandlerValidators.put(CONNECTOR_FAILURE_HANDLER_VALUE_IGNORE, noValidation()); - failureHandlerValidators.put(CONNECTOR_FAILURE_HANDLER_VALUE_RETRY, noValidation()); - failureHandlerValidators.put(CONNECTOR_FAILURE_HANDLER_VALUE_CUSTOM, - key -> properties.validateString(CONNECTOR_FAILURE_HANDLER_CLASS, false, 1)); - properties.validateEnum(CONNECTOR_FAILURE_HANDLER, true, failureHandlerValidators); - } - - private void validateBulkFlush(DescriptorProperties properties) { - properties.validateBoolean(CONNECTOR_FLUSH_ON_CHECKPOINT, true); - properties.validateInt(CONNECTOR_BULK_FLUSH_MAX_ACTIONS, true, 1); - properties.validateMemorySize(CONNECTOR_BULK_FLUSH_MAX_SIZE, true, 1024 * 1024); // only allow MB precision - properties.validateLong(CONNECTOR_BULK_FLUSH_INTERVAL, true, 0); - properties.validateEnumValues(CONNECTOR_BULK_FLUSH_BACKOFF_TYPE, - true, - Arrays.asList( - CONNECTOR_BULK_FLUSH_BACKOFF_TYPE_VALUE_DISABLED, - CONNECTOR_BULK_FLUSH_BACKOFF_TYPE_VALUE_CONSTANT, - CONNECTOR_BULK_FLUSH_BACKOFF_TYPE_VALUE_EXPONENTIAL)); - properties.validateInt(CONNECTOR_BULK_FLUSH_BACKOFF_MAX_RETRIES, true, 1); - properties.validateLong(CONNECTOR_BULK_FLUSH_BACKOFF_DELAY, true, 0); - } - - private void validateConnectionProperties(DescriptorProperties properties) { - properties.validateInt(CONNECTOR_CONNECTION_MAX_RETRY_TIMEOUT, true, 1); - properties.validateString(CONNECTOR_CONNECTION_PATH_PREFIX, true); - } - - /** - * Parse Hosts String to list. - * - *

Hosts String format was given as following: - * - *

-	 *     connector.hosts = http://host_name:9092;http://host_name:9093
-	 * 
- */ - public static List validateAndParseHostsString(DescriptorProperties descriptorProperties) { - final List hostList = new ArrayList<>(); - - descriptorProperties.validateString(CONNECTOR_HOSTS, false, 1); - final String hostsStr = descriptorProperties.getString(CONNECTOR_HOSTS); - - final String[] hosts = hostsStr.split(";"); - final String validationExceptionMessage = "Properties '" + CONNECTOR_HOSTS + "' format should " + - "follow the format 'http://host_name:port', but is '" + hostsStr + "'."; - - if (hosts.length == 0) { - throw new ValidationException(validationExceptionMessage); - } - for (String host : hosts) { - try { - final URL url = new URL(host); - final String protocol = url.getProtocol(); - final String hostName = url.getHost(); - final int hostPort = url.getPort(); - - if (StringUtils.isNullOrWhitespaceOnly(protocol) || - StringUtils.isNullOrWhitespaceOnly(hostName) || - -1 == hostPort) { - throw new ValidationException(validationExceptionMessage); - } - - hostList.add(new Host(hostName, hostPort, protocol)); - } catch (MalformedURLException e) { - throw new ValidationException(validationExceptionMessage, e); - } - } - return hostList; - } -} diff --git a/elasticsearch5-xh/pom.xml b/elasticsearch5-xh/pom.xml deleted file mode 100644 index c68fc833a..000000000 --- a/elasticsearch5-xh/pom.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - flink.sql - com.dtstack.flink - 1.0-SNAPSHOT - - 4.0.0 - - sql.elasticsearch5-xh - elasticsearch5-xh - pom - - elasticsearch5-xh-sink - - - - - - com.dtstack.flink - sql.core - 1.0-SNAPSHOT - provided - - - - - \ No newline at end of file diff --git a/elasticsearch5/elasticsearch5-sink/pom.xml b/elasticsearch5/elasticsearch5-sink/pom.xml index 5b05638ad..459ec5fad 100644 --- a/elasticsearch5/elasticsearch5-sink/pom.xml +++ b/elasticsearch5/elasticsearch5-sink/pom.xml @@ -13,31 +13,6 @@ elasticsearch-sink - - org.elasticsearch.client - transport - ${elasticsearch.version} - - - - org.elasticsearch.client - x-pack-transport - ${elasticsearch.version} - - - - - org.slf4j - slf4j-log4j12 - 1.6.1 - - - - org.apache.logging.log4j - log4j-to-slf4j - 2.7 - - org.apache.flink flink-connector-elasticsearch5_2.11 @@ -45,9 +20,15 @@ - org.apache.flink - flink-connector-elasticsearch-base_2.11 - ${flink.version} + ch.qos.logback + logback-core + 1.1.7 + + + + ch.qos.logback + logback-classic + 1.1.7 @@ -66,7 +47,7 @@ - + org.apache.logging.log4j:log4j-to-slf4j @@ -97,14 +78,14 @@ - + - + diff --git a/elasticsearch5/elasticsearch5-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/CustomerSinkFunc.java b/elasticsearch5/elasticsearch5-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/CustomerSinkFunc.java index c7f236c89..a95d477de 100644 --- a/elasticsearch5/elasticsearch5-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/CustomerSinkFunc.java +++ b/elasticsearch5/elasticsearch5-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/CustomerSinkFunc.java @@ -20,7 +20,6 @@ package com.dtstack.flink.sql.sink.elasticsearch; -import com.dtstack.flink.sql.util.DateUtil; import org.apache.commons.lang3.StringUtils; import org.apache.flink.api.common.functions.RuntimeContext; import org.apache.flink.api.java.tuple.Tuple2; @@ -33,11 +32,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.sql.Date; -import java.sql.Timestamp; +import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.stream.Collectors; /** * Reason: @@ -50,16 +47,11 @@ public class CustomerSinkFunc implements ElasticsearchSinkFunction { private final Logger logger = LoggerFactory.getLogger(CustomerSinkFunc.class); - private static final String ID_VALUE_SPLIT = "_"; - private String index; private String type; - private List ids; - - // true means generation doc's id by position "1[,1]" - private boolean usePosition; + private List idFieldIndexList; private List fieldNames; @@ -67,13 +59,15 @@ public class CustomerSinkFunc implements ElasticsearchSinkFunction { public transient Counter outRecords; - public CustomerSinkFunc(String index, String type, List fieldNames, List fieldTypes, List ids, boolean usePosition) { + /** 默认分隔符为'_' */ + private char sp = '_'; + + public CustomerSinkFunc(String index, String type, List fieldNames, List fieldTypes, List idFieldIndexes){ this.index = index; this.type = type; this.fieldNames = fieldNames; this.fieldTypes = fieldTypes; - this.ids = ids; - this.usePosition = usePosition; + this.idFieldIndexList = idFieldIndexes; } @Override @@ -100,49 +94,26 @@ public void setOutRecords(Counter outRecords) { private IndexRequest createIndexRequest(Row element) { - Map dataMap = EsUtil.rowToJsonMap(element,fieldNames,fieldTypes); - int length = Math.min(element.getArity(), fieldNames.size()); - for(int i=0; i idFieldList = new ArrayList<>(); + for(int index : idFieldIndexList){ + if(index >= element.getArity()){ continue; } - dataMap.put(fieldNames.get(i), element.getField(i)); - } - String idFieldStr = ""; - if (null != ids) { - if (!usePosition) { - idFieldStr = ids.stream() - .map(filedName -> (String) filedName) - .map(filedName -> dataMap.get(filedName).toString()) - .collect(Collectors.joining(ID_VALUE_SPLIT)); - } else { - // compatible old version of generate doc's id - // index start at 1, - idFieldStr = ids.stream() - .map(index -> (Integer) index) - .filter(index -> index > 0 && index <= element.getArity()) - .map(index -> element.getField( index - 1).toString()) - .collect(Collectors.joining(ID_VALUE_SPLIT)); - } + idFieldList.add(element.getField(index).toString()); } - if (StringUtils.isEmpty(idFieldStr)) { - return Requests.indexRequest() - .index(index) - .type(type) - .source(dataMap); + Map dataMap = EsUtil.rowToJsonMap(element,fieldNames,fieldTypes); + int length = Math.min(element.getArity(), fieldNames.size()); + for(int i=0; i, IStreamSi private String type = ""; - private List ids; - - // true means generation doc's id by position "1[,1]" - private boolean usePosition = false; + private List idIndexList; protected String[] fieldNames; @@ -81,11 +74,7 @@ public class ElasticsearchSink implements RetractStreamTableSink, IStreamSi private TypeInformation[] fieldTypes; - private int parallelism = 1; - - protected String registerTableName; - - private ElasticsearchTableInfo esTableInfo; + private int parallelism = -1; @Override @@ -118,14 +107,6 @@ public TypeInformation[] getFieldTypes() { private RichSinkFunction createEsSinkFunction(){ - // check whether id fields is exists in columns if not use position to generate doc's id - if (!usePosition - && ids != null - && ids.size() != 0) { - List filedNamesLists = Arrays.asList(fieldNames); - Preconditions.checkState(filedNamesLists.containsAll(ids), "elasticsearch6 type of id %s is should be exists in columns %s.", ids, filedNamesLists); - } - CustomerSinkFunc customerSinkFunc = new CustomerSinkFunc(index, type, Arrays.asList(fieldNames), Arrays.asList(columnTypes), ids, usePosition); Map userConfig = new HashMap<>(); userConfig.put("cluster.name", clusterName); @@ -134,7 +115,7 @@ private RichSinkFunction createEsSinkFunction(){ List transports = new ArrayList<>(); for(String address : esAddressList){ - String[] infoArray = StringUtils.split(address, ":"); + String[] infoArray = address.split(":"); int port = 9300; String host = infoArray[0]; if(infoArray.length > 1){ @@ -149,29 +130,22 @@ private RichSinkFunction createEsSinkFunction(){ } } - boolean authMesh = esTableInfo.isAuthMesh(); - if (authMesh) { - String authPassword = esTableInfo.getUserName() + ":" + esTableInfo.getPassword(); - userConfig.put("xpack.security.user", authPassword); - } + CustomerSinkFunc customerSinkFunc = new CustomerSinkFunc(index, type, Arrays.asList(fieldNames), Arrays.asList(columnTypes), idIndexList); - return new MetricElasticsearchSink(userConfig, transports, customerSinkFunc, esTableInfo); + return new MetricElasticsearchSink(userConfig, transports, customerSinkFunc); } @Override public void emitDataStream(DataStream> dataStream) { - consumeDataStream(dataStream); - } - - @Override - public DataStreamSink> consumeDataStream(DataStream> dataStream) { RichSinkFunction richSinkFunction = createEsSinkFunction(); - DataStreamSink streamSink = dataStream.addSink(richSinkFunction).name(registerTableName); + DataStreamSink streamSink = dataStream.addSink(richSinkFunction); if(parallelism > 0){ streamSink.setParallelism(parallelism); } + } - return streamSink; + public void setParallelism(int parallelism) { + this.parallelism = parallelism; } public void setBulkFlushMaxActions(int bulkFlushMaxActions) { @@ -179,32 +153,22 @@ public void setBulkFlushMaxActions(int bulkFlushMaxActions) { } @Override - public ElasticsearchSink genStreamSink(AbstractTargetTableInfo targetTableInfo) { + public ElasticsearchSink genStreamSink(TargetTableInfo targetTableInfo) { ElasticsearchTableInfo elasticsearchTableInfo = (ElasticsearchTableInfo) targetTableInfo; - esTableInfo = elasticsearchTableInfo; clusterName = elasticsearchTableInfo.getClusterName(); String address = elasticsearchTableInfo.getAddress(); - String[] addr = StringUtils.split(address, ","); + String[] addr = address.split(","); esAddressList = Arrays.asList(addr); index = elasticsearchTableInfo.getIndex(); type = elasticsearchTableInfo.getEsType(); String id = elasticsearchTableInfo.getId(); - String[] idField = StringUtils.split(id, ","); - registerTableName = elasticsearchTableInfo.getName(); - parallelism = Objects.isNull(elasticsearchTableInfo.getParallelism()) ? - parallelism : elasticsearchTableInfo.getParallelism(); + String[] idField = id.split(","); + idIndexList = new ArrayList<>(); for(int i = 0; i < idField.length; ++i) { - if (!EsUtil.checkWhetherUsePosition(id)) { - ids = Arrays.stream(org.apache.commons.lang.StringUtils.split(id, ",")).map(String::valueOf).collect(Collectors.toList()); - } else { - //compatible old version of generate doc' id - usePosition = true; - ids = Arrays.stream(org.apache.commons.lang.StringUtils.split(id, ",")).map(Integer::valueOf).collect(Collectors.toList()); - } + idIndexList.add(Integer.valueOf(idField[i])); } - columnTypes = elasticsearchTableInfo.getFieldTypes(); return this; diff --git a/elasticsearch5/elasticsearch5-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/EsUtil.java b/elasticsearch5/elasticsearch5-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/EsUtil.java index d4be3be19..26d7827da 100644 --- a/elasticsearch5/elasticsearch5-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/EsUtil.java +++ b/elasticsearch5/elasticsearch5-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/EsUtil.java @@ -18,13 +18,10 @@ package com.dtstack.flink.sql.sink.elasticsearch; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.math.NumberUtils; +import com.dtstack.flink.sql.util.DtStringUtil; import org.apache.flink.types.Row; import org.apache.flink.util.Preconditions; -import com.dtstack.flink.sql.util.DtStringUtil; - import java.util.HashMap; import java.util.List; import java.util.Map; @@ -64,23 +61,5 @@ public static Map rowToJsonMap(Row row, List fields, Lis return jsonMap; } - /** - * check whether use position to generation doc's id - * eg : |1,2,3 -> true - * |id,name,addr -> false - * @param ids - * @return - */ - public static boolean checkWhetherUsePosition(String ids) { - boolean flag = true; - for( String id : StringUtils.split(ids, ",")) { - if (!NumberUtils.isNumber(id)) { - flag= false; - break; - } - } - return flag; - } - } diff --git a/elasticsearch5/elasticsearch5-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/ExtendES5ApiCallBridge.java b/elasticsearch5/elasticsearch5-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/ExtendES5ApiCallBridge.java deleted file mode 100644 index 14baa5449..000000000 --- a/elasticsearch5/elasticsearch5-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/ExtendES5ApiCallBridge.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.elasticsearch; - -import com.dtstack.flink.sql.sink.elasticsearch.table.ElasticsearchTableInfo; -import org.apache.flink.streaming.connectors.elasticsearch.ElasticsearchApiCallBridge; -import org.apache.flink.streaming.connectors.elasticsearch.ElasticsearchSinkBase; -import org.apache.flink.streaming.connectors.elasticsearch.util.ElasticsearchUtils; -import org.apache.flink.util.IOUtils; -import org.apache.flink.util.Preconditions; -import org.elasticsearch.action.bulk.BackoffPolicy; -import org.elasticsearch.action.bulk.BulkItemResponse; -import org.elasticsearch.action.bulk.BulkProcessor; -import org.elasticsearch.client.transport.TransportClient; -import org.elasticsearch.common.network.NetworkModule; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.transport.TransportAddress; -import org.elasticsearch.common.unit.TimeValue; -import org.elasticsearch.transport.Netty3Plugin; -import org.elasticsearch.transport.client.PreBuiltTransportClient; -import org.elasticsearch.xpack.client.PreBuiltXPackTransportClient; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.annotation.Nullable; -import java.net.InetSocketAddress; -import java.util.List; -import java.util.Map; - -/** - * @date 2019/11/16 - * @author xiuzhu - * @Company: www.dtstack.com - */ - -public class ExtendES5ApiCallBridge implements ElasticsearchApiCallBridge { - private static final long serialVersionUID = -5222683870097809633L; - - private static final Logger LOG = LoggerFactory.getLogger(ExtendES5ApiCallBridge.class); - - private final List transportAddresses; - - protected ElasticsearchTableInfo esTableInfo; - - public ExtendES5ApiCallBridge(List transportAddresses, ElasticsearchTableInfo esTableInfo) { - Preconditions.checkArgument(transportAddresses != null && !transportAddresses.isEmpty()); - this.transportAddresses = transportAddresses; - this.esTableInfo = esTableInfo; - } - - @Override - public TransportClient createClient(Map clientConfig) { - Settings settings = Settings.builder().put(clientConfig) - //.put(NetworkModule.HTTP_TYPE_KEY, Netty3Plugin.NETTY_HTTP_TRANSPORT_NAME) - //.put(NetworkModule.TRANSPORT_TYPE_KEY, Netty3Plugin.NETTY_TRANSPORT_NAME) - .build(); - - TransportClient transportClient; - if (esTableInfo.isAuthMesh()) { - transportClient = new PreBuiltXPackTransportClient(settings); - }else { - transportClient = new PreBuiltTransportClient(settings); - } - for (TransportAddress transport : ElasticsearchUtils.convertInetSocketAddresses(transportAddresses)) { - transportClient.addTransportAddress(transport); - } - - // verify that we actually are connected to a cluster - if (transportClient.connectedNodes().isEmpty()) { - - // close the transportClient here - IOUtils.closeQuietly(transportClient); - - throw new RuntimeException("Elasticsearch client is not connected to any Elasticsearch nodes!"); - } - - if (LOG.isInfoEnabled()) { - LOG.info("Created Elasticsearch TransportClient with connected nodes {}", transportClient.connectedNodes()); - } - - return transportClient; - } - - @Override - public BulkProcessor.Builder createBulkProcessorBuilder(TransportClient client, BulkProcessor.Listener listener) { - return BulkProcessor.builder(client, listener); - } - - @Override - public Throwable extractFailureCauseFromBulkItemResponse(BulkItemResponse bulkItemResponse) { - if (!bulkItemResponse.isFailed()) { - return null; - } else { - return bulkItemResponse.getFailure().getCause(); - } - } - - @Override - public void configureBulkProcessorBackoff( - BulkProcessor.Builder builder, - @Nullable ElasticsearchSinkBase.BulkFlushBackoffPolicy flushBackoffPolicy) { - - BackoffPolicy backoffPolicy; - if (flushBackoffPolicy != null) { - switch (flushBackoffPolicy.getBackoffType()) { - case CONSTANT: - backoffPolicy = BackoffPolicy.constantBackoff( - new TimeValue(flushBackoffPolicy.getDelayMillis()), - flushBackoffPolicy.getMaxRetryCount()); - break; - case EXPONENTIAL: - default: - backoffPolicy = BackoffPolicy.exponentialBackoff( - new TimeValue(flushBackoffPolicy.getDelayMillis()), - flushBackoffPolicy.getMaxRetryCount()); - } - } else { - backoffPolicy = BackoffPolicy.noBackoff(); - } - - builder.setBackoffPolicy(backoffPolicy); - } -} diff --git a/elasticsearch5/elasticsearch5-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/MetricElasticsearchSink.java b/elasticsearch5/elasticsearch5-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/MetricElasticsearchSink.java index fa6d31b0f..709150848 100644 --- a/elasticsearch5/elasticsearch5-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/MetricElasticsearchSink.java +++ b/elasticsearch5/elasticsearch5-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/MetricElasticsearchSink.java @@ -19,15 +19,12 @@ package com.dtstack.flink.sql.sink.elasticsearch; import com.dtstack.flink.sql.metric.MetricConstant; -import com.dtstack.flink.sql.sink.elasticsearch.table.ElasticsearchTableInfo; import org.apache.flink.configuration.Configuration; import org.apache.flink.metrics.Counter; import org.apache.flink.metrics.Meter; import org.apache.flink.metrics.MeterView; import org.apache.flink.streaming.connectors.elasticsearch.ElasticsearchSinkFunction; -import org.apache.flink.streaming.connectors.elasticsearch.util.NoOpFailureHandler; -import java.net.InetSocketAddress; import java.util.List; import java.util.Map; @@ -35,23 +32,16 @@ * @Auther: jiangjunjie * @Date: 2018/11/29 14:15 * @Description: - * */ -public class MetricElasticsearchSink extends org.apache.flink.streaming.connectors.elasticsearch.ElasticsearchSinkBase { +public class MetricElasticsearchSink extends org.apache.flink.streaming.connectors.elasticsearch5.ElasticsearchSink { protected CustomerSinkFunc customerSinkFunc; protected transient Meter outRecordsRate; - protected Map userConfig; - - - public MetricElasticsearchSink(Map userConfig, List transportAddresses, - ElasticsearchSinkFunction elasticsearchSinkFunction, - ElasticsearchTableInfo esTableInfo) { - super(new ExtendES5ApiCallBridge(transportAddresses, esTableInfo), userConfig, elasticsearchSinkFunction, new NoOpFailureHandler()); + public MetricElasticsearchSink(Map userConfig, List transportAddresses, ElasticsearchSinkFunction elasticsearchSinkFunction) { + super(userConfig, transportAddresses, elasticsearchSinkFunction); this.customerSinkFunc = (CustomerSinkFunc) elasticsearchSinkFunction; - this.userConfig = userConfig; } @Override diff --git a/elasticsearch5/elasticsearch5-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/table/ElasticsearchSinkParser.java b/elasticsearch5/elasticsearch5-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/table/ElasticsearchSinkParser.java index 1b1e67e26..dd9a65e3e 100644 --- a/elasticsearch5/elasticsearch5-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/table/ElasticsearchSinkParser.java +++ b/elasticsearch5/elasticsearch5-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/table/ElasticsearchSinkParser.java @@ -21,10 +21,8 @@ package com.dtstack.flink.sql.sink.elasticsearch.table; -import com.dtstack.flink.sql.table.AbstractTableParser; -import com.dtstack.flink.sql.table.AbstractTableInfo; -import com.dtstack.flink.sql.util.MathUtil; - +import com.dtstack.flink.sql.table.AbsTableParser; +import com.dtstack.flink.sql.table.TableInfo; import java.util.Map; /** @@ -32,7 +30,7 @@ * @author sishu.yss * @Company: www.dtstack.com */ -public class ElasticsearchSinkParser extends AbstractTableParser { +public class ElasticsearchSinkParser extends AbsTableParser { private static final String KEY_ES_ADDRESS = "address"; @@ -44,21 +42,13 @@ public class ElasticsearchSinkParser extends AbstractTableParser { private static final String KEY_ES_ID_FIELD_INDEX_LIST = "id"; - private static final String KEY_ES_AUTHMESH = "authMesh"; - - private static final String KEY_ES_USERNAME = "userName"; - - private static final String KEY_ES_PASSWORD = "password"; - - private static final String KEY_ES_PARALLELISM = "parallelism"; - @Override protected boolean fieldNameNeedsUpperCase() { return false; } @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { + public TableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { ElasticsearchTableInfo elasticsearchTableInfo = new ElasticsearchTableInfo(); elasticsearchTableInfo.setName(tableName); parseFieldsInfo(fieldsInfo, elasticsearchTableInfo); @@ -67,15 +57,6 @@ public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map fieldNames = Collections.singletonList("name.pv"); - List fieldTypes = Arrays.asList("varchar", "varchar"); - List idFieldIndexes = Collections.singletonList(1); - Tuple2 tuple2 = new Tuple2<>(); - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - customerSinkFunc = new CustomerSinkFunc(index, type, fieldNames, fieldTypes, idFieldIndexes, true); - customerSinkFunc.setOutRecords(outRecords); - tuple2.setField(true, 0); - Row row = new Row(1); - row.setField(0, 1); - tuple2.setField(row, 1); - } - - //测试CustomerSinkFunc中的process和createIndexRequest方法 - @Test - public void processAndcreateIndexRequestTest() { - customerSinkFunc.process(tuple2, ctx, indexer); - tuple2.setField(false, 0); - customerSinkFunc.process(tuple2, ctx, indexer); - } - -} diff --git a/elasticsearch5/elasticsearch5-sink/src/test/java/com/dtstack/flink/sql/sink/elasticsearch/ElasticsearchSinkTest.java b/elasticsearch5/elasticsearch5-sink/src/test/java/com/dtstack/flink/sql/sink/elasticsearch/ElasticsearchSinkTest.java deleted file mode 100644 index e41916a65..000000000 --- a/elasticsearch5/elasticsearch5-sink/src/test/java/com/dtstack/flink/sql/sink/elasticsearch/ElasticsearchSinkTest.java +++ /dev/null @@ -1,93 +0,0 @@ -package com.dtstack.flink.sql.sink.elasticsearch; - -import com.dtstack.flink.sql.sink.elasticsearch.table.ElasticsearchTableInfo; -import com.dtstack.flink.sql.table.AbstractTableInfo; -import com.dtstack.flink.sql.table.AbstractTableParser; -import com.dtstack.flink.sql.util.MathUtil; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.junit.Before; -import org.junit.Test; -import org.mockito.MockitoAnnotations; -import org.mockito.Spy; - -import java.util.HashMap; -import java.util.Map; - -/** - * Company: www.dtstack.com - * - * @author zhufeng - * @date 2020-06-18 - */ -public class ElasticsearchSinkTest { - ElasticsearchTableInfo elasticsearchTableInfo = new ElasticsearchTableInfo(); - @Spy - ElasticsearchSink elasticsearchSink; - String[] fieldNames; - TypeInformation[] fieldTypes; - - - @Before - public void setUp() { - String tableName = "MyResult"; - String fieldsInfo = "pv varchar, channel varchar"; - Map props = new HashMap<>(); - props.put("cluster", "docker-cluster"); - props.put("password", "abc123"); - props.put("address", "172.16.8.193:9200"); - props.put("parallelism", "1"); - props.put("index", "myresult"); - props.put("updatemode", "append"); - props.put("id", "1"); - props.put("type", "elasticsearch"); - props.put("estype", "elasticsearch"); - props.put("authmesh", "true"); - props.put("username", "elastic"); - AbstractTableParser tableParser = new AbstractTableParser() { - @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) throws Exception { - return null; - } - }; - elasticsearchTableInfo.setName(tableName); - tableParser.parseFieldsInfo(fieldsInfo, elasticsearchTableInfo); - elasticsearchTableInfo.setAddress((String) props.get("address")); - elasticsearchTableInfo.setClusterName((String) props.get("cluster")); - elasticsearchTableInfo.setId((String) props.get("id")); - elasticsearchTableInfo.setIndex((String) props.get("index")); - elasticsearchTableInfo.setEsType((String) props.get("estype")); - String authMeshStr = (String) props.get("authmesh"); - if (authMeshStr != null & "true".equals(authMeshStr)) { - elasticsearchTableInfo.setAuthMesh(MathUtil.getBoolean(authMeshStr)); - elasticsearchTableInfo.setUserName(MathUtil.getString(props.get("username"))); - elasticsearchTableInfo.setPassword(MathUtil.getString(props.get("password"))); - } - MockitoAnnotations.initMocks(this); - } - - @Test - public void genStreamSinkTest() { - elasticsearchSink.genStreamSink(elasticsearchTableInfo); - } - - @Test - public void configureTest() { - elasticsearchSink.configure(fieldNames, fieldTypes); - } - - @Test - public void getFieldNamesTest() { - elasticsearchSink.getFieldNames(); - } - - @Test - public void getFieldTypesTest() { - elasticsearchSink.getFieldTypes(); - } - - @Test - public void setBulkFlushMaxActionsTest() { - elasticsearchSink.setBulkFlushMaxActions(1); - } - -} diff --git a/elasticsearch5/elasticsearch5-sink/src/test/java/com/dtstack/flink/sql/sink/elasticsearch/EsUtilTest.java b/elasticsearch5/elasticsearch5-sink/src/test/java/com/dtstack/flink/sql/sink/elasticsearch/EsUtilTest.java deleted file mode 100644 index 8ededee02..000000000 --- a/elasticsearch5/elasticsearch5-sink/src/test/java/com/dtstack/flink/sql/sink/elasticsearch/EsUtilTest.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.dtstack.flink.sql.sink.elasticsearch; - -import org.apache.flink.types.Row; -import org.junit.Assert; -import org.junit.Test; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - - -/** - * Company: www.dtstack.com - * - * @author zhufeng - * @date 2020-06-19 - */ - -public class EsUtilTest { - List fieldNames = Collections.singletonList("name.pv"); - List fieldTypes = Arrays.asList("varchar", "varchar"); - Row row = new Row(1); - - @Test - public void rowToJsonMapTest() { - boolean test = false; - if (EsUtil.rowToJsonMap(row, fieldNames, fieldTypes).toString().equals("{name={}}")) { - test = true; - } - Assert.assertTrue(test); - - } - -} diff --git a/elasticsearch5/elasticsearch5-sink/src/test/java/com/dtstack/flink/sql/sink/elasticsearch/ExtendES5ApiCallBridgeTest.java b/elasticsearch5/elasticsearch5-sink/src/test/java/com/dtstack/flink/sql/sink/elasticsearch/ExtendES5ApiCallBridgeTest.java deleted file mode 100644 index 1211e4b1e..000000000 --- a/elasticsearch5/elasticsearch5-sink/src/test/java/com/dtstack/flink/sql/sink/elasticsearch/ExtendES5ApiCallBridgeTest.java +++ /dev/null @@ -1,105 +0,0 @@ -package com.dtstack.flink.sql.sink.elasticsearch; - -import com.dtstack.flink.sql.sink.elasticsearch.table.ElasticsearchTableInfo; -import com.dtstack.flink.sql.table.AbstractTableInfo; -import com.dtstack.flink.sql.table.AbstractTableParser; -import com.dtstack.flink.sql.util.MathUtil; -import org.apache.flink.streaming.connectors.elasticsearch.ElasticsearchSinkBase; -import org.elasticsearch.action.bulk.BulkItemResponse; -import org.elasticsearch.action.bulk.BulkProcessor; -import org.elasticsearch.client.transport.TransportClient; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.net.InetSocketAddress; -import java.util.*; - -import static org.apache.flink.streaming.connectors.elasticsearch.ElasticsearchSinkBase.FlushBackoffType.CONSTANT; - -/** - * Company: www.dtstack.com - * - * @author zhufeng - * @date 2020-06-19 - */ -public class ExtendES5ApiCallBridgeTest { - List addresses = Collections.singletonList(new InetSocketAddress("172.16.8.193", 9200)); - Map clientConfig = new HashMap<>(); - ExtendES5ApiCallBridge callBridge; - @Mock - BulkProcessor.Builder builder; - @Mock - BulkItemResponse bulkItemResponse; - @Mock - TransportClient client; - @Mock - BulkProcessor.Listener listener; - ElasticsearchSinkBase.BulkFlushBackoffPolicy flushBackoffPolicy = new ElasticsearchSinkBase.BulkFlushBackoffPolicy(); - - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - String tableName = "MyResult"; - String fieldsInfo = "pv varchar, channel varchar"; - Map props = new HashMap<>(); - props.put("cluster", "docker-cluster"); - props.put("password", "abc123"); - props.put("address", "172.16.8.193:9200"); - props.put("parallelism", "1"); - props.put("index", "myresult"); - props.put("updatemode", "append"); - props.put("id", "1"); - props.put("type", "elasticsearch"); - props.put("estype", "elasticsearch"); - props.put("authmesh", "true"); - props.put("username", "elastic"); - AbstractTableParser tableParser = new AbstractTableParser() { - @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) throws Exception { - return null; - } - }; - ElasticsearchTableInfo elasticsearchTableInfo = new ElasticsearchTableInfo(); - elasticsearchTableInfo.setName(tableName); - tableParser.parseFieldsInfo(fieldsInfo, elasticsearchTableInfo); - elasticsearchTableInfo.setAddress((String) props.get("address")); - elasticsearchTableInfo.setClusterName((String) props.get("cluster")); - elasticsearchTableInfo.setId((String) props.get("id")); - elasticsearchTableInfo.setIndex((String) props.get("index")); - elasticsearchTableInfo.setEsType((String) props.get("estype")); - String authMeshStr = (String) props.get("authmesh"); - if (authMeshStr != null & "true".equals(authMeshStr)) { - elasticsearchTableInfo.setAuthMesh(MathUtil.getBoolean(authMeshStr)); - elasticsearchTableInfo.setUserName(MathUtil.getString(props.get("username"))); - elasticsearchTableInfo.setPassword(MathUtil.getString(props.get("password"))); - } - callBridge = new ExtendES5ApiCallBridge(addresses, elasticsearchTableInfo); - } - - //暂时没有ES环境 - public void createClientTest() { - clientConfig.put("cluster.name", "docker-cluster"); - clientConfig.put("xpack.security.user", "elastic:abc123"); - callBridge.createClient(clientConfig); - } - - @Test - public void configureBulkProcessorBackoffTest() { - callBridge.configureBulkProcessorBackoff(builder, flushBackoffPolicy); - flushBackoffPolicy.setBackoffType(CONSTANT); - callBridge.configureBulkProcessorBackoff(builder, flushBackoffPolicy); - } - - @Test - public void extractFailureCauseFromBulkItemResponseTest() { - callBridge.extractFailureCauseFromBulkItemResponse(bulkItemResponse); - } - - @Test - public void createBulkProcessorBuilderTest() { - callBridge.createBulkProcessorBuilder(client, listener); - } -} diff --git a/elasticsearch5/elasticsearch5-sink/src/test/java/com/dtstack/flink/sql/sink/elasticsearch/MetricElasticsearchSinkTest.java b/elasticsearch5/elasticsearch5-sink/src/test/java/com/dtstack/flink/sql/sink/elasticsearch/MetricElasticsearchSinkTest.java deleted file mode 100644 index 9a587720a..000000000 --- a/elasticsearch5/elasticsearch5-sink/src/test/java/com/dtstack/flink/sql/sink/elasticsearch/MetricElasticsearchSinkTest.java +++ /dev/null @@ -1,84 +0,0 @@ -package com.dtstack.flink.sql.sink.elasticsearch; - -import com.dtstack.flink.sql.sink.elasticsearch.table.ElasticsearchTableInfo; -import com.dtstack.flink.sql.table.AbstractTableInfo; -import com.dtstack.flink.sql.table.AbstractTableParser; -import com.dtstack.flink.sql.util.MathUtil; -import org.apache.flink.streaming.connectors.elasticsearch.ElasticsearchSinkBase; -import org.apache.flink.streaming.connectors.elasticsearch.ElasticsearchSinkFunction; -import org.apache.http.HttpHost; -import org.junit.Before; -import org.junit.Test; -import org.mockito.MockitoAnnotations; - -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static org.mockito.Mockito.mock; - -/** - * Company: www.dtstack.com - * - * @author zhufeng - * @date 2020-06-19 - */ -public class MetricElasticsearchSinkTest { - List addresses = Collections.singletonList(new HttpHost("172.16.8.193", 9200)); - ElasticsearchSinkBase.BulkFlushBackoffPolicy flushBackoffPolicy = new ElasticsearchSinkBase.BulkFlushBackoffPolicy(); - Map userConfig = new HashMap(); - MetricElasticsearchSink sink; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - String tableName = "MyResult"; - String fieldsInfo = "pv varchar, channel varchar"; - Map props = new HashMap<>(); - props.put("cluster", "docker-cluster"); - props.put("password", "abc123"); - props.put("address", "172.16.8.193:9200"); - props.put("parallelism", "1"); - props.put("index", "myresult"); - props.put("updatemode", "append"); - props.put("id", "1"); - props.put("type", "elasticsearch"); - props.put("estype", "elasticsearch"); - props.put("authmesh", "true"); - props.put("username", "elastic"); - AbstractTableParser tableParser = new AbstractTableParser() { - @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) throws Exception { - return null; - } - }; - ElasticsearchTableInfo elasticsearchTableInfo = new ElasticsearchTableInfo(); - elasticsearchTableInfo.setName(tableName); - tableParser.parseFieldsInfo(fieldsInfo, elasticsearchTableInfo); - elasticsearchTableInfo.setAddress((String) props.get("address")); - elasticsearchTableInfo.setClusterName((String) props.get("cluster")); - elasticsearchTableInfo.setId((String) props.get("id")); - elasticsearchTableInfo.setIndex((String) props.get("index")); - elasticsearchTableInfo.setEsType((String) props.get("estype")); - String authMeshStr = (String) props.get("authmesh"); - if (authMeshStr != null & "true".equals(authMeshStr)) { - elasticsearchTableInfo.setAuthMesh(MathUtil.getBoolean(authMeshStr)); - elasticsearchTableInfo.setUserName(MathUtil.getString(props.get("username"))); - elasticsearchTableInfo.setPassword(MathUtil.getString(props.get("password"))); - } - ElasticsearchSinkFunction elasticsearchSinkFunction = mock(ElasticsearchSinkFunction.class); - try { - sink = new MetricElasticsearchSink(userConfig, addresses, elasticsearchSinkFunction, elasticsearchTableInfo); - } catch (Exception ignored) { - } - - } - - @Test - public void Test() { - - } -} - - diff --git a/elasticsearch5/elasticsearch5-sink/src/test/java/com/dtstack/flink/sql/sink/elasticsearch/table/ElasticsearchSinkParserTest.java b/elasticsearch5/elasticsearch5-sink/src/test/java/com/dtstack/flink/sql/sink/elasticsearch/table/ElasticsearchSinkParserTest.java deleted file mode 100644 index 5a857ceb0..000000000 --- a/elasticsearch5/elasticsearch5-sink/src/test/java/com/dtstack/flink/sql/sink/elasticsearch/table/ElasticsearchSinkParserTest.java +++ /dev/null @@ -1,131 +0,0 @@ -package com.dtstack.flink.sql.sink.elasticsearch.table; - -import com.dtstack.flink.sql.table.AbstractTableInfo; -import com.dtstack.flink.sql.table.AbstractTableParser; -import com.dtstack.flink.sql.util.MathUtil; -import org.junit.Before; -import org.junit.Test; -import org.mockito.MockitoAnnotations; -import org.mockito.Spy; - -import java.beans.Introspector; -import java.beans.PropertyDescriptor; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static org.junit.Assert.assertFalse; - -/** - * Company: www.dtstack.com - * - * @author zhufeng - * @date 2020-06-17 - */ - -public class ElasticsearchSinkParserTest { - @Spy - ElasticsearchSinkParser elasticsearchSinkParser; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - } - - //ElasticsearchSinkParser中的fieldNameNeedsUpperCase方法 -// @Test - public void fieldNameNeedsUpperCaseTest() { - assertFalse(elasticsearchSinkParser.fieldNameNeedsUpperCase()); - } - - - //getTableInfo方法,得到输入的表信息 -// @Test - public void getTableInfoTest() { - String tableName = "MyResult"; - String fieldsInfo = "pv varchar, channel varchar"; - Map props = new HashMap<>(); - props.put("cluster", "docker-cluster"); - props.put("password", "abc123"); - props.put("address", "172.16.8.193:9200"); - props.put("parallelism", "1"); - props.put("index", "myresult"); - props.put("updatemode", "append"); - props.put("id", "1"); - props.put("type", "elasticsearch"); - props.put("estype", "elasticsearch"); - props.put("authmesh", "true"); - props.put("username", "elastic"); - AbstractTableParser tableParser = new AbstractTableParser() { - @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) throws Exception { - return null; - } - }; - ElasticsearchTableInfo elasticsearchTableInfo = new ElasticsearchTableInfo(); - elasticsearchTableInfo.setName(tableName); - tableParser.parseFieldsInfo(fieldsInfo, elasticsearchTableInfo); - elasticsearchTableInfo.setAddress((String) props.get("address")); - elasticsearchTableInfo.setClusterName((String) props.get("cluster")); - elasticsearchTableInfo.setId((String) props.get("id")); - elasticsearchTableInfo.setIndex((String) props.get("index")); - elasticsearchTableInfo.setEsType((String) props.get("estype")); - String authMeshStr = (String) props.get("authmesh"); - if (authMeshStr != null & "true".equals(authMeshStr)) { - elasticsearchTableInfo.setAuthMesh(MathUtil.getBoolean(authMeshStr)); - elasticsearchTableInfo.setUserName(MathUtil.getString(props.get("username"))); - elasticsearchTableInfo.setPassword(MathUtil.getString(props.get("password"))); - } - String[] ignoreArr = {"fieldClasses", "fieldTypes", "fields"}; - assertTrue(compareFields(elasticsearchTableInfo, elasticsearchSinkParser.getTableInfo(tableName, fieldsInfo, props), ignoreArr)); - } - - private void assertTrue(Boolean compareFields) { - } - - //比较两个对象的值是不是相同 - public static Boolean compareFields(Object obj1, Object obj2, String[] ignoreArr) { - try { - boolean checkIsSame = true; - List ignoreList = null; - if (ignoreArr != null && ignoreArr.length > 0) { - // array转化为list - ignoreList = Arrays.asList(ignoreArr); - } - if (obj1.getClass() == obj2.getClass()) {// 只有两个对象都是同一类型的才有可比性 - Class clazz = obj1.getClass(); - // 获取object的属性描述 - PropertyDescriptor[] pds = Introspector.getBeanInfo(clazz, Object.class).getPropertyDescriptors(); - for (PropertyDescriptor pd : pds) {// 这里就是所有的属性了 - String name = pd.getName();// 属性名 - if (ignoreList != null && ignoreList.contains(name)) {// 如果当前属性选择忽略比较,跳到下一次循环 - continue; - } - Method readMethod = pd.getReadMethod();// get方法 - // 在obj1上调用get方法等同于获得obj1的属性值 - Object o1 = readMethod.invoke(obj1); - // 在obj2上调用get方法等同于获得obj2的属性值 - Object o2 = readMethod.invoke(obj2); - if (o1 == null && o2 == null) { - continue; - } else if (o1 == null) { - checkIsSame = false; - continue; - } - if (!o1.equals(o2)) {// 比较这两个值是否相等,不等就可以放入map了 - checkIsSame = false; - } - } - } - return checkIsSame; - } catch (Exception e) { - e.printStackTrace(); - return null; - } - - } - - -} diff --git a/elasticsearch5/elasticsearch5-sink/src/test/java/com/dtstack/flink/sql/sink/elasticsearch/table/ElasticsearchTableInfoTest.java b/elasticsearch5/elasticsearch5-sink/src/test/java/com/dtstack/flink/sql/sink/elasticsearch/table/ElasticsearchTableInfoTest.java deleted file mode 100644 index a731ecbe8..000000000 --- a/elasticsearch5/elasticsearch5-sink/src/test/java/com/dtstack/flink/sql/sink/elasticsearch/table/ElasticsearchTableInfoTest.java +++ /dev/null @@ -1,106 +0,0 @@ -package com.dtstack.flink.sql.sink.elasticsearch.table; - - -import org.junit.Before; -import org.junit.Test; -import org.mockito.MockitoAnnotations; -import org.mockito.Spy; - -import java.beans.IntrospectionException; -import java.beans.PropertyDescriptor; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -import static org.hamcrest.CoreMatchers.containsString; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import static org.junit.Assert.assertThat; - -/** - * Company: www.dtstack.com - * - * @author zhufeng - * @date 2020-06-17 - */ -public class ElasticsearchTableInfoTest { - - @Spy - ElasticsearchTableInfo tableInfo; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - } - - //通过反射去遍历ElasticsearchTable中所有的get set 方法 - @Test - public void getAndSetTest() throws InvocationTargetException, IntrospectionException, - InstantiationException, IllegalAccessException { - this.testGetAndSet(); - } - - //check()方法,通过捕捉特定的异常来断言 - @Test - public void checkTest() { - tableInfo.setAddress("address"); - tableInfo.setIndex("index"); - tableInfo.setEsType("estype"); - tableInfo.setClusterName("clustername"); - try { - tableInfo.check(); - } catch (NullPointerException e) { - assertThat(e.getMessage(), containsString("is required")); - } - - try { - tableInfo.setId("d"); - tableInfo.check(); - fail("id must be a numeric type"); - } catch (IllegalArgumentException e) { - assertThat(e.getMessage(), containsString("id must be a numeric type")); - } - tableInfo.setId("1"); - try { - tableInfo.setAuthMesh(true); - tableInfo.check(); - } catch (NullPointerException e) { - assertThat(e.getMessage(), containsString("is required")); - } - tableInfo.setUserName("name"); - tableInfo.setPassword("password"); - assertTrue(tableInfo.check()); - } - - - /** - * model的get和set方法 - * 1.子类返回对应的类型 - * 2.通过反射创建类的实例 - * 3.获取该类所有属性字段,遍历获取每个字段对应的get、set方法,并执行 - */ - private void testGetAndSet() throws IllegalAccessException, InstantiationException, IntrospectionException, - InvocationTargetException { - ElasticsearchTableInfo t = new ElasticsearchTableInfo(); - Class modelClass = t.getClass(); - Object obj = modelClass.newInstance(); - Field[] fields = modelClass.getDeclaredFields(); - for (Field f : fields) { - if (!f.getName().equals("CURR_TYPE")) { - if (f.getName().equals("aLike") - || f.isSynthetic()) { - continue; - } - - PropertyDescriptor pd = new PropertyDescriptor(f.getName(), modelClass); - Method get = pd.getReadMethod(); - Method set = pd.getWriteMethod(); - set.invoke(obj, get.invoke(obj)); - } - } - } - - -} - - diff --git a/elasticsearch5/pom.xml b/elasticsearch5/pom.xml index 1c6cd758b..45cc6c92d 100644 --- a/elasticsearch5/pom.xml +++ b/elasticsearch5/pom.xml @@ -11,22 +11,24 @@ sql.elasticsearch5 pom - - - 5.3.3 - - elasticsearch5-sink - - - com.dtstack.flink - sql.core - 1.0-SNAPSHOT - provided - + + + junit + junit + 3.8.1 + test + + + + com.dtstack.flink + sql.core + 1.0-SNAPSHOT + provided + - + \ No newline at end of file diff --git a/elasticsearch6/elasticsearch6-side/elasticsearch6-all-side/pom.xml b/elasticsearch6/elasticsearch6-side/elasticsearch6-all-side/pom.xml deleted file mode 100644 index 7d68e1f95..000000000 --- a/elasticsearch6/elasticsearch6-side/elasticsearch6-all-side/pom.xml +++ /dev/null @@ -1,108 +0,0 @@ - - - - sql.side.elasticsearch6 - com.dtstack.flink - 1.0-SNAPSHOT - - 4.0.0 - - sql.side.all.elasticsearch6 - elasticsearch6-all-side - jar - - - 1.0-SNAPSHOT - - - - - - org.elasticsearch.client - elasticsearch-rest-high-level-client - ${elasticsearch.version} - - - - com.dtstack.flink - sql.side.elasticsearch6.core - ${sql.side.elasticsearch6.core.version} - - - - junit - junit - 4.12 - test - - - - - - - - org.apache.maven.plugins - maven-shade-plugin - 1.4 - - - package - - shade - - - false - - - - - - - - *:* - - META-INF/*.SF - META-INF/*.DSA - META-INF/*.RSA - - - - - - - - - - maven-antrun-plugin - 1.2 - - - copy-resources - - package - - run - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/elasticsearch6/elasticsearch6-side/elasticsearch6-all-side/src/main/java/com/dtstack/flink/sql/side/elasticsearch6/Elasticsearch6AllReqRow.java b/elasticsearch6/elasticsearch6-side/elasticsearch6-all-side/src/main/java/com/dtstack/flink/sql/side/elasticsearch6/Elasticsearch6AllReqRow.java deleted file mode 100644 index 5462f2e07..000000000 --- a/elasticsearch6/elasticsearch6-side/elasticsearch6-all-side/src/main/java/com/dtstack/flink/sql/side/elasticsearch6/Elasticsearch6AllReqRow.java +++ /dev/null @@ -1,284 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.elasticsearch6; - -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.BaseAllReqRow; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.elasticsearch6.table.Elasticsearch6SideTableInfo; -import com.dtstack.flink.sql.side.elasticsearch6.util.Es6Util; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.table.dataformat.BaseRow; -import org.apache.flink.table.dataformat.GenericRow; -import org.apache.flink.table.typeutils.TimeIndicatorTypeInfo; -import org.apache.flink.util.Collector; -import org.elasticsearch.action.search.SearchRequest; -import org.elasticsearch.action.search.SearchResponse; -import org.elasticsearch.client.RequestOptions; -import org.elasticsearch.client.RestHighLevelClient; -import org.elasticsearch.index.query.BoolQueryBuilder; -import org.elasticsearch.search.SearchHit; -import org.elasticsearch.search.builder.SearchSourceBuilder; -import org.elasticsearch.search.sort.SortOrder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.io.Serializable; -import java.sql.Timestamp; -import java.util.Calendar; -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicReference; - -/** - * @author yinxi - * @date 2020/1/13 - 1:00 - */ -public class Elasticsearch6AllReqRow extends BaseAllReqRow implements Serializable { - - private static final Logger LOG = LoggerFactory.getLogger(Elasticsearch6AllReqRow.class); - - private static final int CONN_RETRY_NUM = 3; - private AtomicReference>>> cacheRef = new AtomicReference<>(); - private transient RestHighLevelClient rhlClient; - private SearchRequest searchRequest; - private BoolQueryBuilder boolQueryBuilder; - - public Elasticsearch6AllReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { - super(new Elasticsearch6AllSideInfo(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo)); - } - - @Override - public void flatMap(BaseRow value, Collector out) throws Exception { - GenericRow genericRow = (GenericRow) value; - List inputParams = Lists.newArrayList(); - for (Integer conValIndex : sideInfo.getEqualValIndex()) { - Object equalObj = genericRow.getField(conValIndex); - if (equalObj == null) { - sendOutputRow(value, null, out); - return; - } - - inputParams.add(equalObj); - } - - String key = buildKey(inputParams); - List> cacheList = cacheRef.get().get(key); - if (CollectionUtils.isEmpty(cacheList)) { - sendOutputRow(value, null, out); - return; - } - - for (Map one : cacheList) { - sendOutputRow(value, one, out); - } - } - - @Override - public BaseRow fillData(BaseRow input, Object sideInput) { - GenericRow genericRow = (GenericRow) input; - Map cacheInfo = (Map) sideInput; - GenericRow row = new GenericRow(sideInfo.getOutFieldInfoList().size()); - row.setHeader(input.getHeader()); - for (Map.Entry entry : sideInfo.getInFieldIndex().entrySet()) { - Object obj = genericRow.getField(entry.getValue()); - boolean isTimeIndicatorTypeInfo = TimeIndicatorTypeInfo.class.isAssignableFrom(sideInfo.getRowTypeInfo().getTypeAt(entry.getValue()).getClass()); - - //Type information for indicating event or processing time. However, it behaves like a regular SQL timestamp but is serialized as Long. - if (obj instanceof Timestamp && isTimeIndicatorTypeInfo) { - //去除上一层OutputRowtimeProcessFunction 调用时区导致的影响 - obj = ((Timestamp) obj).getTime() + (long)LOCAL_TZ.getOffset(((Timestamp) obj).getTime()); - } - - row.setField(entry.getKey(), obj); - } - - for (Map.Entry entry : sideInfo.getSideFieldNameIndex().entrySet()) { - if (cacheInfo == null) { - row.setField(entry.getKey(), null); - } else { - row.setField(entry.getKey(), cacheInfo.get(entry.getValue())); - } - } - - return row; - } - - private String buildKey(List equalValList) { - StringBuilder sb = new StringBuilder(""); - for (Object equalVal : equalValList) { - sb.append(equalVal).append("_"); - } - - return sb.toString(); - } - - private String buildKey(Map val, List equalFieldList) { - StringBuilder sb = new StringBuilder(""); - for (String equalField : equalFieldList) { - sb.append(val.get(equalField)).append("_"); - } - - return sb.toString(); - } - - @Override - protected void initCache() { - Map>> newCache = Maps.newConcurrentMap(); - cacheRef.set(newCache); - try { - // create search request and build where cause - searchRequest = Es6Util.setSearchRequest(sideInfo); - boolQueryBuilder = Es6Util.setPredicateclause(sideInfo); - loadData(newCache); - } catch (Exception e) { - LOG.error("", e); - throw new RuntimeException(e); - } - } - - @Override - protected void reloadCache() { - //reload cacheRef and replace to old cacheRef - Map>> newCache = Maps.newConcurrentMap(); - try { - loadData(newCache); - } catch (Exception e) { - LOG.error("", e); - throw new RuntimeException(e); - } - - cacheRef.set(newCache); - LOG.info("----- elasticsearch6 all cacheRef reload end:{}", Calendar.getInstance()); - } - - private void loadData(Map>> tmpCache) throws IOException { - Elasticsearch6SideTableInfo tableInfo = (Elasticsearch6SideTableInfo) sideInfo.getSideTableInfo(); - - try { - for (int i = 0; i < CONN_RETRY_NUM; i++) { - try { - rhlClient = Es6Util.getClient(tableInfo.getAddress(), tableInfo.isAuthMesh(), tableInfo.getUserName(), tableInfo.getPassword()); - break; - } catch (Exception e) { - if (i == CONN_RETRY_NUM - 1) { - throw new RuntimeException("", e); - } - - try { - String connInfo = "url: " + tableInfo.getAddress() + "; userName: " + tableInfo.getUserName() + ", pwd:" + tableInfo.getPassword(); - LOG.warn("get conn fail, wait for 5 sec and try again, connInfo:" + connInfo); - Thread.sleep(LOAD_DATA_ERROR_SLEEP_TIME); - } catch (InterruptedException e1) { - LOG.error("", e1); - } - } - - } - SearchSourceBuilder searchSourceBuilder = initConfiguration(boolQueryBuilder); - searchData(searchSourceBuilder, tmpCache); - - } catch (Exception e) { - LOG.error("", e); - throw new RuntimeException(e); - } finally { - - if (rhlClient != null) { - rhlClient.close(); - } - } - } - - // initialize searchSourceBuilder - private SearchSourceBuilder initConfiguration(BoolQueryBuilder boolQueryBuilder){ - SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); - if (boolQueryBuilder != null) { - searchSourceBuilder.query(boolQueryBuilder); - } - - searchSourceBuilder.size(getFetchSize()); - searchSourceBuilder.sort("_id", SortOrder.DESC); - - // fields included in the source data - String[] sideFieldNames = StringUtils.split(sideInfo.getSideSelectFields().trim(), ","); - searchSourceBuilder.fetchSource(sideFieldNames, null); - return searchSourceBuilder; - } - - - private void searchData(SearchSourceBuilder searchSourceBuilder, Map>> tmpCache) { - - Object[] searchAfterParameter = null; - SearchResponse searchResponse = null; - SearchHit[] searchHits = null; - - while (true) { - try { - if (searchAfterParameter != null) { - // set search mark - searchSourceBuilder.searchAfter(searchAfterParameter); - } - - searchRequest.source(searchSourceBuilder); - searchResponse = rhlClient.search(searchRequest, RequestOptions.DEFAULT); - searchHits = searchResponse.getHits().getHits(); - loadToCache(searchHits, tmpCache); - - if (searchHits.length < getFetchSize()) { - break; - } - - searchAfterParameter = searchHits[searchHits.length - 1].getSortValues(); - } catch (IOException e) { - LOG.error("Query failed!", e); - } - } - } - - // data load to cache - private void loadToCache(SearchHit[] searchHits, Map>> tmpCache) { - String[] sideFieldNames = StringUtils.split(sideInfo.getSideSelectFields().trim(), ","); - String[] sideFieldTypes = sideInfo.getSideTableInfo().getFieldTypes(); - - for (SearchHit searchHit : searchHits) { - Map oneRow = Maps.newHashMap(); - for (String fieldName : sideFieldNames) { - Object object = searchHit.getSourceAsMap().get(fieldName.trim()); - int fieldIndex = sideInfo.getSideTableInfo().getFieldList().indexOf(fieldName.trim()); - object = Es6Util.getTarget(object, sideFieldTypes[fieldIndex]); - oneRow.put(fieldName.trim(), object); - } - - String cacheKey = buildKey(oneRow, sideInfo.getEqualFieldList()); - List> list = tmpCache.computeIfAbsent(cacheKey, key -> Lists.newArrayList()); - list.add(oneRow); - - } - } - - public int getFetchSize() { - return 1000; - } -} diff --git a/elasticsearch6/elasticsearch6-side/elasticsearch6-all-side/src/main/java/com/dtstack/flink/sql/side/elasticsearch6/Elasticsearch6AllSideInfo.java b/elasticsearch6/elasticsearch6-side/elasticsearch6-all-side/src/main/java/com/dtstack/flink/sql/side/elasticsearch6/Elasticsearch6AllSideInfo.java deleted file mode 100644 index d353a583d..000000000 --- a/elasticsearch6/elasticsearch6-side/elasticsearch6-all-side/src/main/java/com/dtstack/flink/sql/side/elasticsearch6/Elasticsearch6AllSideInfo.java +++ /dev/null @@ -1,104 +0,0 @@ -/** - * 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 com.dtstack.flink.sql.side.elasticsearch6; - -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.BaseSideInfo; -import org.apache.flink.api.java.typeutils.RowTypeInfo; - -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; - -import com.dtstack.flink.sql.util.ParseUtils; -import com.google.common.collect.Lists; -import org.apache.calcite.sql.SqlNode; -import org.apache.commons.collections.CollectionUtils; - -import java.util.List; - -/** - * @author yinxi - * @date 2020/1/13 - 1:01 - */ -public class Elasticsearch6AllSideInfo extends BaseSideInfo { - - - public Elasticsearch6AllSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { - super(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); - } - - @Override - public void buildEqualInfo(JoinInfo joinInfo, AbstractSideTableInfo sideTableInfo) { - - } - - - @Override - public void parseSelectFields(JoinInfo joinInfo) { - String sideTableName = joinInfo.getSideTableName(); - String nonSideTableName = joinInfo.getNonSideTable(); - List fields = Lists.newArrayList(); - - int sideIndex = 0; - for (int i = 0; i < outFieldInfoList.size(); i++) { - FieldInfo fieldInfo = outFieldInfoList.get(i); - if (fieldInfo.getTable().equalsIgnoreCase(sideTableName)) { - fields.add(fieldInfo.getFieldName()); - sideFieldIndex.put(i, sideIndex); - sideFieldNameIndex.put(i, fieldInfo.getFieldName()); - sideIndex++; - } else if (fieldInfo.getTable().equalsIgnoreCase(nonSideTableName)) { - int nonSideIndex = rowTypeInfo.getFieldIndex(fieldInfo.getFieldName()); - inFieldIndex.put(i, nonSideIndex); - } else { - throw new RuntimeException("unknown table " + fieldInfo.getTable()); - } - } - - if (fields.size() == 0) { - throw new RuntimeException("select non field from table " + sideTableName); - } - - //add join on condition field to select fields - SqlNode conditionNode = joinInfo.getCondition(); - - List sqlNodeList = Lists.newArrayList(); - - ParseUtils.parseAnd(conditionNode, sqlNodeList); - - for (SqlNode sqlNode : sqlNodeList) { - dealOneEqualCon(sqlNode, sideTableName); - } - - if (CollectionUtils.isEmpty(equalFieldList)) { - throw new RuntimeException("no join condition found after table " + joinInfo.getLeftTableName()); - } - - for (String equalField : equalFieldList) { - if (fields.contains(equalField)) { - continue; - } - - fields.add(equalField); - } - - sideSelectFields = String.join(",", fields); - } - -} diff --git a/elasticsearch6/elasticsearch6-side/elasticsearch6-all-side/src/test/java/com/dtstack/flink/sql/side/elasticsearch6/Elasticsearch6AllReqRowTest.java b/elasticsearch6/elasticsearch6-side/elasticsearch6-all-side/src/test/java/com/dtstack/flink/sql/side/elasticsearch6/Elasticsearch6AllReqRowTest.java deleted file mode 100644 index abebad5ab..000000000 --- a/elasticsearch6/elasticsearch6-side/elasticsearch6-all-side/src/test/java/com/dtstack/flink/sql/side/elasticsearch6/Elasticsearch6AllReqRowTest.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.dtstack.flink.sql.side.elasticsearch6; - - -import org.apache.flink.table.dataformat.BaseRow; -import org.apache.flink.types.Row; -import org.apache.flink.util.Collector; -import org.junit.Test; - -import static org.mockito.Mockito.mock; - -/** - * Company: www.dtstack.com - * - * @author zhufeng - * @date 2020-07-03 - */ -public class Elasticsearch6AllReqRowTest { - Elasticsearch6AllReqRow reqRow = mock(Elasticsearch6AllReqRow.class); - - @Test -//有问题,有参构造器初始化时getKind()中Sqlkind.inter无法赋值 - public void ES6Test() throws Exception { - BaseRow value = mock(BaseRow.class); - Collector out = mock(Collector.class); - BaseRow input = mock(BaseRow.class); - Object sideInput = mock(Object.class); - reqRow.initCache(); - reqRow.getFetchSize(); - reqRow.reloadCache(); - reqRow.flatMap(value, out); - reqRow.fillData(input, sideInput); - } - -} diff --git a/elasticsearch6/elasticsearch6-side/elasticsearch6-all-side/src/test/java/com/dtstack/flink/sql/side/elasticsearch6/Elasticsearch6AllSideInfoTest.java b/elasticsearch6/elasticsearch6-side/elasticsearch6-all-side/src/test/java/com/dtstack/flink/sql/side/elasticsearch6/Elasticsearch6AllSideInfoTest.java deleted file mode 100644 index 98c1fd8c7..000000000 --- a/elasticsearch6/elasticsearch6-side/elasticsearch6-all-side/src/test/java/com/dtstack/flink/sql/side/elasticsearch6/Elasticsearch6AllSideInfoTest.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.dtstack.flink.sql.side.elasticsearch6; - - -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import org.apache.calcite.sql.SqlNode; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.ArrayList; -import java.util.List; - -import static org.mockito.Mockito.mock; - -/** - * Company: www.dtstack.com - * - * @author zhufeng - * @date 2020-07-02 - */ -public class Elasticsearch6AllSideInfoTest { - FieldInfo fieldInfo = new FieldInfo(); - @Mock - TypeInformation typeInformation; - List outFieldInfoList = new ArrayList(); - Elasticsearch6AllSideInfo allSideInfo; - @Mock - RowTypeInfo rowTypeInfo; - @Mock - AbstractSideTableInfo sideTableInfo; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - fieldInfo = new FieldInfo(); - fieldInfo.setTypeInformation(typeInformation); - fieldInfo.setTable("mytable"); - fieldInfo.setFieldName("mytable"); - outFieldInfoList.add(0, fieldInfo); - JoinInfo joinInfo = new JoinInfo(); - joinInfo.setLeftTableAlias("mytable"); - joinInfo.setLeftIsSideTable(true); - SqlNode sqlNode = mock(SqlNode.class); - joinInfo.setCondition(sqlNode); - try { - allSideInfo = new Elasticsearch6AllSideInfo(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); - } catch (Exception ignored) { - } - JoinInfo joinInfo1 = new JoinInfo(); - joinInfo1.setRightTableAlias("mytable"); - joinInfo1.setLeftIsSideTable(true); - try { - allSideInfo = new Elasticsearch6AllSideInfo(rowTypeInfo, joinInfo1, outFieldInfoList, sideTableInfo); - } catch (Exception ignored) { - } - JoinInfo joinInfo2 = new JoinInfo(); - try { - allSideInfo = new Elasticsearch6AllSideInfo(rowTypeInfo, joinInfo2, outFieldInfoList, sideTableInfo); - } catch (Exception ignored) { - } - } - - @Test - public void buildEqualInfoTest() { - } -} diff --git a/elasticsearch6/elasticsearch6-side/elasticsearch6-async-side/pom.xml b/elasticsearch6/elasticsearch6-side/elasticsearch6-async-side/pom.xml deleted file mode 100644 index bc1d96bb4..000000000 --- a/elasticsearch6/elasticsearch6-side/elasticsearch6-async-side/pom.xml +++ /dev/null @@ -1,101 +0,0 @@ - - - - sql.side.elasticsearch6 - com.dtstack.flink - 1.0-SNAPSHOT - - 4.0.0 - - sql.side.async.elasticsearch6 - elasticsearch6-async-side - jar - - - 1.0-SNAPSHOT - - - - - - org.elasticsearch.client - elasticsearch-rest-high-level-client - ${elasticsearch.version} - - - - com.dtstack.flink - sql.side.elasticsearch6.core - ${sql.side.elasticsearch6.core.version} - - - - - - - - org.apache.maven.plugins - maven-shade-plugin - 1.4 - - - package - - shade - - - false - - - - - - - - *:* - - META-INF/*.SF - META-INF/*.DSA - META-INF/*.RSA - - - - - - - - - - maven-antrun-plugin - 1.2 - - - copy-resources - - package - - run - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/elasticsearch6/elasticsearch6-side/elasticsearch6-async-side/src/main/java/com/dtstack/flink/sql/side/elasticsearch6/Elasticsearch6AsyncReqRow.java b/elasticsearch6/elasticsearch6-side/elasticsearch6-async-side/src/main/java/com/dtstack/flink/sql/side/elasticsearch6/Elasticsearch6AsyncReqRow.java deleted file mode 100644 index 9a1c10811..000000000 --- a/elasticsearch6/elasticsearch6-side/elasticsearch6-async-side/src/main/java/com/dtstack/flink/sql/side/elasticsearch6/Elasticsearch6AsyncReqRow.java +++ /dev/null @@ -1,254 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.elasticsearch6; - -import com.dtstack.flink.sql.enums.ECacheContentType; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.BaseAsyncReqRow; -import com.dtstack.flink.sql.side.CacheMissVal; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.PredicateInfo; -import com.dtstack.flink.sql.side.cache.CacheObj; -import com.dtstack.flink.sql.side.elasticsearch6.table.Elasticsearch6SideTableInfo; -import com.dtstack.flink.sql.side.elasticsearch6.util.Es6Util; -import com.dtstack.flink.sql.util.ParseUtils; -import com.dtstack.flink.sql.util.RowDataComplete; -import com.google.common.collect.Lists; -import org.apache.calcite.sql.SqlNode; -import org.apache.commons.lang3.StringUtils; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.configuration.Configuration; -import org.apache.flink.streaming.api.functions.async.ResultFuture; -import org.apache.flink.table.dataformat.BaseRow; -import org.apache.flink.table.dataformat.GenericRow; -import org.apache.flink.table.typeutils.TimeIndicatorTypeInfo; -import org.elasticsearch.action.ActionListener; -import org.elasticsearch.action.search.SearchRequest; -import org.elasticsearch.action.search.SearchResponse; -import org.elasticsearch.client.RequestOptions; -import org.elasticsearch.client.RestHighLevelClient; -import org.elasticsearch.index.query.BoolQueryBuilder; -import org.elasticsearch.search.SearchHit; -import org.elasticsearch.search.builder.SearchSourceBuilder; -import org.elasticsearch.search.sort.SortOrder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.io.Serializable; -import java.sql.Timestamp; -import java.util.List; -import java.util.Map; - -/** - * @author yinxi - * @date 2020/2/13 - 13:10 - */ -public class Elasticsearch6AsyncReqRow extends BaseAsyncReqRow implements Serializable { - - private static final Logger LOG = LoggerFactory.getLogger(Elasticsearch6AsyncReqRow.class); - private transient RestHighLevelClient rhlClient; - private SearchRequest searchRequest; - private List sqlJoinCompareOperate = Lists.newArrayList(); - - public Elasticsearch6AsyncReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { - super(new Elasticsearch6AsyncSideInfo(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo)); - SqlNode conditionNode = joinInfo.getCondition(); - ParseUtils.parseJoinCompareOperate(conditionNode, sqlJoinCompareOperate); - } - - @Override - public void open(Configuration parameters) throws Exception { - super.open(parameters); - Elasticsearch6SideTableInfo tableInfo = (Elasticsearch6SideTableInfo) sideInfo.getSideTableInfo(); - rhlClient = Es6Util.getClient(tableInfo.getAddress(), tableInfo.isAuthMesh(), tableInfo.getUserName(), tableInfo.getPassword()); - searchRequest = Es6Util.setSearchRequest(sideInfo); - - } - - - @Override - public void handleAsyncInvoke(Map inputParams, BaseRow input, ResultFuture resultFuture) throws Exception { - String key = buildCacheKey(inputParams); - BoolQueryBuilder boolQueryBuilder = Es6Util.setPredicateclause(sideInfo); - boolQueryBuilder = setInputParams(inputParams, boolQueryBuilder); - SearchSourceBuilder searchSourceBuilder = initConfiguration(); - searchSourceBuilder.query(boolQueryBuilder); - searchRequest.source(searchSourceBuilder); - - // 异步查询数据 - rhlClient.searchAsync(searchRequest, RequestOptions.DEFAULT, new ActionListener() { - - //成功响应时 - @Override - public void onResponse(SearchResponse searchResponse) { - - List cacheContent = Lists.newArrayList(); - List rowList = Lists.newArrayList(); - SearchHit[] searchHits = searchResponse.getHits().getHits(); - if (searchHits.length > 0) { - Elasticsearch6SideTableInfo tableInfo = null; - RestHighLevelClient tmpRhlClient = null; - try { - while (true) { - loadDataToCache(searchHits, rowList, cacheContent, input); - // determine if all results haven been ferched - if (searchHits.length < getFetchSize()) { - break; - } - if (tableInfo == null) { - // create new connection to fetch data - tableInfo = (Elasticsearch6SideTableInfo) sideInfo.getSideTableInfo(); - tmpRhlClient = Es6Util.getClient(tableInfo.getAddress(), tableInfo.isAuthMesh(), tableInfo.getUserName(), tableInfo.getPassword()); - } - Object[] searchAfterParameter = searchHits[searchHits.length - 1].getSortValues(); - searchSourceBuilder.searchAfter(searchAfterParameter); - searchRequest.source(searchSourceBuilder); - searchResponse = tmpRhlClient.search(searchRequest, RequestOptions.DEFAULT); - searchHits = searchResponse.getHits().getHits(); - } - dealCacheData(key, CacheObj.buildCacheObj(ECacheContentType.MultiLine, cacheContent)); - RowDataComplete.completeBaseRow(resultFuture, rowList); - } catch (Exception e) { - dealFillDataError(input, resultFuture, e); - } finally { - if (tmpRhlClient != null) { - try { - tmpRhlClient.close(); - } catch (IOException e) { - LOG.warn("Failed to shut down tmpRhlClient.", e); - } - } - } - } else { - dealMissKey(input, resultFuture); - dealCacheData(key, CacheMissVal.getMissKeyObj()); - } - } - - // 响应失败处理 - @Override - public void onFailure(Exception e) { - LOG.error("" + e); - resultFuture.completeExceptionally(new RuntimeException("Response failed!")); - } - }); - } - - @Override - public String buildCacheKey(Map inputParams) { - StringBuilder sb = new StringBuilder(); - for (Object ele : inputParams.values()) { - sb.append(ele) - .append("_"); - } - - return sb.toString(); - } - - private void loadDataToCache(SearchHit[] searchHits, List rowList, List cacheContent, BaseRow copyCrow) { - List results = Lists.newArrayList(); - for (SearchHit searchHit : searchHits) { - Map object = searchHit.getSourceAsMap(); - results.add(object); - } - rowList.addAll(getRows(copyCrow, cacheContent, results)); - } - - protected List getRows(BaseRow inputRow, List cacheContent, List results) { - List rowList = Lists.newArrayList(); - for (Object line : results) { - BaseRow row = fillData(inputRow, line); - if (null != cacheContent && openCache()) { - cacheContent.add(line); - } - rowList.add(row); - } - return rowList; - } - - @Override - public BaseRow fillData(BaseRow input, Object line) { - GenericRow genericRow = (GenericRow) input; - Map cacheInfo = (Map) line; - GenericRow row = new GenericRow(sideInfo.getOutFieldInfoList().size()); - row.setHeader(input.getHeader()); - String[] fields = sideInfo.getSideTableInfo().getFieldTypes(); - for (Map.Entry entry : sideInfo.getInFieldIndex().entrySet()) { - Object obj = genericRow.getField(entry.getValue()); - boolean isTimeIndicatorTypeInfo = TimeIndicatorTypeInfo.class.isAssignableFrom(sideInfo.getRowTypeInfo().getTypeAt(entry.getValue()).getClass()); - if (obj instanceof Timestamp && isTimeIndicatorTypeInfo) { - obj = ((Timestamp) obj).getTime(); - } - - row.setField(entry.getKey(), obj); - } - - for (Map.Entry entry : sideInfo.getSideFieldIndex().entrySet()) { - if (cacheInfo == null) { - row.setField(entry.getKey(), null); - } else { - Object object = Es6Util.getTarget(cacheInfo.get(sideInfo.getSideFieldNameIndex().get(entry.getKey())), fields[entry.getValue()]); - row.setField(entry.getKey(), object); - } - } - - return row; - } - - @Override - public void close() throws Exception { - super.close(); - if (rhlClient != null) { - rhlClient.close(); - } - - } - - private SearchSourceBuilder initConfiguration() { - SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); - searchSourceBuilder.size(getFetchSize()); - searchSourceBuilder.sort("_id", SortOrder.DESC); - String[] sideFieldNames = StringUtils.split(sideInfo.getSideSelectFields().trim(), ","); - searchSourceBuilder.fetchSource(sideFieldNames, null); - - return searchSourceBuilder; - } - - private BoolQueryBuilder setInputParams(Map inputParams, BoolQueryBuilder boolQueryBuilder) { - if (boolQueryBuilder == null) { - boolQueryBuilder = new BoolQueryBuilder(); - } - - for (int i = 0; i < sqlJoinCompareOperate.size(); i++) { - String fieldName = sideInfo.getEqualFieldList().get(i); - String operatorKind = sqlJoinCompareOperate.get(sideInfo.getEqualFieldList().indexOf(fieldName)); - String condition = String.valueOf(inputParams.get(fieldName)); - boolQueryBuilder = Es6Util.buildFilterCondition(boolQueryBuilder, new PredicateInfo(null, operatorKind, null, fieldName, condition), sideInfo); - } - - return boolQueryBuilder; - } - - public int getFetchSize() { - return 1000; - } -} - diff --git a/elasticsearch6/elasticsearch6-side/elasticsearch6-async-side/src/main/java/com/dtstack/flink/sql/side/elasticsearch6/Elasticsearch6AsyncSideInfo.java b/elasticsearch6/elasticsearch6-side/elasticsearch6-async-side/src/main/java/com/dtstack/flink/sql/side/elasticsearch6/Elasticsearch6AsyncSideInfo.java deleted file mode 100644 index f584e3149..000000000 --- a/elasticsearch6/elasticsearch6-side/elasticsearch6-async-side/src/main/java/com/dtstack/flink/sql/side/elasticsearch6/Elasticsearch6AsyncSideInfo.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.elasticsearch6; - -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.BaseSideInfo; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.util.ParseUtils; -import com.google.common.collect.Lists; -import org.apache.calcite.sql.SqlNode; -import org.apache.flink.api.java.typeutils.RowTypeInfo; - -import java.util.List; - -/** - * @author yinxi - * @date 2020/2/13 - 13:09 - */ -public class Elasticsearch6AsyncSideInfo extends BaseSideInfo { - - public Elasticsearch6AsyncSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { - super(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); - } - - @Override - public void buildEqualInfo(JoinInfo joinInfo, AbstractSideTableInfo sideTableInfo) { - - String sideTableName = joinInfo.getSideTableName(); - SqlNode conditionNode = joinInfo.getCondition(); - List sqlNodeList = Lists.newArrayList(); - ParseUtils.parseAnd(conditionNode, sqlNodeList); - - for (SqlNode sqlNode : sqlNodeList) { - dealOneEqualCon(sqlNode, sideTableName); - } - } -} diff --git a/elasticsearch6/elasticsearch6-side/elasticsearch6-async-side/src/test/java/com/dtstack/flink/sql/side/elasticsearch6/Elasticsearch6AsyncReqRowTest.java b/elasticsearch6/elasticsearch6-side/elasticsearch6-async-side/src/test/java/com/dtstack/flink/sql/side/elasticsearch6/Elasticsearch6AsyncReqRowTest.java deleted file mode 100644 index 1cbf0fc1f..000000000 --- a/elasticsearch6/elasticsearch6-side/elasticsearch6-async-side/src/test/java/com/dtstack/flink/sql/side/elasticsearch6/Elasticsearch6AsyncReqRowTest.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.dtstack.flink.sql.side.elasticsearch6; - -/** - * Company: www.dtstack.com - * - * @author zhufeng - * @date 2020-07-03 - */ -public class Elasticsearch6AsyncReqRowTest { -//有问题,有参构造器初始化时getKind()中Sqlkind.inter无法赋值,后面的方法暂时不能测试 -} diff --git a/elasticsearch6/elasticsearch6-side/elasticsearch6-async-side/src/test/java/com/dtstack/flink/sql/side/elasticsearch6/Elasticsearch6AsyncSideInfoTest.java b/elasticsearch6/elasticsearch6-side/elasticsearch6-async-side/src/test/java/com/dtstack/flink/sql/side/elasticsearch6/Elasticsearch6AsyncSideInfoTest.java deleted file mode 100644 index ee1b1f166..000000000 --- a/elasticsearch6/elasticsearch6-side/elasticsearch6-async-side/src/test/java/com/dtstack/flink/sql/side/elasticsearch6/Elasticsearch6AsyncSideInfoTest.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.dtstack.flink.sql.side.elasticsearch6; - -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import org.apache.calcite.sql.SqlNode; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.ArrayList; -import java.util.List; - -import static org.mockito.Mockito.mock; - -/** - * Company: www.dtstack.com - * - * @author zhufeng - * @date 2020-07-02 - */ -public class Elasticsearch6AsyncSideInfoTest { - - @Mock - RowTypeInfo rowTypeInfo; - List outFieldInfoList = new ArrayList<>(); - - AbstractSideTableInfo sideTableInfo = new AbstractSideTableInfo() { - private static final long serialVersionUID = 8709300729625942851L; - - @Override - public boolean check() { - return false; - } - }; - @Mock - TypeInformation typeInformation; - FieldInfo fieldInfo = new FieldInfo(); - Elasticsearch6AsyncSideInfo sideInfo; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - fieldInfo = new FieldInfo(); - fieldInfo.setTypeInformation(typeInformation); - fieldInfo.setTable("mytable"); - fieldInfo.setFieldName("mytable"); - outFieldInfoList.add(0, fieldInfo); - JoinInfo joinInfo = new JoinInfo(); - joinInfo.setLeftTableAlias("mytable"); - joinInfo.setLeftIsSideTable(true); - sideTableInfo.addField("mytable"); - String[] str = new String[10]; - str[0] = "varchar"; - sideTableInfo.setFieldTypes(str); - SqlNode sqlNode = mock(SqlNode.class); - joinInfo.setCondition(sqlNode); - /* Whitebox.setInternalState(sqlKind, OTHER, );*/ - try { - sideInfo = new Elasticsearch6AsyncSideInfo(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); - } catch (Exception ignored) { - } - - } - - @Test - public void Test() { - - } -} diff --git a/elasticsearch6/elasticsearch6-side/elasticsearch6-side-core/pom.xml b/elasticsearch6/elasticsearch6-side/elasticsearch6-side-core/pom.xml deleted file mode 100644 index 457f6b5d5..000000000 --- a/elasticsearch6/elasticsearch6-side/elasticsearch6-side-core/pom.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - sql.side.elasticsearch6 - com.dtstack.flink - 1.0-SNAPSHOT - ../pom.xml - - 4.0.0 - - sql.side.elasticsearch6.core - elasticsearch6-side-core - 1.0-SNAPSHOT - jar - - - - org.elasticsearch.client - elasticsearch-rest-high-level-client - ${elasticsearch.version} - - - junit - junit - 4.12 - test - - - - - \ No newline at end of file diff --git a/elasticsearch6/elasticsearch6-side/elasticsearch6-side-core/src/main/java/com/dtstack/flink/sql/side/elasticsearch6/table/Elasticsearch6SideParser.java b/elasticsearch6/elasticsearch6-side/elasticsearch6-side-core/src/main/java/com/dtstack/flink/sql/side/elasticsearch6/table/Elasticsearch6SideParser.java deleted file mode 100644 index dfe84d04b..000000000 --- a/elasticsearch6/elasticsearch6-side/elasticsearch6-side-core/src/main/java/com/dtstack/flink/sql/side/elasticsearch6/table/Elasticsearch6SideParser.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.elasticsearch6.table; - -import com.dtstack.flink.sql.table.AbstractSideTableParser; -import com.dtstack.flink.sql.table.AbstractTableInfo; -import com.dtstack.flink.sql.util.ClassUtil; -import com.dtstack.flink.sql.util.MathUtil; -import org.apache.commons.lang3.StringUtils; - -import java.util.Map; - -/** - * @author yinxi - * @date 2020/1/13 - 1:07 - */ -public class Elasticsearch6SideParser extends AbstractSideTableParser { - - private static final String KEY_ES6_ADDRESS = "address"; - - private static final String KEY_ES6_CLUSTER = "cluster"; - - private static final String KEY_ES6_INDEX = "index"; - - private static final String KEY_ES6_TYPE = "esType"; - - private static final String KEY_ES6_AUTHMESH = "authMesh"; - - private static final String KEY_ES6_USERNAME = "userName"; - - private static final String KEY_ES6_PASSWORD = "password"; - - private static final String KEY_TRUE = "true"; - - - @Override - protected boolean fieldNameNeedsUpperCase() { - return false; - } - - @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { - Elasticsearch6SideTableInfo elasticsearch6SideTableInfo = new Elasticsearch6SideTableInfo(); - elasticsearch6SideTableInfo.setName(tableName); - parseFieldsInfo(fieldsInfo, elasticsearch6SideTableInfo); - parseCacheProp(elasticsearch6SideTableInfo, props); - elasticsearch6SideTableInfo.setAddress((String) props.get(KEY_ES6_ADDRESS.toLowerCase())); - elasticsearch6SideTableInfo.setClusterName((String) props.get(KEY_ES6_CLUSTER.toLowerCase())); - elasticsearch6SideTableInfo.setIndex((String) props.get(KEY_ES6_INDEX.toLowerCase())); - elasticsearch6SideTableInfo.setEsType((String) props.get(KEY_ES6_TYPE.toLowerCase())); - - String authMeshStr = (String) props.get(KEY_ES6_AUTHMESH.toLowerCase()); - if (authMeshStr != null && StringUtils.equalsIgnoreCase(KEY_TRUE, authMeshStr)) { - elasticsearch6SideTableInfo.setAuthMesh(MathUtil.getBoolean(authMeshStr)); - elasticsearch6SideTableInfo.setUserName(MathUtil.getString(props.get(KEY_ES6_USERNAME.toLowerCase()))); - elasticsearch6SideTableInfo.setPassword(MathUtil.getString(props.get(KEY_ES6_PASSWORD.toLowerCase()))); - } - - if (MathUtil.getLongVal(props.get(elasticsearch6SideTableInfo.ERROR_LIMIT.toLowerCase())) != null) { - elasticsearch6SideTableInfo.setErrorLimit(MathUtil.getLongVal(props.get(elasticsearch6SideTableInfo.ERROR_LIMIT.toLowerCase()))); - } - - elasticsearch6SideTableInfo.check(); - return elasticsearch6SideTableInfo; - } - - @Override - public Class dbTypeConvertToJavaType(String fieldType) { - return ClassUtil.stringConvertClass(fieldType); - } -} diff --git a/elasticsearch6/elasticsearch6-side/elasticsearch6-side-core/src/main/java/com/dtstack/flink/sql/side/elasticsearch6/table/Elasticsearch6SideTableInfo.java b/elasticsearch6/elasticsearch6-side/elasticsearch6-side-core/src/main/java/com/dtstack/flink/sql/side/elasticsearch6/table/Elasticsearch6SideTableInfo.java deleted file mode 100644 index 3b8cfa114..000000000 --- a/elasticsearch6/elasticsearch6-side/elasticsearch6-side-core/src/main/java/com/dtstack/flink/sql/side/elasticsearch6/table/Elasticsearch6SideTableInfo.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.elasticsearch6.table; - -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.google.common.base.Preconditions; -import org.elasticsearch.search.builder.SearchSourceBuilder; - -/** - * @author yinxi - * @date 2020/1/13 - 15:00 - */ -public class Elasticsearch6SideTableInfo extends AbstractSideTableInfo { - - private static final String CURR_TYPE = "elasticsearch6"; - - private String address; - - private String clusterName; - - private String index; - - private String esType; - - private boolean authMesh = false; - - private String userName; - - private String password; - - private transient SearchSourceBuilder searchSourceBuilder; - - public String getEsType() { - return esType; - } - - public void setEsType(String esType) { - this.esType = esType; - } - - public String getAddress() { - return address; - } - - public void setAddress(String address) { - this.address = address; - } - - public String getIndex() { - return index; - } - - public void setIndex(String index) { - this.index = index; - } - - @Override - public String getType() { - //return super.getType().toLowerCase() + TARGET_SUFFIX; - return super.getType().toLowerCase(); - } - - public void setClusterName(String clusterName) { - this.clusterName = clusterName; - } - - public boolean isAuthMesh() { - return authMesh; - } - - public void setAuthMesh(boolean authMesh) { - this.authMesh = authMesh; - } - - public String getUserName() { - return userName; - } - - public void setUserName(String userName) { - this.userName = userName; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - - public SearchSourceBuilder getSearchSourceBuilder() { - return searchSourceBuilder; - } - - public void setSearchSourceBuilder(SearchSourceBuilder searchSourceBuilder) { - this.searchSourceBuilder = searchSourceBuilder; - } - - public Elasticsearch6SideTableInfo() { - setType(CURR_TYPE); - } - - @Override - public boolean check() { - Preconditions.checkNotNull(address, "elasticsearch6 type of address is required"); - Preconditions.checkNotNull(clusterName, "elasticsearch6 type of clusterName is required"); - - if (isAuthMesh()) { - Preconditions.checkNotNull(userName, "elasticsearch6 type of userName is required"); - Preconditions.checkNotNull(password, "elasticsearch6 type of password is required"); - } - - return true; - } -} diff --git a/elasticsearch6/elasticsearch6-side/elasticsearch6-side-core/src/main/java/com/dtstack/flink/sql/side/elasticsearch6/util/Es6Util.java b/elasticsearch6/elasticsearch6-side/elasticsearch6-side-core/src/main/java/com/dtstack/flink/sql/side/elasticsearch6/util/Es6Util.java deleted file mode 100644 index 8ed3a415b..000000000 --- a/elasticsearch6/elasticsearch6-side/elasticsearch6-side-core/src/main/java/com/dtstack/flink/sql/side/elasticsearch6/util/Es6Util.java +++ /dev/null @@ -1,271 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.elasticsearch6.util; - -import com.dtstack.flink.sql.side.BaseSideInfo; -import com.dtstack.flink.sql.side.PredicateInfo; -import com.dtstack.flink.sql.side.elasticsearch6.table.Elasticsearch6SideTableInfo; -import com.dtstack.flink.sql.util.MathUtil; -import org.apache.commons.lang3.StringUtils; -import org.apache.http.HttpHost; -import org.apache.http.auth.AuthScope; -import org.apache.http.auth.UsernamePasswordCredentials; -import org.apache.http.client.CredentialsProvider; -import org.apache.http.impl.client.BasicCredentialsProvider; -import org.elasticsearch.action.search.SearchRequest; -import org.elasticsearch.client.RequestOptions; -import org.elasticsearch.client.RestClient; -import org.elasticsearch.client.RestClientBuilder; -import org.elasticsearch.client.RestHighLevelClient; -import org.elasticsearch.index.query.BoolQueryBuilder; -import org.elasticsearch.index.query.QueryBuilders; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; - -/** - * @author yinxi - * @date 2020/2/21 - 20:51 - */ -public class Es6Util { - - private static final Logger LOG = LoggerFactory.getLogger(Es6Util.class); - private static final String KEY_WORD_TYPE = ".keyword"; - private static final String APOSTROPHE = "'"; - - // connect to the elasticsearch - public static RestHighLevelClient getClient(String esAddress, Boolean isAuthMesh, String userName, String password) { - List httpHostList = new ArrayList<>(); - String[] address = StringUtils.split(esAddress, ","); - for (String addr : address) { - String[] infoArray = StringUtils.split(addr, ":"); - int port = 9200; - String host = infoArray[0].trim(); - if (infoArray.length > 1) { - port = Integer.parseInt(infoArray[1].trim()); - } - httpHostList.add(new HttpHost(host, port, "http")); - } - - RestClientBuilder restClientBuilder = RestClient.builder(httpHostList.toArray(new HttpHost[0])); - - if (isAuthMesh) { - // 进行用户和密码认证 - final CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); - credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(userName.trim(), password.trim())); - restClientBuilder.setHttpClientConfigCallback(httpAsyncClientBuilder -> - httpAsyncClientBuilder.setDefaultCredentialsProvider(credentialsProvider)); - } - - RestHighLevelClient rhlClient = new RestHighLevelClient(restClientBuilder); - - if (LOG.isInfoEnabled()) { - LOG.info("Pinging Elasticsearch cluster via hosts {} ...", httpHostList); - } - - try { - if (!rhlClient.ping(RequestOptions.DEFAULT)) { - throw new RuntimeException("There are no reachable Elasticsearch nodes!"); - } - } catch (IOException e) { - LOG.warn("", e); - } - - - if (LOG.isInfoEnabled()) { - LOG.info("Created Elasticsearch RestHighLevelClient connected to {}", httpHostList.toString()); - } - - return rhlClient; - } - - // add index and type to search request - public static SearchRequest setSearchRequest(BaseSideInfo sideInfo) { - SearchRequest searchRequest = new SearchRequest(); - Elasticsearch6SideTableInfo tableInfo = (Elasticsearch6SideTableInfo) sideInfo.getSideTableInfo(); - // determine existence of index - String index = tableInfo.getIndex(); - if (!StringUtils.isEmpty(index) || index.trim().length() > 0) { - // strip leading and trailing spaces from a string - String[] indexes = StringUtils.split(index, ","); - for (int i = 0; i < indexes.length; i++) { - indexes[i] = indexes[i].trim(); - } - - searchRequest.indices(indexes); - } - - // determine existence of type - String type = tableInfo.getEsType(); - if (!StringUtils.isEmpty(type) || type.trim().length() > 0) { - // strip leading and trailing spaces from a string - String[] types = StringUtils.split(type, ","); - for (int i = 0; i < types.length; i++) { - types[i] = types[i].trim(); - } - - searchRequest.types(types); - } - - return searchRequest; - } - - // build where cause - public static BoolQueryBuilder setPredicateclause(BaseSideInfo sideInfo) { - - BoolQueryBuilder boolQueryBuilder = null; - List predicateInfoes = sideInfo.getSideTableInfo().getPredicateInfoes(); - if (predicateInfoes.size() > 0) { - boolQueryBuilder = new BoolQueryBuilder(); - for (PredicateInfo info : predicateInfoes) { - boolQueryBuilder = Es6Util.buildFilterCondition(boolQueryBuilder, info, sideInfo); - } - } - - return boolQueryBuilder; - } - - // build filter condition - public static BoolQueryBuilder buildFilterCondition(BoolQueryBuilder boolQueryBuilder, PredicateInfo info, BaseSideInfo sideInfo) { - switch (info.getOperatorKind()) { - case "IN": - return boolQueryBuilder.must(QueryBuilders.termsQuery(textConvertToKeyword(info.getFieldName(), sideInfo), removeSpaceAndApostrophe(info.getCondition()))); - case "NOT_IN": - return boolQueryBuilder.mustNot(QueryBuilders.termsQuery(textConvertToKeyword(info.getFieldName(), sideInfo), removeSpaceAndApostrophe(info.getCondition()))); - case ">=": - case "GREATER_THAN_OR_EQUAL": - return boolQueryBuilder.must(QueryBuilders.rangeQuery(info.getFieldName()).gte(info.getCondition())); - case ">": - case "GREATER_THAN": - return boolQueryBuilder.must(QueryBuilders.rangeQuery(info.getFieldName()).gt(info.getCondition())); - case "<=": - case "LESS_THAN_OR_EQUAL": - return boolQueryBuilder.must(QueryBuilders.rangeQuery(info.getFieldName()).lte(info.getCondition())); - case "<": - case "LESS_THAN": - return boolQueryBuilder.must(QueryBuilders.rangeQuery(info.getFieldName()).lt(info.getCondition())); - case "BETWEEN": - return boolQueryBuilder.must(QueryBuilders.rangeQuery(info.getFieldName()).gte(StringUtils.split(info.getCondition().toUpperCase(), "AND")[0].trim()) - .lte(StringUtils.split(info.getCondition().toUpperCase(), "AND")[1].trim())); - case "IS_NULL": - return boolQueryBuilder.mustNot(QueryBuilders.existsQuery(info.getFieldName())); - case "IS_NOT_NULL": - return boolQueryBuilder.must(QueryBuilders.existsQuery(info.getFieldName())); - case "=": - case "EQUALS": - if (StringUtils.isBlank(info.getCondition())) { - return boolQueryBuilder; - } - return boolQueryBuilder.must(QueryBuilders.termQuery(textConvertToKeyword(info.getFieldName(), sideInfo), removeSpaceAndApostrophe(info.getCondition())[0])); - case "<>": - case "NOT_EQUALS": - return boolQueryBuilder.mustNot(QueryBuilders.termQuery(textConvertToKeyword(info.getFieldName(), sideInfo), removeSpaceAndApostrophe(info.getCondition())[0])); - default: - return boolQueryBuilder; - } - - } - - // remove extra spaces and apostrophes - public static String[] removeSpaceAndApostrophe(String str) { - String[] split = StringUtils.split(str, ","); - for (int i = 0; i < split.length; i++) { - split[i] = StringUtils.trim(split[i]); - if (StringUtils.startsWith(split[i], APOSTROPHE)) { - split[i] = StringUtils.substring(split[i], 1, split[i].length() - 1); - } - } - - return split; - } - - // prevent word segmentation - public static String textConvertToKeyword(String fieldName, BaseSideInfo sideInfo) { - String[] sideFieldTypes = sideInfo.getSideTableInfo().getFieldTypes(); - int fieldIndex = sideInfo.getSideTableInfo().getFieldList().indexOf(fieldName.trim()); - String fieldType = sideFieldTypes[fieldIndex]; - switch (fieldType.toLowerCase(Locale.ENGLISH)) { - case "varchar": - case "char": - case "text": - return fieldName + KEY_WORD_TYPE; - default: - return fieldName; - } - } - - public static Object getTarget(Object obj, String targetType) { - switch (targetType.toLowerCase(Locale.ENGLISH)) { - - case "smallint": - case "smallintunsigned": - case "tinyint": - case "tinyintunsigned": - case "mediumint": - case "mediumintunsigned": - case "integer": - case "int": - return MathUtil.getIntegerVal(obj); - - case "bigint": - case "bigintunsigned": - case "intunsigned": - case "integerunsigned": - return MathUtil.getLongVal(obj); - - case "boolean": - return MathUtil.getBoolean(obj); - - case "blob": - return MathUtil.getByte(obj); - - case "varchar": - case "char": - case "text": - return MathUtil.getString(obj); - - case "real": - case "float": - case "realunsigned": - case "floatunsigned": - return MathUtil.getFloatVal(obj); - - case "double": - case "doubleunsigned": - return MathUtil.getDoubleVal(obj); - - case "decimal": - case "decimalunsigned": - return MathUtil.getBigDecimal(obj); - - case "date": - return MathUtil.getDate(obj); - - case "timestamp": - case "datetime": - return MathUtil.getTimestamp(obj); - default: - } - return obj; - } -} diff --git a/elasticsearch6/elasticsearch6-side/elasticsearch6-side-core/src/test/java/com/dtstack/flink/sql/side/elasticsearch6/table/Elasticsearch6SideParserTest.java b/elasticsearch6/elasticsearch6-side/elasticsearch6-side-core/src/test/java/com/dtstack/flink/sql/side/elasticsearch6/table/Elasticsearch6SideParserTest.java deleted file mode 100644 index c672e0970..000000000 --- a/elasticsearch6/elasticsearch6-side/elasticsearch6-side-core/src/test/java/com/dtstack/flink/sql/side/elasticsearch6/table/Elasticsearch6SideParserTest.java +++ /dev/null @@ -1,81 +0,0 @@ - - -package com.dtstack.flink.sql.side.elasticsearch6.table; - - -import com.dtstack.flink.sql.table.AbstractTableInfo; -import com.dtstack.flink.sql.table.AbstractTableParser; -import com.dtstack.flink.sql.util.MathUtil; -import org.junit.Before; -import org.junit.Test; -import org.mockito.MockitoAnnotations; -import org.mockito.Spy; - -import java.util.HashMap; -import java.util.Map; - -import static org.junit.Assert.assertFalse; - -/** - * Company: www.dtstack.com - * - * @author zhufeng - * @date 2020-07-02 - */ -public class Elasticsearch6SideParserTest { - - @Spy - Elasticsearch6SideParser elasticsearch6SideParser; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - } - - //ElasticsearchSinkParser中的fieldNameNeedsUpperCase方法 - @Test - public void fieldNameNeedsUpperCaseTest() { - assertFalse(elasticsearch6SideParser.fieldNameNeedsUpperCase()); - } - - - //getTableInfo方法,得到输入的表信息 - @Test - public void getTableInfoTest() { - String tableName = "MyResult"; - String fieldsInfo = "pv varchar, channel varchar, PRIMARY KEY (pv)"; - Map props = new HashMap<>(); - props.put("cluster", "docker-cluster"); - props.put("password", "abc123"); - props.put("address", "172.16.8.193:9200"); - props.put("parallelism", "1"); - props.put("index", "myresult"); - props.put("updatemode", "append"); - props.put("id", "1"); - props.put("type", "elasticsearch"); - props.put("estype", "elasticsearch"); - props.put("authmesh", "true"); - props.put("username", "elastic"); - AbstractTableParser tableParser = new AbstractTableParser() { - @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) throws Exception { - return null; - } - }; - Elasticsearch6SideTableInfo elasticsearchTableInfo = new Elasticsearch6SideTableInfo(); - elasticsearchTableInfo.setName(tableName); - tableParser.parseFieldsInfo(fieldsInfo, elasticsearchTableInfo); - elasticsearchTableInfo.setAddress((String) props.get("address")); - elasticsearchTableInfo.setClusterName((String) props.get("cluster")); - elasticsearchTableInfo.setIndex((String) props.get("index")); - elasticsearchTableInfo.setEsType((String) props.get("estype")); - String authMeshStr = (String) props.get("authmesh"); - if (authMeshStr != null & "true".equals(authMeshStr)) { - elasticsearchTableInfo.setAuthMesh(MathUtil.getBoolean(authMeshStr)); - elasticsearchTableInfo.setUserName(MathUtil.getString(props.get("username"))); - elasticsearchTableInfo.setPassword(MathUtil.getString(props.get("password"))); - } - elasticsearch6SideParser.getTableInfo(tableName, fieldsInfo, props); - } - -} diff --git a/elasticsearch6/elasticsearch6-side/elasticsearch6-side-core/src/test/java/com/dtstack/flink/sql/side/elasticsearch6/table/Elasticsearch6SideTableInfoTest.java b/elasticsearch6/elasticsearch6-side/elasticsearch6-side-core/src/test/java/com/dtstack/flink/sql/side/elasticsearch6/table/Elasticsearch6SideTableInfoTest.java deleted file mode 100644 index 4e5cccda8..000000000 --- a/elasticsearch6/elasticsearch6-side/elasticsearch6-side-core/src/test/java/com/dtstack/flink/sql/side/elasticsearch6/table/Elasticsearch6SideTableInfoTest.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.elasticsearch6.table; - -import org.junit.Test; - -import java.beans.IntrospectionException; -import java.beans.PropertyDescriptor; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -/** - * Company: www.dtstack.com - * - * @author zhufeng - * @date 2020-07-02 - */ -public class Elasticsearch6SideTableInfoTest { - Elasticsearch6SideTableInfo tableInfo = new Elasticsearch6SideTableInfo(); - - @Test - public void getAndSetTest() throws InvocationTargetException, IntrospectionException, - InstantiationException, IllegalAccessException { - this.testGetAndSet(); - } - - @Test - public void getTypeTest() { - tableInfo.getType(); - } - - private void testGetAndSet() throws IllegalAccessException, InstantiationException, IntrospectionException, - InvocationTargetException { - Elasticsearch6SideTableInfo t = new Elasticsearch6SideTableInfo(); - Class modelClass = t.getClass(); - Object obj = modelClass.newInstance(); - Field[] fields = modelClass.getDeclaredFields(); - for (Field f : fields) { - if (!f.getName().equals("CURR_TYPE")) { - if (f.getName().equals("aLike") - || f.isSynthetic()) { - continue; - } - - PropertyDescriptor pd = new PropertyDescriptor(f.getName(), modelClass); - Method get = pd.getReadMethod(); - Method set = pd.getWriteMethod(); - set.invoke(obj, get.invoke(obj)); - } - } - } -} diff --git a/elasticsearch6/elasticsearch6-side/elasticsearch6-side-core/src/test/java/com/dtstack/flink/sql/side/elasticsearch6/util/Es6UtilTest.java b/elasticsearch6/elasticsearch6-side/elasticsearch6-side-core/src/test/java/com/dtstack/flink/sql/side/elasticsearch6/util/Es6UtilTest.java deleted file mode 100644 index ce1f33170..000000000 --- a/elasticsearch6/elasticsearch6-side/elasticsearch6-side-core/src/test/java/com/dtstack/flink/sql/side/elasticsearch6/util/Es6UtilTest.java +++ /dev/null @@ -1,135 +0,0 @@ -package com.dtstack.flink.sql.side.elasticsearch6.util; - -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.BaseSideInfo; -import com.dtstack.flink.sql.side.PredicateInfo; -import com.dtstack.flink.sql.side.elasticsearch6.table.Elasticsearch6SideTableInfo; -import com.dtstack.flink.sql.table.AbstractTableInfo; -import com.dtstack.flink.sql.table.AbstractTableParser; -import com.dtstack.flink.sql.util.MathUtil; -import org.elasticsearch.index.query.BoolQueryBuilder; -import org.junit.Test; - -import java.math.BigDecimal; -import java.sql.Timestamp; -import java.util.HashMap; -import java.util.Map; - - -import static org.mockito.Mockito.mock; - -/** - * Company: www.dtstack.com - * - * @author zhufeng - * @date 2020-07-02 - */ -public class Es6UtilTest { - - @Test - public void getClientTest() { - String esAddress = "172.16.8.193:9200"; - boolean isAuthMesh = true; - String userName = "elastic"; - String password = "abc123"; - Es6Util.getClient(esAddress, isAuthMesh, userName, password); - BaseSideInfo sideInfo = mock(BaseSideInfo.class); - String tableName = "MyResult"; - String fieldsInfo = "pv varchar, channel varchar, PRIMARY KEY (pv)"; - Map props = new HashMap<>(); - props.put("cluster", "docker-cluster"); - props.put("password", "abc123"); - props.put("address", "172.16.8.193:9200"); - props.put("parallelism", "1"); - props.put("index", "myresult"); - props.put("updatemode", "append"); - props.put("id", "1"); - props.put("type", "elasticsearch"); - props.put("estype", "elasticsearch"); - props.put("authmesh", "true"); - props.put("username", "elastic"); - AbstractTableParser tableParser = new AbstractTableParser() { - @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) throws Exception { - return null; - } - }; - Elasticsearch6SideTableInfo elasticsearchTableInfo = new Elasticsearch6SideTableInfo(); - elasticsearchTableInfo.setName(tableName); - tableParser.parseFieldsInfo(fieldsInfo, elasticsearchTableInfo); - elasticsearchTableInfo.setAddress((String) props.get("address")); - elasticsearchTableInfo.setClusterName((String) props.get("cluster")); - elasticsearchTableInfo.setIndex((String) props.get("index")); - elasticsearchTableInfo.setEsType((String) props.get("estype")); - String authMeshStr = (String) props.get("authmesh"); - if (authMeshStr != null & "true".equals(authMeshStr)) { - elasticsearchTableInfo.setAuthMesh(com.dtstack.flink.sql.util.MathUtil.getBoolean(authMeshStr)); - elasticsearchTableInfo.setUserName(com.dtstack.flink.sql.util.MathUtil.getString(props.get("username"))); - elasticsearchTableInfo.setPassword(MathUtil.getString(props.get("password"))); - } - AbstractSideTableInfo tableInfo = mock(AbstractSideTableInfo.class); - - sideInfo.setSideTableInfo(tableInfo); - try { - Es6Util.setSearchRequest(sideInfo); - Es6Util.setPredicateclause(sideInfo); - } catch (Exception ignored) { - } - } - - @Test - public void buildFilterConditionTest() { - BoolQueryBuilder boolQueryBuilder = mock(BoolQueryBuilder.class); - BaseSideInfo sideInfo = mock(BaseSideInfo.class); - PredicateInfo info = new PredicateInfo("zf", "IN", "mytable", "name", "varchar"); - try { - Es6Util.buildFilterCondition(boolQueryBuilder, info, sideInfo); - } catch (Exception ignored) { - } - - } - - @Test - public void removeSpaceAndApostropheTest() { - Es6Util.removeSpaceAndApostrophe("zftest"); - } - - @Test - public void textConvertToKeywordTest() { - BaseSideInfo sideInfo = mock(BaseSideInfo.class); - try { - Es6Util.textConvertToKeyword("name", sideInfo); - } catch (Exception ignored) { - } - } - - @Test - public void es6UtilTest() { - Integer test1 = 1; - String targetType = "smallint"; - Es6Util.getTarget(test1, targetType); - String targetType2 = "long"; - Es6Util.getTarget(test1, targetType2); - Boolean test2 = true; - String targetType3 = "boolean"; - Es6Util.getTarget(test2, targetType3); - Byte test3 = 1; - String targetType4 = "blob"; - Es6Util.getTarget(test3, targetType4); - String test4 = "name"; - String targetType5 = "varchar"; - Es6Util.getTarget(test4, targetType5); - Float test5 = 1.0f; - String targetType6 = "real"; - Es6Util.getTarget(test5, targetType6); - BigDecimal test7 = new BigDecimal("1234567890"); - String targetType8 = "decimal"; - Es6Util.getTarget(test7, targetType8); - java.sql.Date date = new java.sql.Date(System.currentTimeMillis()); - String targetType9 = "date"; - Es6Util.getTarget(date, targetType9); - Timestamp timestamp = new Timestamp(System.currentTimeMillis()); - String targetType10 = "timestamp"; - Es6Util.getTarget(timestamp, targetType10); - } -} diff --git a/elasticsearch6/elasticsearch6-side/pom.xml b/elasticsearch6/elasticsearch6-side/pom.xml deleted file mode 100644 index de01d68df..000000000 --- a/elasticsearch6/elasticsearch6-side/pom.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - sql.elasticsearch6 - com.dtstack.flink - 1.0-SNAPSHOT - - 4.0.0 - - sql.side.elasticsearch6 - pom - elasticsearch6-side - - elasticsearch6-all-side - elasticsearch6-async-side - elasticsearch6-side-core - - - \ No newline at end of file diff --git a/elasticsearch6/elasticsearch6-sink/pom.xml b/elasticsearch6/elasticsearch6-sink/pom.xml deleted file mode 100644 index b0ae10a7c..000000000 --- a/elasticsearch6/elasticsearch6-sink/pom.xml +++ /dev/null @@ -1,129 +0,0 @@ - - - - sql.elasticsearch6 - com.dtstack.flink - 1.0-SNAPSHOT - - 4.0.0 - - sql.sink.elasticsearch6 - elasticsearch6-sink - - - - org.apache.flink - flink-streaming-java_2.11 - ${flink.version} - provided - - - - org.elasticsearch.client - elasticsearch-rest-high-level-client - ${elasticsearch.version} - - - - log4j - log4j - 1.2.17 - - - - slf4j-api - org.slf4j - 1.7.15 - - - - - org.slf4j - slf4j-log4j12 - 1.6.1 - - - - org.apache.flink - flink-connector-elasticsearch6_2.11 - ${flink.version} - - - log4j-to-slf4j - org.apache.logging.log4j - - - - - - org.apache.flink - flink-connector-elasticsearch-base_2.11 - ${flink.version} - - - - - - - org.apache.maven.plugins - maven-shade-plugin - 1.4 - - - package - - shade - - - - - - - - - - *:* - - META-INF/*.SF - META-INF/*.DSA - META-INF/*.RSA - - - - - - - - - - maven-antrun-plugin - 1.2 - - - copy-resources - - package - - run - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/elasticsearch6/elasticsearch6-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/CustomerSinkFunc.java b/elasticsearch6/elasticsearch6-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/CustomerSinkFunc.java deleted file mode 100644 index 85df4dc62..000000000 --- a/elasticsearch6/elasticsearch6-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/CustomerSinkFunc.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.elasticsearch; - -import com.dtstack.flink.sql.util.DateUtil; -import org.apache.flink.api.common.functions.RuntimeContext; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.metrics.Counter; -import org.apache.flink.streaming.connectors.elasticsearch.ElasticsearchSinkFunction; -import org.apache.flink.streaming.connectors.elasticsearch.RequestIndexer; -import org.apache.flink.types.Row; - -import org.apache.commons.lang3.StringUtils; -import org.elasticsearch.action.index.IndexRequest; -import org.elasticsearch.client.Requests; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.sql.Date; -import java.sql.Time; -import java.sql.Timestamp; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -/** - * @author yinxi - * @date 2020/1/9 - 15:10 - */ -public class CustomerSinkFunc implements ElasticsearchSinkFunction { - - private final Logger logger = LoggerFactory.getLogger(CustomerSinkFunc.class); - /** - * 用作ID的属性值连接符号 - */ - private static final String ID_VALUE_SPLIT = "_"; - - private String index; - - private String type; - - private List ids; - - // true means generation doc's id by position "1[,1]" - private boolean usePosition; - - private List fieldNames; - - private List fieldTypes; - - private transient Counter outRecords; - - private transient Counter outDirtyRecords; - - public CustomerSinkFunc(String index, String type, List fieldNames, List fieldTypes, List ids, boolean usePosition) { - this.index = index; - this.type = type; - this.fieldNames = fieldNames; - this.fieldTypes = fieldTypes; - this.ids = ids; - this.usePosition = usePosition; - } - - @Override - public void process(Tuple2 tuple2, RuntimeContext ctx, RequestIndexer indexer) { - try { - Tuple2 tupleTrans = tuple2; - Boolean retract = tupleTrans.getField(0); - Row element = tupleTrans.getField(1); - if (!retract) { - return; - } - - indexer.add(createIndexRequest(element)); - outRecords.inc(); - } catch (Throwable e) { - outDirtyRecords.inc(); - logger.error("Failed to store source data {}. ", tuple2.getField(1)); - logger.error("Failed to create index request exception. ", e); - } - } - - public void setOutRecords(Counter outRecords) { - this.outRecords = outRecords; - } - - public void setOutDirtyRecords(Counter outDirtyRecords) { - this.outDirtyRecords = outDirtyRecords; - } - - private IndexRequest createIndexRequest(Row element) { - - Map dataMap = Es6Util.rowToJsonMap(element, fieldNames, fieldTypes); - int length = Math.min(element.getArity(), fieldNames.size()); - for (int i = 0; i < length; i++) { - if (element.getField(i) instanceof Date) { - dataMap.put(fieldNames.get(i), DateUtil.transformSqlDateToUtilDate((Date) element.getField(i))); - continue; - } - if (element.getField(i) instanceof Timestamp) { - dataMap.put(fieldNames.get(i), ((Timestamp) element.getField(i)).getTime()); - continue; - } - dataMap.put(fieldNames.get(i), element.getField(i)); - } - - String idFieldStr = ""; - if (null != ids) { - if (!usePosition) { - idFieldStr = ids.stream() - .map(filedName -> (String) filedName) - .map(filedName -> dataMap.get(filedName).toString()) - .collect(Collectors.joining(ID_VALUE_SPLIT)); - } else { - // compatible old version of generate doc's id - // index start at 1, - idFieldStr = ids.stream() - .map(index -> (Integer) index) - .filter(index -> index > 0 && index <= element.getArity()) - .map(index -> element.getField( index - 1).toString()) - .collect(Collectors.joining(ID_VALUE_SPLIT)); - } - } - - if (StringUtils.isEmpty(idFieldStr)) { - return Requests.indexRequest() - .index(index) - .type(type) - .source(dataMap); - } - - return Requests.indexRequest() - .index(index) - .type(type) - .id(idFieldStr) - .source(dataMap); - } -} diff --git a/elasticsearch6/elasticsearch6-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/ElasticsearchSink.java b/elasticsearch6/elasticsearch6-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/ElasticsearchSink.java deleted file mode 100644 index dd29f2ed8..000000000 --- a/elasticsearch6/elasticsearch6-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/ElasticsearchSink.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.elasticsearch; - -import com.dtstack.flink.sql.table.AbstractTargetTableInfo; -import com.google.common.base.Preconditions; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.api.java.typeutils.TupleTypeInfo; -import org.apache.flink.streaming.api.datastream.DataStream; -import org.apache.flink.streaming.api.datastream.DataStreamSink; -import org.apache.flink.streaming.api.functions.sink.RichSinkFunction; -import org.apache.flink.table.sinks.RetractStreamTableSink; -import org.apache.flink.table.sinks.TableSink; -import org.apache.flink.types.Row; - -import com.dtstack.flink.sql.sink.IStreamSinkGener; -import com.dtstack.flink.sql.sink.elasticsearch.table.ElasticsearchTableInfo; -import com.google.common.collect.Maps; -import org.apache.commons.lang.StringUtils; -import org.apache.http.HttpHost; - -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.stream.Collectors; - -/** - * @author yinxi - * @date 2020/1/9 - 15:08 - */ -public class ElasticsearchSink implements RetractStreamTableSink, IStreamSinkGener { - - private final int ES_DEFAULT_PORT = 9200; - private final String ES_DEFAULT_SCHEMA = "http"; - - private String clusterName; - - private int bulkFlushMaxActions = 1; - - private List esAddressList; - - private String index = ""; - - private String type = ""; - - private List ids; - - // true means generation doc's id by position "1[,1]" - private boolean usePosition = false; - - protected String[] fieldNames; - - protected String[] columnTypes; - - private TypeInformation[] fieldTypes; - - private int parallelism = 1; - - protected String registerTableName; - - private ElasticsearchTableInfo esTableInfo; - - - @Override - public TableSink> configure(String[] fieldNames, TypeInformation[] fieldTypes) { - this.fieldNames = fieldNames; - this.fieldTypes = fieldTypes; - return this; - } - - @Override - public TupleTypeInfo> getOutputType() { - return new TupleTypeInfo(org.apache.flink.table.api.Types.BOOLEAN(), getRecordType()); - } - - @Override - public TypeInformation getRecordType() { - return new RowTypeInfo(fieldTypes, fieldNames); - } - - @Override - public String[] getFieldNames() { - return fieldNames; - } - - @Override - public TypeInformation[] getFieldTypes() { - return fieldTypes; - } - - - private RichSinkFunction createEsSinkFunction() { - - // check whether id fields is exists in columns if not use position to generate doc's id - if (!usePosition - && ids != null - && ids.size() != 0) { - List filedNamesLists = Arrays.asList(fieldNames); - Preconditions.checkState(filedNamesLists.containsAll(ids), "elasticsearch6 type of id %s is should be exists in columns %s.", ids, filedNamesLists); - } - CustomerSinkFunc customerSinkFunc = new CustomerSinkFunc(index, type, Arrays.asList(fieldNames), Arrays.asList(columnTypes), ids, usePosition); - - Map userConfig = Maps.newHashMap(); - userConfig.put("cluster.name", clusterName); - // This instructs the sink to emit after every element, otherwise they would be buffered - userConfig.put(org.apache.flink.streaming.connectors.elasticsearch6.ElasticsearchSink.CONFIG_KEY_BULK_FLUSH_MAX_ACTIONS, "" + bulkFlushMaxActions); - - List transports = esAddressList.stream() - .map(address -> address.split(":")) - .map(addressArray -> { - String host = addressArray[0].trim(); - int port = addressArray.length > 1 ? Integer.valueOf(addressArray[1].trim()) : ES_DEFAULT_PORT; - return new HttpHost(host.trim(), port, ES_DEFAULT_SCHEMA); - }).collect(Collectors.toList()); - - - return new MetricElasticsearch6Sink(userConfig, transports, customerSinkFunc, esTableInfo); - } - - @Override - public void emitDataStream(DataStream> dataStream) { - consumeDataStream(dataStream); - } - - @Override - public DataStreamSink consumeDataStream(DataStream> dataStream) { - RichSinkFunction richSinkFunction = createEsSinkFunction(); - DataStreamSink streamSink = dataStream.addSink(richSinkFunction).name(registerTableName); - if (parallelism > 0) { - streamSink.setParallelism(parallelism); - } - return streamSink; - } - - @Override - public ElasticsearchSink genStreamSink(AbstractTargetTableInfo targetTableInfo) { - esTableInfo = (ElasticsearchTableInfo) targetTableInfo; - clusterName = esTableInfo.getClusterName(); - index = esTableInfo.getIndex(); - type = esTableInfo.getEsType(); - columnTypes = esTableInfo.getFieldTypes(); - esAddressList = Arrays.asList(esTableInfo.getAddress().split(",")); - String id = esTableInfo.getId(); - registerTableName = esTableInfo.getName(); - parallelism = Objects.isNull(esTableInfo.getParallelism()) ? parallelism : esTableInfo.getParallelism(); - - // check mode of generate doc's id - if (!StringUtils.isEmpty(id)) { - if (!Es6Util.checkWhetherUsePosition(id)) { - ids = Arrays.stream(StringUtils.split(id, ",")).map(String::valueOf).collect(Collectors.toList()); - } else { - //compatible old version of generate doc' id - usePosition = true; - ids = Arrays.stream(StringUtils.split(id, ",")).map(Integer::valueOf).collect(Collectors.toList()); - } - } - return this; - } -} diff --git a/elasticsearch6/elasticsearch6-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/Es6Util.java b/elasticsearch6/elasticsearch6-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/Es6Util.java deleted file mode 100644 index 5d0d2deaa..000000000 --- a/elasticsearch6/elasticsearch6-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/Es6Util.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.elasticsearch; - -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.math.NumberUtils; -import org.apache.flink.types.Row; -import org.apache.flink.util.Preconditions; - -import org.apache.flink.shaded.guava18.com.google.common.collect.Maps; - -import com.dtstack.flink.sql.util.DtStringUtil; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicBoolean; - -/** - * @author yinxi - * @date 2020/1/9 - 15:08 - */ -public class Es6Util { - - public static Map rowToJsonMap(Row row, List fields, List types) { - Preconditions.checkArgument(row.getArity() == fields.size()); - Map jsonMap = Maps.newHashMap(); - int i = 0; - for(; i < fields.size(); ++i) { - String field = fields.get(i); - String[] parts = field.split("\\."); - Map currMap = jsonMap; - for(int j = 0; j < parts.length - 1; ++j) { - String key = parts[j]; - if(currMap.get(key) == null) { - HashMap hashMap = Maps.newHashMap(); - currMap.put(key, hashMap); - } - currMap = (Map) currMap.get(key); - } - String key = parts[parts.length - 1]; - Object col = row.getField(i); - if(col != null) { - Object value = DtStringUtil.col2string(col, types.get(i)); - currMap.put(key, value); - } - - } - - return jsonMap; - } - - /** - * check whether use position to generation doc's id - * eg : |1,2,3 -> true - * |id,name,addr -> false - * @param ids - * @return - */ - public static boolean checkWhetherUsePosition(String ids) { - boolean flag = true; - for( String id : StringUtils.split(ids, ",")) { - if (!NumberUtils.isNumber(id)) { - flag= false; - break; - } - } - return flag; - } - -} diff --git a/elasticsearch6/elasticsearch6-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/ExtendEs6ApiCallBridge.java b/elasticsearch6/elasticsearch6-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/ExtendEs6ApiCallBridge.java deleted file mode 100644 index 5f9cf2fff..000000000 --- a/elasticsearch6/elasticsearch6-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/ExtendEs6ApiCallBridge.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.elasticsearch; - -import org.apache.flink.streaming.connectors.elasticsearch.ElasticsearchApiCallBridge; -import org.apache.flink.streaming.connectors.elasticsearch.ElasticsearchSinkBase; -import org.apache.flink.util.Preconditions; - -import com.dtstack.flink.sql.sink.elasticsearch.table.ElasticsearchTableInfo; -import org.apache.http.HttpHost; -import org.apache.http.auth.AuthScope; -import org.apache.http.auth.UsernamePasswordCredentials; -import org.apache.http.client.CredentialsProvider; -import org.apache.http.impl.client.BasicCredentialsProvider; -import org.elasticsearch.action.bulk.BackoffPolicy; -import org.elasticsearch.action.bulk.BulkItemResponse; -import org.elasticsearch.action.bulk.BulkProcessor; -import org.elasticsearch.client.RequestOptions; -import org.elasticsearch.client.RestClient; -import org.elasticsearch.client.RestClientBuilder; -import org.elasticsearch.client.RestHighLevelClient; -import org.elasticsearch.common.unit.TimeValue; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.annotation.Nullable; - -import java.io.IOException; -import java.util.List; -import java.util.Map; - -/** - * @author yinxi - * @date 2020/1/9 - 15:09 - */ -public class ExtendEs6ApiCallBridge implements ElasticsearchApiCallBridge { - - private static final Logger LOG = LoggerFactory.getLogger(ExtendEs6ApiCallBridge.class); - - private final List HttpAddresses; - - protected ElasticsearchTableInfo es6TableInfo; - - public ExtendEs6ApiCallBridge(List httpAddresses, ElasticsearchTableInfo es6TableInfo) { - Preconditions.checkArgument(httpAddresses != null && !httpAddresses.isEmpty()); - this.HttpAddresses = httpAddresses; - this.es6TableInfo = es6TableInfo; - } - - @Override - public RestHighLevelClient createClient(Map clientConfig) { - - RestClientBuilder restClientBuilder = RestClient.builder(HttpAddresses.toArray(new HttpHost[HttpAddresses.size()])); - if (es6TableInfo.isAuthMesh()) { - // 进行用户和密码认证 - final CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); - credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(es6TableInfo.getUserName(), es6TableInfo.getPassword())); - restClientBuilder.setHttpClientConfigCallback(httpAsyncClientBuilder -> - httpAsyncClientBuilder.setDefaultCredentialsProvider(credentialsProvider)); - } - - RestHighLevelClient rhlClient = new RestHighLevelClient(restClientBuilder); - - if (LOG.isInfoEnabled()) { - LOG.info("Pinging Elasticsearch cluster via hosts {} ...", HttpAddresses); - } - - try{ - if (!rhlClient.ping(RequestOptions.DEFAULT)) { - throw new RuntimeException("There are no reachable Elasticsearch nodes!"); - } - } catch (IOException e){ - LOG.warn("", e); - } - - - if (LOG.isInfoEnabled()) { - LOG.info("Created Elasticsearch RestHighLevelClient connected to {}", HttpAddresses.toString()); - } - - return rhlClient; - } - - @Override - public BulkProcessor.Builder createBulkProcessorBuilder(RestHighLevelClient client, BulkProcessor.Listener listener) { - return BulkProcessor.builder(client::bulkAsync, listener); - } - - @Override - public Throwable extractFailureCauseFromBulkItemResponse(BulkItemResponse bulkItemResponse) { - if (!bulkItemResponse.isFailed()) { - return null; - } else { - return bulkItemResponse.getFailure().getCause(); - } - } - - @Override - public void configureBulkProcessorBackoff( - BulkProcessor.Builder builder, - @Nullable ElasticsearchSinkBase.BulkFlushBackoffPolicy flushBackoffPolicy) { - - BackoffPolicy backoffPolicy; - if (flushBackoffPolicy != null) { - switch (flushBackoffPolicy.getBackoffType()) { - case CONSTANT: - backoffPolicy = BackoffPolicy.constantBackoff( - new TimeValue(flushBackoffPolicy.getDelayMillis()), - flushBackoffPolicy.getMaxRetryCount()); - break; - case EXPONENTIAL: - default: - backoffPolicy = BackoffPolicy.exponentialBackoff( - new TimeValue(flushBackoffPolicy.getDelayMillis()), - flushBackoffPolicy.getMaxRetryCount()); - } - } else { - backoffPolicy = BackoffPolicy.noBackoff(); - } - - builder.setBackoffPolicy(backoffPolicy); - } - -} diff --git a/elasticsearch6/elasticsearch6-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/MetricElasticsearch6Sink.java b/elasticsearch6/elasticsearch6-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/MetricElasticsearch6Sink.java deleted file mode 100644 index b17b1243a..000000000 --- a/elasticsearch6/elasticsearch6-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/MetricElasticsearch6Sink.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.elasticsearch; - -import org.apache.flink.configuration.Configuration; -import org.apache.flink.metrics.Counter; -import org.apache.flink.metrics.Meter; -import org.apache.flink.metrics.MeterView; -import org.apache.flink.streaming.connectors.elasticsearch.ElasticsearchSinkBase; -import org.apache.flink.streaming.connectors.elasticsearch.ElasticsearchSinkFunction; -import org.apache.flink.streaming.connectors.elasticsearch.util.NoOpFailureHandler; - -import com.dtstack.flink.sql.metric.MetricConstant; -import com.dtstack.flink.sql.sink.elasticsearch.table.ElasticsearchTableInfo; -import org.elasticsearch.client.RestHighLevelClient; - -import java.util.List; -import java.util.Map; - -/** - * @author yinxi - * @date 2020/1/9 - 15:05 - */ -public class MetricElasticsearch6Sink extends ElasticsearchSinkBase { - - protected CustomerSinkFunc customerSinkFunc; - - protected transient Meter outRecordsRate; - - protected Map userConfig; - - - public MetricElasticsearch6Sink(Map userConfig, List transportAddresses, - ElasticsearchSinkFunction elasticsearchSinkFunction, - ElasticsearchTableInfo es6TableInfo) { - super(new ExtendEs6ApiCallBridge(transportAddresses, es6TableInfo), userConfig, elasticsearchSinkFunction, new NoOpFailureHandler()); - this.customerSinkFunc = (CustomerSinkFunc) elasticsearchSinkFunction; - this.userConfig = userConfig; - } - - @Override - public void open(Configuration parameters) throws Exception { - super.open(parameters); - initMetric(); - } - - - public void initMetric() { - Counter counter = getRuntimeContext().getMetricGroup().counter(MetricConstant.DT_NUM_RECORDS_OUT); - Counter outDirtyRecords = getRuntimeContext().getMetricGroup().counter(MetricConstant.DT_NUM_DIRTY_RECORDS_OUT); - - customerSinkFunc.setOutRecords(counter); - customerSinkFunc.setOutDirtyRecords(outDirtyRecords); - outRecordsRate = getRuntimeContext().getMetricGroup().meter(MetricConstant.DT_NUM_RECORDS_OUT_RATE, new MeterView(counter, 20)); - } -} - diff --git a/elasticsearch6/elasticsearch6-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/table/ElasticsearchSinkParser.java b/elasticsearch6/elasticsearch6-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/table/ElasticsearchSinkParser.java deleted file mode 100644 index 062935bf4..000000000 --- a/elasticsearch6/elasticsearch6-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/table/ElasticsearchSinkParser.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.elasticsearch.table; - -import com.dtstack.flink.sql.table.AbstractTableInfo; -import com.dtstack.flink.sql.table.AbstractTableParser; -import com.dtstack.flink.sql.util.MathUtil; -import org.apache.commons.lang3.StringUtils; - -import java.util.Map; - -/** - * @author yinxi - * @date 2020/1/9 - 15:06 - */ -public class ElasticsearchSinkParser extends AbstractTableParser { - - private static final String KEY_ES6_ADDRESS = "address"; - - private static final String KEY_ES6_CLUSTER = "cluster"; - - private static final String KEY_ES6_INDEX = "index"; - - private static final String KEY_ES6_TYPE = "estype"; - - private static final String KEY_ES6_ID_FIELD_INDEX_LIST = "id"; - - private static final String KEY_ES6_AUTHMESH = "authMesh"; - - private static final String KEY_ES6_USERNAME = "userName"; - - private static final String KEY_ES6_PASSWORD = "password"; - - private static final String KEY_TRUE = "true"; - - private static final String KEY_ES6_PARALLELISM = "parallelism"; - - @Override - protected boolean fieldNameNeedsUpperCase() { - return false; - } - - @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { - ElasticsearchTableInfo elasticsearchTableInfo = new ElasticsearchTableInfo(); - elasticsearchTableInfo.setName(tableName); - parseFieldsInfo(fieldsInfo, elasticsearchTableInfo); - elasticsearchTableInfo.setAddress((String) props.get(KEY_ES6_ADDRESS.toLowerCase())); - elasticsearchTableInfo.setClusterName((String) props.get(KEY_ES6_CLUSTER.toLowerCase())); - elasticsearchTableInfo.setId((String) props.get(KEY_ES6_ID_FIELD_INDEX_LIST.toLowerCase())); - elasticsearchTableInfo.setIndex((String) props.get(KEY_ES6_INDEX.toLowerCase())); - elasticsearchTableInfo.setEsType((String) props.get(KEY_ES6_TYPE.toLowerCase())); - elasticsearchTableInfo.setParallelism(MathUtil.getIntegerVal(props.getOrDefault(KEY_ES6_PARALLELISM.toLowerCase(), 1))); - - String authMeshStr = (String) props.get(KEY_ES6_AUTHMESH.toLowerCase()); - if (authMeshStr != null && StringUtils.equalsIgnoreCase(KEY_TRUE, authMeshStr)) { - elasticsearchTableInfo.setAuthMesh(MathUtil.getBoolean(authMeshStr)); - elasticsearchTableInfo.setUserName(MathUtil.getString(props.get(KEY_ES6_USERNAME.toLowerCase()))); - elasticsearchTableInfo.setPassword(MathUtil.getString(props.get(KEY_ES6_PASSWORD.toLowerCase()))); - } - elasticsearchTableInfo.check(); - return elasticsearchTableInfo; - } -} diff --git a/elasticsearch6/elasticsearch6-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/table/ElasticsearchTableInfo.java b/elasticsearch6/elasticsearch6-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/table/ElasticsearchTableInfo.java deleted file mode 100644 index dc9590756..000000000 --- a/elasticsearch6/elasticsearch6-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/table/ElasticsearchTableInfo.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.elasticsearch.table; - -import com.dtstack.flink.sql.table.AbstractTargetTableInfo; -import com.google.common.base.Preconditions; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang3.math.NumberUtils; - -import java.util.Arrays; - -/** - * @author yinxi - * @date 2020/1/9 - 15:06 - */ -public class ElasticsearchTableInfo extends AbstractTargetTableInfo { - - private static final String CURR_TYPE = "elasticsearch6"; - - private String address; - - private String index; - - private String id; - - private String clusterName; - - private String esType; - - private boolean authMesh = false; - - private String userName; - - private String password; - - public String getEsType() { - return esType; - } - - public void setEsType(String esType) { - this.esType = esType; - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getAddress() { - return address; - } - - public void setAddress(String address) { - this.address = address; - } - - public String getIndex() { - return index; - } - - public void setIndex(String index) { - this.index = index; - } - - @Override - public String getType() { - //return super.getType().toLowerCase() + TARGET_SUFFIX; - return super.getType().toLowerCase(); - } - - public String getClusterName() { - return clusterName; - } - - public void setClusterName(String clusterName) { - this.clusterName = clusterName; - } - - public boolean isAuthMesh() { - return authMesh; - } - - public void setAuthMesh(boolean authMesh) { - this.authMesh = authMesh; - } - - public String getUserName() { - return userName; - } - - public void setUserName(String userName) { - this.userName = userName; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public ElasticsearchTableInfo() { - setType(CURR_TYPE); - } - - @Override - public boolean check() { - Preconditions.checkNotNull(address, "elasticsearch6 type of address is required"); - Preconditions.checkNotNull(index, "elasticsearch6 type of index is required"); - Preconditions.checkNotNull(esType, "elasticsearch6 type of type is required"); - Preconditions.checkNotNull(clusterName, "elasticsearch6 type of clusterName is required"); - - if (isAuthMesh()) { - Preconditions.checkNotNull(userName, "elasticsearch6 type of userName is required"); - Preconditions.checkNotNull(password, "elasticsearch6 type of password is required"); - } - - return true; - } - -} - diff --git a/elasticsearch6/elasticsearch6-sink/src/test/java/com/dtstack/flink/sql/sink/elasticsearch/CustomerSinkFuncTest.java b/elasticsearch6/elasticsearch6-sink/src/test/java/com/dtstack/flink/sql/sink/elasticsearch/CustomerSinkFuncTest.java deleted file mode 100644 index f760cbc8e..000000000 --- a/elasticsearch6/elasticsearch6-sink/src/test/java/com/dtstack/flink/sql/sink/elasticsearch/CustomerSinkFuncTest.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.dtstack.flink.sql.sink.elasticsearch; - -import org.apache.flink.api.common.functions.RuntimeContext; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.metrics.Counter; -import org.apache.flink.streaming.connectors.elasticsearch.RequestIndexer; -import org.apache.flink.types.Row; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -/** - * Company: www.dtstack.com - * - * @author zhufeng - * @date 2020-06-23 - */ -public class CustomerSinkFuncTest { - private CustomerSinkFunc customerSinkFunc; - @Mock - RuntimeContext ctx; - @Mock - RequestIndexer indexer; - @Mock - Counter outRecords; - String index; - String type; - List fieldNames = Collections.singletonList("name.pv"); - List fieldTypes = Arrays.asList("varchar", "varchar"); - List idFieldIndexes = Collections.singletonList(1); - Tuple2 tuple2 = new Tuple2<>(); - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - customerSinkFunc = new CustomerSinkFunc(index, type, fieldNames, fieldTypes, idFieldIndexes, true); - customerSinkFunc.setOutRecords(outRecords); - tuple2.setField(true, 0); - Row row = new Row(1); - row.setField(0, 1); - tuple2.setField(row, 1); - } - - //测试CustomerSinkFunc中的process和createIndexRequest方法 - @Test - public void processAndcreateIndexRequestTest() { - customerSinkFunc.process(tuple2, ctx, indexer); - tuple2.setField(false, 0); - customerSinkFunc.process(tuple2, ctx, indexer); - } -} diff --git a/elasticsearch6/elasticsearch6-sink/src/test/java/com/dtstack/flink/sql/sink/elasticsearch/ElasticsearchSinkTest.java b/elasticsearch6/elasticsearch6-sink/src/test/java/com/dtstack/flink/sql/sink/elasticsearch/ElasticsearchSinkTest.java deleted file mode 100644 index e46c051ba..000000000 --- a/elasticsearch6/elasticsearch6-sink/src/test/java/com/dtstack/flink/sql/sink/elasticsearch/ElasticsearchSinkTest.java +++ /dev/null @@ -1,90 +0,0 @@ -package com.dtstack.flink.sql.sink.elasticsearch; - -import com.dtstack.flink.sql.sink.elasticsearch.table.ElasticsearchTableInfo; -import com.dtstack.flink.sql.table.AbstractTableInfo; -import com.dtstack.flink.sql.table.AbstractTableParser; -import com.dtstack.flink.sql.util.MathUtil; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.junit.Before; -import org.junit.Test; -import org.mockito.MockitoAnnotations; -import org.mockito.Spy; - -import java.util.HashMap; -import java.util.Map; - -/** - * Company: www.dtstack.com - * - * @author zhufeng - * @date 2020-06-23 - */ -public class ElasticsearchSinkTest { - ElasticsearchTableInfo elasticsearchTableInfo = new ElasticsearchTableInfo(); - @Spy - ElasticsearchSink elasticsearchSink; - String[] fieldNames; - TypeInformation[] fieldTypes; - - - @Before - public void setUp() { - String tableName = "MyResult"; - String fieldsInfo = "pv varchar, channel varchar"; - Map props = new HashMap<>(); - props.put("cluster", "docker-cluster"); - props.put("password", "abc123"); - props.put("address", "172.16.8.193:9200"); - props.put("parallelism", "1"); - props.put("index", "myresult"); - props.put("updatemode", "append"); - props.put("id", "1"); - props.put("type", "elasticsearch"); - props.put("estype", "elasticsearch"); - props.put("authmesh", "true"); - props.put("username", "elastic"); - AbstractTableParser tableParser = new AbstractTableParser() { - @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) throws Exception { - return null; - } - }; - elasticsearchTableInfo.setName(tableName); - tableParser.parseFieldsInfo(fieldsInfo, elasticsearchTableInfo); - elasticsearchTableInfo.setAddress((String) props.get("address")); - elasticsearchTableInfo.setClusterName((String) props.get("cluster")); - elasticsearchTableInfo.setId((String) props.get("id")); - elasticsearchTableInfo.setIndex((String) props.get("index")); - elasticsearchTableInfo.setEsType((String) props.get("estype")); - String authMeshStr = (String) props.get("authmesh"); - if (authMeshStr != null & "true".equals(authMeshStr)) { - elasticsearchTableInfo.setAuthMesh(MathUtil.getBoolean(authMeshStr)); - elasticsearchTableInfo.setUserName(MathUtil.getString(props.get("username"))); - elasticsearchTableInfo.setPassword(MathUtil.getString(props.get("password"))); - } - MockitoAnnotations.initMocks(this); - elasticsearchSink.configure(fieldNames, fieldTypes); - } - - @Test - public void genStreamSinkTest() { - elasticsearchSink.genStreamSink(elasticsearchTableInfo); - } - - @Test - public void configureTest() { - elasticsearchSink.configure(fieldNames, fieldTypes); - } - - @Test - public void getFieldNamesTest() { - elasticsearchSink.getFieldNames(); - } - - @Test - public void getFieldTypesTest() { - elasticsearchSink.getFieldTypes(); - } - - -} diff --git a/elasticsearch6/elasticsearch6-sink/src/test/java/com/dtstack/flink/sql/sink/elasticsearch/Es6UtilTest.java b/elasticsearch6/elasticsearch6-sink/src/test/java/com/dtstack/flink/sql/sink/elasticsearch/Es6UtilTest.java deleted file mode 100644 index 26ee3b9ce..000000000 --- a/elasticsearch6/elasticsearch6-sink/src/test/java/com/dtstack/flink/sql/sink/elasticsearch/Es6UtilTest.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.dtstack.flink.sql.sink.elasticsearch; - -import junit.framework.Assert; -import org.apache.flink.types.Row; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import org.junit.Test; - - -/** - * Company: www.dtstack.com - * - * @author zhufeng - * @date 2020-06-23 - */ -public class Es6UtilTest { - List fieldNames = Collections.singletonList("name.pv"); - List fieldTypes = Arrays.asList("varchar", "varchar"); - Row row = new Row(1); - - @Test - public void rowToJsonMapTest() { - boolean test = false; - if (Es6Util.rowToJsonMap(row, fieldNames, fieldTypes).toString().equals("{name={}}")) { - test = true; - } - Assert.assertTrue(test); - } -} diff --git a/elasticsearch6/elasticsearch6-sink/src/test/java/com/dtstack/flink/sql/sink/elasticsearch/ExtendES6ApiCallBridgeTest.java b/elasticsearch6/elasticsearch6-sink/src/test/java/com/dtstack/flink/sql/sink/elasticsearch/ExtendES6ApiCallBridgeTest.java deleted file mode 100644 index 09d41c334..000000000 --- a/elasticsearch6/elasticsearch6-sink/src/test/java/com/dtstack/flink/sql/sink/elasticsearch/ExtendES6ApiCallBridgeTest.java +++ /dev/null @@ -1,108 +0,0 @@ -package com.dtstack.flink.sql.sink.elasticsearch; - -import com.dtstack.flink.sql.sink.elasticsearch.table.ElasticsearchTableInfo; -import com.dtstack.flink.sql.table.AbstractTableInfo; -import com.dtstack.flink.sql.table.AbstractTableParser; -import com.dtstack.flink.sql.util.MathUtil; -import org.apache.flink.streaming.connectors.elasticsearch.ElasticsearchSinkBase; -import org.apache.http.HttpHost; -import org.elasticsearch.action.bulk.BulkItemResponse; -import org.elasticsearch.action.bulk.BulkProcessor; -import org.elasticsearch.client.RestHighLevelClient; -import org.elasticsearch.client.transport.TransportClient; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - - -import java.net.InetSocketAddress; -import java.util.*; - -import static org.apache.flink.streaming.connectors.elasticsearch.ElasticsearchSinkBase.FlushBackoffType.CONSTANT; -/** - * Company: www.dtstack.com - * - * @author zhufeng - * @date 2020-06-23 - */ -public class ExtendES6ApiCallBridgeTest { - List addresses = Collections.singletonList(new HttpHost("172.16.8.193", 9200)); - Map clientConfig = new HashMap<>(); - ExtendEs6ApiCallBridge callBridge; - @Mock - BulkProcessor.Builder builder; - @Mock - BulkItemResponse bulkItemResponse; - @Mock - RestHighLevelClient client; - @Mock - BulkProcessor.Listener listener; - ElasticsearchSinkBase.BulkFlushBackoffPolicy flushBackoffPolicy = new ElasticsearchSinkBase.BulkFlushBackoffPolicy(); - - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - String tableName = "MyResult"; - String fieldsInfo = "pv varchar, channel varchar"; - Map props = new HashMap<>(); - props.put("cluster", "docker-cluster"); - props.put("password", "abc123"); - props.put("address", "172.16.8.193:9200"); - props.put("parallelism", "1"); - props.put("index", "myresult"); - props.put("updatemode", "append"); - props.put("id", "1"); - props.put("type", "elasticsearch"); - props.put("estype", "elasticsearch"); - props.put("authmesh", "true"); - props.put("username", "elastic"); - AbstractTableParser tableParser = new AbstractTableParser() { - @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) throws Exception { - return null; - } - }; - ElasticsearchTableInfo elasticsearchTableInfo = new ElasticsearchTableInfo(); - elasticsearchTableInfo.setName(tableName); - tableParser.parseFieldsInfo(fieldsInfo, elasticsearchTableInfo); - elasticsearchTableInfo.setAddress((String) props.get("address")); - elasticsearchTableInfo.setClusterName((String) props.get("cluster")); - elasticsearchTableInfo.setId((String) props.get("id")); - elasticsearchTableInfo.setIndex((String) props.get("index")); - elasticsearchTableInfo.setEsType((String) props.get("estype")); - String authMeshStr = (String) props.get("authmesh"); - if (authMeshStr != null & "true".equals(authMeshStr)) { - elasticsearchTableInfo.setAuthMesh(MathUtil.getBoolean(authMeshStr)); - elasticsearchTableInfo.setUserName(MathUtil.getString(props.get("username"))); - elasticsearchTableInfo.setPassword(MathUtil.getString(props.get("password"))); - } - callBridge = new ExtendEs6ApiCallBridge(addresses, elasticsearchTableInfo); - } - - //暂时没有ES环境 - @Test - public void createClientTest() { - clientConfig.put("cluster.name", "docker-cluster"); - clientConfig.put("xpack.security.user", "elastic:abc123"); - callBridge.createClient(clientConfig); - } - - @Test - public void configureBulkProcessorBackoffTest() { - callBridge.configureBulkProcessorBackoff(builder, flushBackoffPolicy); - flushBackoffPolicy.setBackoffType(CONSTANT); - callBridge.configureBulkProcessorBackoff(builder, flushBackoffPolicy); - } - - @Test - public void extractFailureCauseFromBulkItemResponseTest() { - callBridge.extractFailureCauseFromBulkItemResponse(bulkItemResponse); - } - - @Test - public void createBulkProcessorBuilderTest() { - callBridge.createBulkProcessorBuilder(client, listener); - } -} diff --git a/elasticsearch6/elasticsearch6-sink/src/test/java/com/dtstack/flink/sql/sink/elasticsearch/MetricElasticsearch6SinkTest.java b/elasticsearch6/elasticsearch6-sink/src/test/java/com/dtstack/flink/sql/sink/elasticsearch/MetricElasticsearch6SinkTest.java deleted file mode 100644 index eb05a643b..000000000 --- a/elasticsearch6/elasticsearch6-sink/src/test/java/com/dtstack/flink/sql/sink/elasticsearch/MetricElasticsearch6SinkTest.java +++ /dev/null @@ -1,85 +0,0 @@ -package com.dtstack.flink.sql.sink.elasticsearch; - -import com.dtstack.flink.sql.sink.elasticsearch.table.ElasticsearchTableInfo; -import com.dtstack.flink.sql.table.AbstractTableInfo; -import com.dtstack.flink.sql.table.AbstractTableParser; -import com.dtstack.flink.sql.util.MathUtil; -import org.apache.flink.streaming.connectors.elasticsearch.ElasticsearchSinkBase; -import org.apache.flink.streaming.connectors.elasticsearch.ElasticsearchSinkFunction; -import org.apache.http.HttpHost; -import org.junit.Before; -import org.junit.Test; -import org.mockito.MockitoAnnotations; - -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static org.mockito.Mockito.mock; -/** - * Company: www.dtstack.com - * - * @author zhufeng - * @date 2020-06-23 - */ - -public class MetricElasticsearch6SinkTest { - List addresses = Collections.singletonList(new HttpHost("172.16.8.193", 9200)); - ElasticsearchSinkBase.BulkFlushBackoffPolicy flushBackoffPolicy = new ElasticsearchSinkBase.BulkFlushBackoffPolicy(); - Map userConfig = new HashMap(); - MetricElasticsearch6Sink sink; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - String tableName = "MyResult"; - String fieldsInfo = "pv varchar, channel varchar"; - Map props = new HashMap<>(); - props.put("cluster", "docker-cluster"); - props.put("password", "abc123"); - props.put("address", "172.16.8.193:9200"); - props.put("parallelism", "1"); - props.put("index", "myresult"); - props.put("updatemode", "append"); - props.put("id", "1"); - props.put("type", "elasticsearch"); - props.put("estype", "elasticsearch"); - props.put("authmesh", "true"); - props.put("username", "elastic"); - AbstractTableParser tableParser = new AbstractTableParser() { - @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) throws Exception { - return null; - } - }; - ElasticsearchTableInfo elasticsearchTableInfo = new ElasticsearchTableInfo(); - elasticsearchTableInfo.setName(tableName); - tableParser.parseFieldsInfo(fieldsInfo, elasticsearchTableInfo); - elasticsearchTableInfo.setAddress((String) props.get("address")); - elasticsearchTableInfo.setClusterName((String) props.get("cluster")); - elasticsearchTableInfo.setId((String) props.get("id")); - elasticsearchTableInfo.setIndex((String) props.get("index")); - elasticsearchTableInfo.setEsType((String) props.get("estype")); - String authMeshStr = (String) props.get("authmesh"); - if (authMeshStr != null & "true".equals(authMeshStr)) { - elasticsearchTableInfo.setAuthMesh(MathUtil.getBoolean(authMeshStr)); - elasticsearchTableInfo.setUserName(MathUtil.getString(props.get("username"))); - elasticsearchTableInfo.setPassword(MathUtil.getString(props.get("password"))); - } - ElasticsearchSinkFunction elasticsearchSinkFunction = mock(ElasticsearchSinkFunction.class); - try { - sink = new MetricElasticsearch6Sink(userConfig, addresses, elasticsearchSinkFunction, elasticsearchTableInfo); - } catch (Exception ignored) { - } - - } - - @Test - public void Test() { - - } -} - - diff --git a/elasticsearch6/elasticsearch6-sink/src/test/java/com/dtstack/flink/sql/sink/elasticsearch/table/ElasticsearchSinkParserTest.java b/elasticsearch6/elasticsearch6-sink/src/test/java/com/dtstack/flink/sql/sink/elasticsearch/table/ElasticsearchSinkParserTest.java deleted file mode 100644 index 3563d9536..000000000 --- a/elasticsearch6/elasticsearch6-sink/src/test/java/com/dtstack/flink/sql/sink/elasticsearch/table/ElasticsearchSinkParserTest.java +++ /dev/null @@ -1,130 +0,0 @@ -package com.dtstack.flink.sql.sink.elasticsearch.table; - -import com.dtstack.flink.sql.table.AbstractTableInfo; -import com.dtstack.flink.sql.table.AbstractTableParser; -import com.dtstack.flink.sql.util.MathUtil; -import org.junit.Before; -import org.junit.Test; -import org.mockito.MockitoAnnotations; -import org.mockito.Spy; - -import java.beans.Introspector; -import java.beans.PropertyDescriptor; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static org.junit.Assert.assertFalse; - -/** - * Company: www.dtstack.com - * - * @author zhufeng - * @date 2020-06-22 - */ -public class ElasticsearchSinkParserTest { - @Spy - ElasticsearchSinkParser elasticsearchSinkParser; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - } - - //ElasticsearchSinkParser中的fieldNameNeedsUpperCase方法 -// @Test - public void fieldNameNeedsUpperCaseTest() { - assertFalse(elasticsearchSinkParser.fieldNameNeedsUpperCase()); - } - - - //getTableInfo方法,得到输入的表信息 -// @Test - public void getTableInfoTest() { - String tableName = "MyResult"; - String fieldsInfo = "pv varchar, channel varchar"; - Map props = new HashMap<>(); - props.put("cluster", "docker-cluster"); - props.put("password", "abc123"); - props.put("address", "172.16.8.193:9200"); - props.put("parallelism", "1"); - props.put("index", "myresult"); - props.put("updatemode", "append"); - props.put("id", "1"); - props.put("type", "elasticsearch"); - props.put("estype", "elasticsearch"); - props.put("authmesh", "true"); - props.put("username", "elastic"); - AbstractTableParser tableParser = new AbstractTableParser() { - @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) throws Exception { - return null; - } - }; - ElasticsearchTableInfo elasticsearchTableInfo = new ElasticsearchTableInfo(); - elasticsearchTableInfo.setName(tableName); - tableParser.parseFieldsInfo(fieldsInfo, elasticsearchTableInfo); - elasticsearchTableInfo.setAddress((String) props.get("address")); - elasticsearchTableInfo.setClusterName((String) props.get("cluster")); - elasticsearchTableInfo.setId((String) props.get("id")); - elasticsearchTableInfo.setIndex((String) props.get("index")); - elasticsearchTableInfo.setEsType((String) props.get("estype")); - String authMeshStr = (String) props.get("authmesh"); - if (authMeshStr != null & "true".equals(authMeshStr)) { - elasticsearchTableInfo.setAuthMesh(MathUtil.getBoolean(authMeshStr)); - elasticsearchTableInfo.setUserName(MathUtil.getString(props.get("username"))); - elasticsearchTableInfo.setPassword(MathUtil.getString(props.get("password"))); - } - String[] ignoreArr = {"fieldClasses", "fieldTypes", "fields"}; - assertTrue(compareFields(elasticsearchTableInfo, elasticsearchSinkParser.getTableInfo(tableName, fieldsInfo, props), ignoreArr)); - } - - private void assertTrue(Boolean compareFields) { - } - - //比较两个对象的值是不是相同 - public static Boolean compareFields(Object obj1, Object obj2, String[] ignoreArr) { - try { - Boolean checkIsSame = true; - List ignoreList = null; - if (ignoreArr != null && ignoreArr.length > 0) { - // array转化为list - ignoreList = Arrays.asList(ignoreArr); - } - if (obj1.getClass() == obj2.getClass()) {// 只有两个对象都是同一类型的才有可比性 - Class clazz = obj1.getClass(); - // 获取object的属性描述 - PropertyDescriptor[] pds = Introspector.getBeanInfo(clazz, Object.class).getPropertyDescriptors(); - for (PropertyDescriptor pd : pds) {// 这里就是所有的属性了 - String name = pd.getName();// 属性名 - if (ignoreList != null && ignoreList.contains(name)) {// 如果当前属性选择忽略比较,跳到下一次循环 - continue; - } - Method readMethod = pd.getReadMethod();// get方法 - // 在obj1上调用get方法等同于获得obj1的属性值 - Object o1 = readMethod.invoke(obj1); - // 在obj2上调用get方法等同于获得obj2的属性值 - Object o2 = readMethod.invoke(obj2); - if (o1 == null && o2 == null) { - continue; - } else if (o1 == null && o2 != null) { - checkIsSame = false; - continue; - } - if (!o1.equals(o2)) {// 比较这两个值是否相等,不等就可以放入map了 - checkIsSame = false; - } - } - } - return checkIsSame; - } catch (Exception e) { - e.printStackTrace(); - return null; - } - - } - - -} diff --git a/elasticsearch6/elasticsearch6-sink/src/test/java/com/dtstack/flink/sql/sink/elasticsearch/table/ElasticsearchTableInfoTest.java b/elasticsearch6/elasticsearch6-sink/src/test/java/com/dtstack/flink/sql/sink/elasticsearch/table/ElasticsearchTableInfoTest.java deleted file mode 100644 index 19aac0f6e..000000000 --- a/elasticsearch6/elasticsearch6-sink/src/test/java/com/dtstack/flink/sql/sink/elasticsearch/table/ElasticsearchTableInfoTest.java +++ /dev/null @@ -1,107 +0,0 @@ -package com.dtstack.flink.sql.sink.elasticsearch.table; - - -import org.junit.Before; -import org.junit.Test; -import org.mockito.MockitoAnnotations; -import org.mockito.Spy; - - -import java.beans.IntrospectionException; -import java.beans.PropertyDescriptor; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -import static junit.framework.Assert.assertTrue; -import static junit.framework.Assert.fail; -import static org.hamcrest.CoreMatchers.containsString; -import static org.junit.Assert.assertThat; - -/** - * Company: www.dtstack.com - * - * @author zhufeng - * @date 2020-06-22 - */ -public class ElasticsearchTableInfoTest { - - @Spy - ElasticsearchTableInfo tableInfo; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - } - - //通过反射去遍历ElasticsearchTable中所有的get set 方法 - @Test - public void getAndSetTest() throws InvocationTargetException, IntrospectionException, - InstantiationException, IllegalAccessException { - this.testGetAndSet(); - } - - //check()方法,通过捕捉特定的异常来断言 - @Test - public void checkTest() { - tableInfo.setAddress("address"); - tableInfo.setIndex("index"); - tableInfo.setEsType("estype"); - tableInfo.setClusterName("clustername"); - try { - tableInfo.check(); - } catch (NullPointerException e) { - assertThat(e.getMessage(), containsString("is required")); - } - - try { - tableInfo.setId("d"); - tableInfo.check(); - fail("id must be a numeric type"); - } catch (IllegalArgumentException e) { - assertThat(e.getMessage(), containsString("id must be a numeric type")); - } - tableInfo.setId("1"); - try { - tableInfo.setAuthMesh(true); - tableInfo.check(); - } catch (NullPointerException e) { - assertThat(e.getMessage(), containsString("is required")); - } - tableInfo.setUserName("name"); - tableInfo.setPassword("password"); - assertTrue(tableInfo.check()); - } - - - /** - * model的get和set方法 - * 1.子类返回对应的类型 - * 2.通过反射创建类的实例 - * 3.获取该类所有属性字段,遍历获取每个字段对应的get、set方法,并执行 - */ - private void testGetAndSet() throws IllegalAccessException, InstantiationException, IntrospectionException, - InvocationTargetException { - ElasticsearchTableInfo t = new ElasticsearchTableInfo(); - Class modelClass = t.getClass(); - Object obj = modelClass.newInstance(); - Field[] fields = modelClass.getDeclaredFields(); - for (Field f : fields) { - if (!f.getName().equals("CURR_TYPE")) { - if (f.getName().equals("aLike") - || f.isSynthetic()) { - continue; - } - - PropertyDescriptor pd = new PropertyDescriptor(f.getName(), modelClass); - Method get = pd.getReadMethod(); - Method set = pd.getWriteMethod(); - set.invoke(obj, get.invoke(obj)); - } - } - } - - -} - - diff --git a/elasticsearch6/pom.xml b/elasticsearch6/pom.xml deleted file mode 100644 index 4df6cc660..000000000 --- a/elasticsearch6/pom.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - flink.sql - com.dtstack.flink - 1.0-SNAPSHOT - - 4.0.0 - - sql.elasticsearch6 - pom - - - - 6.8.6 - - - - elasticsearch6-side - elasticsearch6-sink - - - - - - com.dtstack.flink - sql.core - 1.0-SNAPSHOT - provided - - - - - \ No newline at end of file diff --git a/elasticsearch7/elasticsearch7-side/elasticsearch7-all-side/pom.xml b/elasticsearch7/elasticsearch7-side/elasticsearch7-all-side/pom.xml deleted file mode 100644 index 3798168a3..000000000 --- a/elasticsearch7/elasticsearch7-side/elasticsearch7-all-side/pom.xml +++ /dev/null @@ -1,112 +0,0 @@ - - - - sql.side.elasticsearch7 - com.dtstack.flink - 1.0-SNAPSHOT - - 4.0.0 - - sql.side.all.elasticsearch7 - elasticsearch7-all-side - jar - - - 1.0-SNAPSHOT - - - - - - org.elasticsearch.client - elasticsearch-rest-high-level-client - ${elasticsearch.version} - - - - com.dtstack.flink - sql.side.elasticsearch7.core - ${sql.side.elasticsearch7.core.version} - - - - junit - junit - 4.12 - test - - - - - - - - org.apache.maven.plugins - maven-shade-plugin - 1.4 - - - package - - shade - - - false - - - - - - - - *:* - - META-INF/*.SF - META-INF/*.DSA - META-INF/*.RSA - - - - - - - - - - maven-antrun-plugin - 1.2 - - - copy-resources - - package - - run - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/elasticsearch7/elasticsearch7-side/elasticsearch7-all-side/src/main/java/com/dtstack/flink/sql/side/elasticsearch7/Elasticsearch7AllReqRow.java b/elasticsearch7/elasticsearch7-side/elasticsearch7-all-side/src/main/java/com/dtstack/flink/sql/side/elasticsearch7/Elasticsearch7AllReqRow.java deleted file mode 100644 index 8fc11f1c7..000000000 --- a/elasticsearch7/elasticsearch7-side/elasticsearch7-all-side/src/main/java/com/dtstack/flink/sql/side/elasticsearch7/Elasticsearch7AllReqRow.java +++ /dev/null @@ -1,260 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.elasticsearch7; - -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.BaseAllReqRow; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.elasticsearch7.table.Elasticsearch7SideTableInfo; -import com.dtstack.flink.sql.side.elasticsearch7.util.Es7Util; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.table.dataformat.BaseRow; -import org.apache.flink.table.dataformat.GenericRow; -import org.apache.flink.table.typeutils.TimeIndicatorTypeInfo; -import org.apache.flink.util.Collector; -import org.elasticsearch.action.search.SearchRequest; -import org.elasticsearch.action.search.SearchResponse; -import org.elasticsearch.client.RequestOptions; -import org.elasticsearch.client.RestHighLevelClient; -import org.elasticsearch.index.query.BoolQueryBuilder; -import org.elasticsearch.search.SearchHit; -import org.elasticsearch.search.builder.SearchSourceBuilder; -import org.elasticsearch.search.sort.SortOrder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.io.Serializable; -import java.sql.SQLException; -import java.sql.Timestamp; -import java.util.Calendar; -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicReference; - -/** - * @description: - * @program: flink.sql - * @author: lany - * @create: 2021/01/11 14:53 - */ -public class Elasticsearch7AllReqRow extends BaseAllReqRow implements Serializable { - - private static final Logger LOG = LoggerFactory.getLogger(Elasticsearch7AllReqRow.class); - - private static final int CONN_RETRY_NUM = 3; - private AtomicReference>>> cacheRef = new AtomicReference<>(); - private transient RestHighLevelClient rhlClient; - private SearchRequest searchRequest; - private BoolQueryBuilder boolQueryBuilder; - - public Elasticsearch7AllReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { - super(new Elasticsearch7AllSideInfo(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo)); - } - - @Override - public void flatMap(BaseRow value, Collector out) throws Exception { - GenericRow genericRow = (GenericRow) value; - List inputParams = Lists.newArrayList(); - for (Integer conValIndex : sideInfo.getEqualValIndex()) { - Object equalObj = genericRow.getField(conValIndex); - if (equalObj == null) { - sendOutputRow(value, null, out); - return; - } - inputParams.add(equalObj); - } - - String key = buildKey(inputParams); - List> cacheList = cacheRef.get().get(key); - if (CollectionUtils.isEmpty(cacheList)) { - sendOutputRow(value, null, out); - return; - } - - for (Map one: cacheList) { - sendOutputRow(value, one, out); - return; - } - - for (Map one : cacheList) { - sendOutputRow(value, one, out); - } - } - - @Override - protected void initCache() throws SQLException { - Map>> newCache = Maps.newConcurrentMap(); - cacheRef.set(newCache); - try { - // create search request and build where cause - searchRequest = Es7Util.setSearchRequest(sideInfo); - boolQueryBuilder = Es7Util.setPredicateclause(sideInfo); - loadData(newCache); - } catch (Exception e) { - LOG.error("", e); - throw new RuntimeException(e); - } - } - - @Override - protected void reloadCache() { - //reload cacheRef and replace to old cacheRef - Map>> newCache = Maps.newConcurrentMap(); - try { - loadData(newCache); - } catch (Exception e) { - LOG.error("", e); - throw new RuntimeException(e); - } - - cacheRef.set(newCache); - LOG.info("----- elasticsearch7 all cacheRef reload end:{}", Calendar.getInstance()); - } - - private void loadData(Map>> tmpCache) throws IOException { - Elasticsearch7SideTableInfo tableInfo = (Elasticsearch7SideTableInfo) sideInfo.getSideTableInfo(); - - try { - for (int i = 0; i < CONN_RETRY_NUM; i++) { - try { - rhlClient = Es7Util.getClient(tableInfo.getAddress(), tableInfo.isAuthMesh(), tableInfo.getUserName(), tableInfo.getPassword()); - break; - } catch (Exception e) { - if (i == CONN_RETRY_NUM - 1) { - throw new RuntimeException("", e); - } - - try { - String connInfo = "url: " + tableInfo.getAddress() + "; userName: " + tableInfo.getUserName() + ", pwd:" + tableInfo.getPassword(); - LOG.warn("get conn fail, wait for 5 sec and try again, connInfo:" + connInfo); - Thread.sleep(LOAD_DATA_ERROR_SLEEP_TIME); - } catch (InterruptedException e1) { - LOG.error("", e1); - } - } - - } - SearchSourceBuilder searchSourceBuilder = initConfiguration(boolQueryBuilder); - searchData(searchSourceBuilder, tmpCache); - - } catch (Exception e) { - LOG.error("", e); - throw new RuntimeException(e); - } finally { - - if (rhlClient != null) { - rhlClient.close(); - } - } - } - - private void searchData(SearchSourceBuilder searchSourceBuilder, Map>> tmpCache) { - - Object[] searchAfterParameter = null; - SearchResponse searchResponse = null; - SearchHit[] searchHits = null; - - while (true) { - try { - if (searchAfterParameter != null) { - // set search mark - searchSourceBuilder.searchAfter(searchAfterParameter); - } - - searchRequest.source(searchSourceBuilder); - searchResponse = rhlClient.search(searchRequest, RequestOptions.DEFAULT); - searchHits = searchResponse.getHits().getHits(); - loadToCache(searchHits, tmpCache); - - if (searchHits.length < getFetchSize()) { - break; - } - - searchAfterParameter = searchHits[searchHits.length - 1].getSortValues(); - } catch (IOException e) { - LOG.error("Query failed!", e); - } - } - } - - // initialize searchSourceBuilder - private SearchSourceBuilder initConfiguration(BoolQueryBuilder boolQueryBuilder){ - SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); - if (boolQueryBuilder != null) { - searchSourceBuilder.query(boolQueryBuilder); - } - - searchSourceBuilder.size(getFetchSize()); - - // fields included in the source data - String[] sideFieldNames = StringUtils.split(sideInfo.getSideSelectFields().trim(), ","); - searchSourceBuilder.fetchSource(sideFieldNames, null); - return searchSourceBuilder; - } - - // data load to cache - private void loadToCache(SearchHit[] searchHits, Map>> tmpCache) { - String[] sideFieldNames = StringUtils.split(sideInfo.getSideSelectFields().trim(), ","); - String[] sideFieldTypes = sideInfo.getSideTableInfo().getFieldTypes(); - - for (SearchHit searchHit : searchHits) { - Map oneRow = Maps.newHashMap(); - for (String fieldName : sideFieldNames) { - Object object = searchHit.getSourceAsMap().get(fieldName.trim()); - int fieldIndex = sideInfo.getSideTableInfo().getFieldList().indexOf(fieldName.trim()); - object = Es7Util.getTarget(object, sideFieldTypes[fieldIndex]); - oneRow.put(fieldName.trim(), object); - } - - String cacheKey = buildKey(oneRow, sideInfo.getEqualFieldList()); - List> list = tmpCache.computeIfAbsent(cacheKey, key -> Lists.newArrayList()); - list.add(oneRow); - - } - } - - private String buildKey(List equalValList) { - StringBuilder sb = new StringBuilder(""); - for (Object equalVal : equalValList) { - sb.append(equalVal).append("_"); - } - - return sb.toString(); - } - - private String buildKey(Map val, List equalFieldList) { - StringBuilder sb = new StringBuilder(""); - for (String equalField : equalFieldList) { - sb.append(val.get(equalField)).append("_"); - } - - return sb.toString(); - } - - public int getFetchSize() { - return 1000; - } -} diff --git a/elasticsearch7/elasticsearch7-side/elasticsearch7-all-side/src/main/java/com/dtstack/flink/sql/side/elasticsearch7/Elasticsearch7AllSideInfo.java b/elasticsearch7/elasticsearch7-side/elasticsearch7-all-side/src/main/java/com/dtstack/flink/sql/side/elasticsearch7/Elasticsearch7AllSideInfo.java deleted file mode 100644 index a14fe5a6a..000000000 --- a/elasticsearch7/elasticsearch7-side/elasticsearch7-all-side/src/main/java/com/dtstack/flink/sql/side/elasticsearch7/Elasticsearch7AllSideInfo.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.elasticsearch7; - -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.BaseSideInfo; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.util.ParseUtils; -import org.apache.calcite.sql.SqlNode; -import org.apache.commons.collections.CollectionUtils; -import org.apache.flink.api.java.typeutils.RowTypeInfo; - -import java.util.ArrayList; -import java.util.List; - -/** - * @description: - * @program: flink.sql - * @author: lany - * @create: 2021/01/11 14:53 - */ -public class Elasticsearch7AllSideInfo extends BaseSideInfo { - - public Elasticsearch7AllSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { - super(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); - } - - @Override - public void buildEqualInfo(JoinInfo joinInfo, AbstractSideTableInfo sideTableInfo) { - - } - - @Override - public void parseSelectFields(JoinInfo joinInfo) { - - String sideTableName = joinInfo.getSideTableName(); - String nonSideTableName = joinInfo.getNonSideTable(); - List fields = new ArrayList<>(); - - int sideIndex = 0; - for (int i = 0; i< outFieldInfoList.size(); i++) { - FieldInfo fieldInfo = outFieldInfoList.get(i); - if (fieldInfo.getTable().equalsIgnoreCase(sideTableName)) { - fields.add(fieldInfo.getFieldName()); - sideFieldIndex.put(i, sideIndex); - sideFieldNameIndex.put(i, fieldInfo.getFieldName()); - sideIndex++; - } else if (fieldInfo.getTable().equalsIgnoreCase(nonSideTableName)) { - int nonSideIndex = rowTypeInfo.getFieldIndex(fieldInfo.getFieldName()); - inFieldIndex.put(i, nonSideIndex); - } else { - throw new RuntimeException("unknown table " + fieldInfo.getTable()); - } - } - - if (fields.size() == 0) { - throw new RuntimeException("select non field from table " + sideTableName); - } - - SqlNode conditionNode = joinInfo.getCondition(); - - List sqlNodeList = new ArrayList<>(); - - ParseUtils.parseAnd(conditionNode, sqlNodeList); - - for (SqlNode sqlNode: sqlNodeList) { - dealOneEqualCon(sqlNode, sideTableName); - } - - if (CollectionUtils.isEmpty(equalFieldList)) { - throw new RuntimeException("no join condition found after table" + joinInfo.getLeftTableName()); - } - - for (String equalField : equalFieldList) { - if (fields.contains(equalField)) { - continue; - } - - fields.add(equalField); - } - - sideSelectFields = String.join(",", fields); - } -} diff --git a/elasticsearch7/elasticsearch7-side/elasticsearch7-async-side/pom.xml b/elasticsearch7/elasticsearch7-side/elasticsearch7-async-side/pom.xml deleted file mode 100644 index d17832704..000000000 --- a/elasticsearch7/elasticsearch7-side/elasticsearch7-async-side/pom.xml +++ /dev/null @@ -1,106 +0,0 @@ - - - - sql.side.elasticsearch7 - com.dtstack.flink - 1.0-SNAPSHOT - - 4.0.0 - - sql.side.async.elasticsearch7 - elasticsearch7-async-side - jar - - - 1.0-SNAPSHOT - - - - - - org.elasticsearch.client - elasticsearch-rest-high-level-client - ${elasticsearch.version} - - - - com.dtstack.flink - sql.side.elasticsearch7.core - ${sql.side.elasticsearch7.core.version} - - - - - - - - org.apache.maven.plugins - maven-shade-plugin - 1.4 - - - package - - shade - - - false - - - - - - - - *:* - - META-INF/*.SF - META-INF/*.DSA - META-INF/*.RSA - - - - - - - - - - maven-antrun-plugin - 1.2 - - - copy-resources - - package - - run - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/elasticsearch7/elasticsearch7-side/elasticsearch7-async-side/src/main/java/com/dtstack/flink/sql/side/elasticsearch7/Elasticsearch7AsyncReqRow.java b/elasticsearch7/elasticsearch7-side/elasticsearch7-async-side/src/main/java/com/dtstack/flink/sql/side/elasticsearch7/Elasticsearch7AsyncReqRow.java deleted file mode 100644 index fae742b29..000000000 --- a/elasticsearch7/elasticsearch7-side/elasticsearch7-async-side/src/main/java/com/dtstack/flink/sql/side/elasticsearch7/Elasticsearch7AsyncReqRow.java +++ /dev/null @@ -1,246 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.elasticsearch7; - -import com.dtstack.flink.sql.enums.ECacheContentType; -import com.dtstack.flink.sql.side.*; -import com.dtstack.flink.sql.side.cache.CacheObj; -import com.dtstack.flink.sql.side.elasticsearch7.table.Elasticsearch7SideTableInfo; -import com.dtstack.flink.sql.side.elasticsearch7.util.Es7Util; -import com.dtstack.flink.sql.util.ParseUtils; -import com.dtstack.flink.sql.util.RowDataComplete; -import org.apache.calcite.sql.SqlNode; -import org.apache.commons.lang3.StringUtils; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.configuration.Configuration; -import org.apache.flink.streaming.api.functions.async.ResultFuture; -import org.apache.flink.table.dataformat.BaseRow; -import org.apache.flink.table.dataformat.GenericRow; -import org.apache.flink.table.typeutils.TimeIndicatorTypeInfo; -import org.elasticsearch.action.ActionListener; -import org.elasticsearch.action.search.SearchRequest; -import org.elasticsearch.action.search.SearchResponse; -import org.elasticsearch.client.RequestOptions; -import org.elasticsearch.client.RestHighLevelClient; -import org.elasticsearch.index.query.BoolQueryBuilder; -import org.elasticsearch.search.SearchHit; -import org.elasticsearch.search.builder.SearchSourceBuilder; -import org.elasticsearch.search.sort.SortOrder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.io.Serializable; -import java.sql.Timestamp; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -/** - * @description: - * @program: flink.sql - * @author: lany - * @create: 2021/01/11 11:21 - */ -public class Elasticsearch7AsyncReqRow extends BaseAsyncReqRow implements Serializable { - - private static final Logger LOG = LoggerFactory.getLogger(Elasticsearch7AsyncReqRow.class); - private transient RestHighLevelClient rhlClient; - private SearchRequest searchRequest; - private List sqlJoinCompareOperate = new ArrayList<>(); - - public Elasticsearch7AsyncReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { - super(new Elasticsearch7AsyncSideInfo(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo)); - SqlNode conditionNode = joinInfo.getCondition(); - ParseUtils.parseJoinCompareOperate(conditionNode, sqlJoinCompareOperate); - } - - @Override - public void open(Configuration parameters) throws Exception { - super.open(parameters); - Elasticsearch7SideTableInfo tableInfo = (Elasticsearch7SideTableInfo) sideInfo.getSideTableInfo(); - rhlClient = Es7Util.getClient(tableInfo.getAddress(), - tableInfo.isAuthMesh(), - tableInfo.getUserName(), - tableInfo.getPassword()); - searchRequest = Es7Util.setSearchRequest(sideInfo); - } - - @Override - public void handleAsyncInvoke(Map inputParams, BaseRow input, ResultFuture resultFuture) throws Exception { - String key = buildCacheKey(inputParams); - BoolQueryBuilder boolQueryBuilder = Es7Util.setPredicateclause(sideInfo); - boolQueryBuilder = setInputParams(inputParams, boolQueryBuilder); - SearchSourceBuilder searchSourceBuilder = initConfiguration(); - searchSourceBuilder.query(boolQueryBuilder); - searchRequest.source(searchSourceBuilder); - - //async search data - rhlClient.searchAsync(searchRequest, RequestOptions.DEFAULT, new ActionListener() { - @Override - public void onResponse(SearchResponse searchResponse) { - - List cacheContent = new ArrayList<>(); - List rowList = new ArrayList<>(); - SearchHit[] searchHits = searchResponse.getHits().getHits(); - if (searchHits.length > 0) { - Elasticsearch7SideTableInfo tableInfo = null; - RestHighLevelClient tmpRhlClient = null; - try { - while (true) { - loadDataToCache(searchHits, rowList, cacheContent, input); - if (searchHits.length < getFetchSize()) { - break; - } - if (tableInfo == null) { - tableInfo = (Elasticsearch7SideTableInfo) sideInfo.getSideTableInfo(); - tmpRhlClient = Es7Util.getClient(tableInfo.getAddress(), tableInfo.isAuthMesh(), tableInfo.getUserName(), tableInfo.getPassword()); - } - - Object[] searchAfterParameter = searchHits[searchHits.length - 1].getSortValues(); - searchSourceBuilder.searchAfter(searchAfterParameter); - searchRequest.source(searchSourceBuilder); - searchResponse = tmpRhlClient.search(searchRequest, RequestOptions.DEFAULT); - searchHits = searchResponse.getHits().getHits(); - } - dealCacheData(key, CacheObj.buildCacheObj(ECacheContentType.MultiLine, cacheContent)); - RowDataComplete.completeBaseRow(resultFuture, rowList); - } catch (Exception e) { - dealFillDataError(input, resultFuture, e); - } finally { - if (tmpRhlClient != null) { - try { - tmpRhlClient.close(); - } catch (IOException ex) { - LOG.warn("Failed to shutdown tmpRhlClient.", ex); - } - } - } - } else { - dealMissKey(input, resultFuture); - dealCacheData(key, CacheMissVal.getMissKeyObj()); - } - } - - @Override - public void onFailure(Exception e) { - LOG.error("" + e); - resultFuture.completeExceptionally(new RuntimeException("Response failed!")); - } - }); - } - - @Override - public String buildCacheKey(Map inputParams) { - StringBuilder sb = new StringBuilder(); - for (Object ele: inputParams.values()) { - sb.append(ele) - .append("_"); - } - return sb.toString(); - } - - protected List getRows(BaseRow inputRow, List cacheContent, List results) { - List rowList = com.google.common.collect.Lists.newArrayList(); - for (Object line : results) { - BaseRow row = fillData(inputRow, line); - if (null != cacheContent && openCache()) { - cacheContent.add(line); - } - rowList.add(row); - } - return rowList; - } - - private void loadDataToCache(SearchHit[] searchHits, List rowList, List cacheContent, BaseRow copyCrow) { - List results = com.google.common.collect.Lists.newArrayList(); - for (SearchHit searchHit : searchHits) { - Map object = searchHit.getSourceAsMap(); - results.add(object); - } - rowList.addAll(getRows(copyCrow, cacheContent, results)); - } - - @Override - public BaseRow fillData(BaseRow input, Object line) { - GenericRow genericRow = (GenericRow) input; - Map cacheInfo = (Map) line; - GenericRow row = new GenericRow(sideInfo.getOutFieldInfoList().size()); - row.setHeader(input.getHeader()); - String[] fields = sideInfo.getSideTableInfo().getFieldTypes(); - for (Map.Entry entry: sideInfo.getInFieldIndex().entrySet()) { - Object obj = genericRow.getField(entry.getValue()); - obj = convertTimeIndictorTypeInfo(entry.getValue(), obj); - row.setField(entry.getKey(), obj); - } - - for (Map.Entry entry : sideInfo.getSideFieldIndex().entrySet()) { - if (cacheInfo == null) { - row.setField(entry.getKey(), null); - } else { - Object object = Es7Util.getTarget(cacheInfo.get(sideInfo.getSideFieldNameIndex().get(entry.getKey())), fields[entry.getValue()]); - row.setField(entry.getKey(), object); - } - } - - return row; - } - - @Override - public void close() throws Exception { - super.close(); - if (rhlClient != null) { - try { - rhlClient.close(); - } catch (IOException ex) { - LOG.warn("Failed to shutdown tmpRhlClient.", ex); - } - } - } - - private SearchSourceBuilder initConfiguration() { - SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); - searchSourceBuilder.size(getFetchSize()); - String[] sideFieldNames = StringUtils.split(sideInfo.getSideSelectFields().trim(), ","); - searchSourceBuilder.fetchSource(sideFieldNames, null); - - return searchSourceBuilder; - } - - private BoolQueryBuilder setInputParams(Map inputParams, BoolQueryBuilder boolQueryBuilder) { - if (boolQueryBuilder == null) { - boolQueryBuilder = new BoolQueryBuilder(); - } - - for (int i = 0; i < sqlJoinCompareOperate.size(); i++) { - String fieldName = sideInfo.getEqualFieldList().get(i); - String operatorKind = sqlJoinCompareOperate.get(sideInfo.getEqualFieldList().indexOf(fieldName)); - String condition = String.valueOf(inputParams.get(fieldName)); - boolQueryBuilder = Es7Util.buildFilterCondition(boolQueryBuilder, new PredicateInfo(null, operatorKind, null, fieldName, condition), sideInfo); - } - - return boolQueryBuilder; - } - - public int getFetchSize() { - return 1000; - } - -} diff --git a/elasticsearch7/elasticsearch7-side/elasticsearch7-async-side/src/main/java/com/dtstack/flink/sql/side/elasticsearch7/Elasticsearch7AsyncSideInfo.java b/elasticsearch7/elasticsearch7-side/elasticsearch7-async-side/src/main/java/com/dtstack/flink/sql/side/elasticsearch7/Elasticsearch7AsyncSideInfo.java deleted file mode 100644 index a9b389cda..000000000 --- a/elasticsearch7/elasticsearch7-side/elasticsearch7-async-side/src/main/java/com/dtstack/flink/sql/side/elasticsearch7/Elasticsearch7AsyncSideInfo.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.elasticsearch7; - -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.BaseSideInfo; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.util.ParseUtils; -import com.google.common.collect.Lists; -import org.apache.calcite.sql.SqlNode; -import org.apache.flink.api.java.typeutils.RowTypeInfo; - -import java.util.Arrays; -import java.util.List; - -/** - * @description: - * @program: flink.sql - * @author: lany - * @create: 2021/01/11 11:21 - */ -public class Elasticsearch7AsyncSideInfo extends BaseSideInfo { - - - public Elasticsearch7AsyncSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { - super(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); - } - - @Override - public void parseSelectFields(JoinInfo joinInfo){ - String sideTableName = joinInfo.getSideTableName(); - String nonSideTableName = joinInfo.getNonSideTable(); - List fields = Lists.newArrayList(); - int sideTableFieldIndex; - - for( int i=0; i sqlNodeList = Lists.newArrayList(); - ParseUtils.parseAnd(conditionNode, sqlNodeList); - - for (SqlNode sqlNode : sqlNodeList) { - dealOneEqualCon(sqlNode, sideTableName); - } - - } -} diff --git a/elasticsearch7/elasticsearch7-side/elasticsearch7-side-core/pom.xml b/elasticsearch7/elasticsearch7-side/elasticsearch7-side-core/pom.xml deleted file mode 100644 index 52189c35c..000000000 --- a/elasticsearch7/elasticsearch7-side/elasticsearch7-side-core/pom.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - sql.side.elasticsearch7 - com.dtstack.flink - 1.0-SNAPSHOT - - 4.0.0 - - sql.side.elasticsearch7.core - elasticsearch7-side-core - 1.0-SNAPSHOT - jar - - - - org.elasticsearch.client - elasticsearch-rest-high-level-client - ${elasticsearch.version} - - - junit - junit - 4.12 - test - - - - - - \ No newline at end of file diff --git a/elasticsearch7/elasticsearch7-side/elasticsearch7-side-core/src/main/java/com/dtstack/flink/sql/side/elasticsearch7/table/Elasticsearch7SideParser.java b/elasticsearch7/elasticsearch7-side/elasticsearch7-side-core/src/main/java/com/dtstack/flink/sql/side/elasticsearch7/table/Elasticsearch7SideParser.java deleted file mode 100644 index c84790436..000000000 --- a/elasticsearch7/elasticsearch7-side/elasticsearch7-side-core/src/main/java/com/dtstack/flink/sql/side/elasticsearch7/table/Elasticsearch7SideParser.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.elasticsearch7.table; - -import com.dtstack.flink.sql.table.AbstractSideTableParser; -import com.dtstack.flink.sql.table.AbstractTableInfo; -import com.dtstack.flink.sql.util.ClassUtil; -import com.dtstack.flink.sql.util.MathUtil; -import org.apache.commons.lang3.StringUtils; - -import java.util.Map; - -/** - * @description: elasticsearch side module core - * @program: flink.sql - * @author: lany - * @create: 2021/01/11 10:21 - */ -public class Elasticsearch7SideParser extends AbstractSideTableParser { - - private static final String KEY_ES7_ADDRESS = "address"; - - private static final String KEY_ES7_CLUSTER = "cluster"; - - private static final String KEY_ES7_INDEX = "index"; - - private static final String KEY_ES7_AUTHMESH = "authMesh"; - - private static final String KEY_ES7_USERNAME = "userName"; - - private static final String KEY_ES7_PASSWORD = "password"; - - private static final String KEY_TRUE = "true"; - - @Override - protected boolean fieldNameNeedsUpperCase() { - return false; - } - - @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) throws Exception { - - Elasticsearch7SideTableInfo elasticsearch7SideTableInfo = new Elasticsearch7SideTableInfo(); - elasticsearch7SideTableInfo.setName(tableName); - parseFieldsInfo(fieldsInfo, elasticsearch7SideTableInfo); - parseCacheProp(elasticsearch7SideTableInfo, props); - elasticsearch7SideTableInfo.setAddress((String) props.get(KEY_ES7_ADDRESS.toLowerCase())); - elasticsearch7SideTableInfo.setClusterName((String) props.get(KEY_ES7_CLUSTER.toLowerCase())); - elasticsearch7SideTableInfo.setIndex((String) props.get(KEY_ES7_INDEX.toLowerCase())); - - String authMethStr = (String) props.get(KEY_ES7_AUTHMESH.toLowerCase()); - if (authMethStr != null && StringUtils.equalsIgnoreCase(KEY_TRUE, authMethStr)) { - elasticsearch7SideTableInfo.setAuthMesh(MathUtil.getBoolean(authMethStr)); - elasticsearch7SideTableInfo.setUserName(MathUtil.getString(props.get(KEY_ES7_USERNAME.toLowerCase()))); - elasticsearch7SideTableInfo.setPassword(MathUtil.getString(props.get(KEY_ES7_PASSWORD.toLowerCase()))); - } - - if (MathUtil.getLongVal(props.get(elasticsearch7SideTableInfo.ERROR_LIMIT.toLowerCase())) != null) { - elasticsearch7SideTableInfo.setErrorLimit(MathUtil.getLongVal(props.get(elasticsearch7SideTableInfo.ERROR_LIMIT.toLowerCase()))); - } - - elasticsearch7SideTableInfo.check(); - return elasticsearch7SideTableInfo; - } - - @Override - public Class dbTypeConvertToJavaType(String fieldType) { - return ClassUtil.stringConvertClass(fieldType); - } -} diff --git a/elasticsearch7/elasticsearch7-side/elasticsearch7-side-core/src/main/java/com/dtstack/flink/sql/side/elasticsearch7/table/Elasticsearch7SideTableInfo.java b/elasticsearch7/elasticsearch7-side/elasticsearch7-side-core/src/main/java/com/dtstack/flink/sql/side/elasticsearch7/table/Elasticsearch7SideTableInfo.java deleted file mode 100644 index b8f814a92..000000000 --- a/elasticsearch7/elasticsearch7-side/elasticsearch7-side-core/src/main/java/com/dtstack/flink/sql/side/elasticsearch7/table/Elasticsearch7SideTableInfo.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.elasticsearch7.table; - -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.google.common.base.Preconditions; -import org.elasticsearch.search.builder.SearchSourceBuilder; - -/** - * @description: - * @program: flink.sql - * @author: lany - * @create: 2021/01/11 10:23 - */ -public class Elasticsearch7SideTableInfo extends AbstractSideTableInfo { - - private static final String CURR_TYPE = "elasticsearch7"; - - private String address; - - private String clusterName; - - private String index; - - private boolean authMesh = false; - - private String userName; - - private String password; - - private transient SearchSourceBuilder searchSourceBuilder; - - public String getAddress() { - return address; - } - - public void setAddress(String address) { - this.address = address; - } - - public String getIndex() { - return index; - } - - public void setIndex(String index) { - this.index = index; - } - - @Override - public String getType() { - return super.getType().toLowerCase(); - } - - public void setClusterName(String clusterName) { - this.clusterName = clusterName; - } - - public boolean isAuthMesh() { - return authMesh; - } - - public void setAuthMesh(boolean authMesh) { - this.authMesh = authMesh; - } - - public String getUserName() { - return userName; - } - - public void setUserName(String userName) { - this.userName = userName; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - - public SearchSourceBuilder getSearchSourceBuilder() { - return searchSourceBuilder; - } - - public void setSearchSourceBuilder(SearchSourceBuilder searchSourceBuilder) { - this.searchSourceBuilder = searchSourceBuilder; - } - - public Elasticsearch7SideTableInfo() { - setType(CURR_TYPE); - } - - @Override - public boolean check() { - - Preconditions.checkNotNull(address, "elasticsearch7 type of address is required."); - Preconditions.checkNotNull(clusterName, "elasticsearch7 type of clusterName is required"); - - if (isAuthMesh()) { - Preconditions.checkNotNull(userName, "elasticsearch7 type of userName is required"); - Preconditions.checkNotNull(password, "elasticsearch7 type of password is required"); - } - - return true; - } -} diff --git a/elasticsearch7/elasticsearch7-side/elasticsearch7-side-core/src/main/java/com/dtstack/flink/sql/side/elasticsearch7/util/Es7Util.java b/elasticsearch7/elasticsearch7-side/elasticsearch7-side-core/src/main/java/com/dtstack/flink/sql/side/elasticsearch7/util/Es7Util.java deleted file mode 100644 index 07c1b0f6d..000000000 --- a/elasticsearch7/elasticsearch7-side/elasticsearch7-side-core/src/main/java/com/dtstack/flink/sql/side/elasticsearch7/util/Es7Util.java +++ /dev/null @@ -1,265 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.elasticsearch7.util; - -import com.dtstack.flink.sql.side.BaseSideInfo; -import com.dtstack.flink.sql.side.PredicateInfo; -import com.dtstack.flink.sql.side.elasticsearch7.table.Elasticsearch7SideTableInfo; -import com.dtstack.flink.sql.util.MathUtil; -import org.apache.commons.lang3.StringUtils; -import org.apache.http.HttpHost; -import org.apache.http.auth.AuthScope; -import org.apache.http.auth.UsernamePasswordCredentials; -import org.apache.http.client.CredentialsProvider; -import org.apache.http.impl.client.BasicCredentialsProvider; -import org.elasticsearch.action.search.SearchRequest; -import org.elasticsearch.client.RequestOptions; -import org.elasticsearch.client.RestClient; -import org.elasticsearch.client.RestClientBuilder; -import org.elasticsearch.client.RestHighLevelClient; -import org.elasticsearch.index.query.BoolQueryBuilder; -import org.elasticsearch.index.query.QueryBuilders; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Locale; - -/** - * @description: - * @program: flink.sql - * @author: lany - * @create: 2021/01/11 10:23 - */ -public class Es7Util { - - private static final Logger LOG = LoggerFactory.getLogger(Es7Util.class); - private static final String KEY_WORD_TYPE = ".keyword"; - private static final String APOSTROPHE = "'"; - - /* - * create client for elasticsearch - */ - public static RestHighLevelClient getClient(String esAddress, Boolean isAuthMesh, String userName, String password) { - List httpHostList = new ArrayList<>(); - String[] address = StringUtils.split(esAddress, ","); - Arrays.stream(address).forEach( addr -> { - String[] infoArray = StringUtils.split(addr, ":"); - int port = 9200; - String host = infoArray[0].trim(); - if (infoArray.length > 1) { - port = Integer.parseInt(infoArray[1].trim()); - } - httpHostList.add(new HttpHost(host, port, "http")); - }); - - RestClientBuilder restClientBuilder = RestClient.builder(httpHostList.toArray(new HttpHost[0])); - - if (isAuthMesh) { - final CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); - credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(userName.trim(), password.trim())); - restClientBuilder.setHttpClientConfigCallback(httpAsyncClientBuilder -> - httpAsyncClientBuilder.setDefaultCredentialsProvider(credentialsProvider)); - } - - RestHighLevelClient rhlClient = new RestHighLevelClient(restClientBuilder); - - if (LOG.isInfoEnabled()) { - LOG.info("Pinging Elasticsearch cluster via hosts {}...", httpHostList); - } - - try { - if (!rhlClient.ping(RequestOptions.DEFAULT)) { - throw new RuntimeException("There are no reachable Elasticsearch nodes!"); - } - } catch (IOException e) { - LOG.warn("", e); - } - - if (LOG.isInfoEnabled()) { - LOG.info("Create Elasticsearch RestHighLevelClient connected to {}.", httpHostList.toString()); - } - - return rhlClient; - } - - // add index to search request - public static SearchRequest setSearchRequest(BaseSideInfo sideInfo) { - - SearchRequest searchRequest = new SearchRequest(); - Elasticsearch7SideTableInfo tableInfo = (Elasticsearch7SideTableInfo)sideInfo.getSideTableInfo(); - // determine existence of index - String index = tableInfo.getIndex(); - if (!StringUtils.isEmpty(index) || index.trim().length() > 0) { - // strip leading and trailing spaces from a string - String[] indexes = StringUtils.split(index, ","); - for (int i = 0; i< indexes.length; i++) { - indexes[i] = indexes[i].trim(); - } - searchRequest.indices(indexes); - } - - return searchRequest; - } - - // build where cause - public static BoolQueryBuilder setPredicateclause(BaseSideInfo sideInfo) { - - BoolQueryBuilder boolQueryBuilder = null; - List predicateInfos = sideInfo.getSideTableInfo().getPredicateInfoes(); - if (predicateInfos.size() > 0) { - boolQueryBuilder = new BoolQueryBuilder(); - for (PredicateInfo info : predicateInfos) { - boolQueryBuilder = Es7Util.buildFilterCondition(boolQueryBuilder, info, sideInfo); - } - } - - return boolQueryBuilder; - } - - // build filter condition - public static BoolQueryBuilder buildFilterCondition(BoolQueryBuilder boolQueryBuilder, PredicateInfo info, BaseSideInfo sideInfo) { - switch (info.getOperatorKind()) { - case "IN": - return boolQueryBuilder.must(QueryBuilders.termsQuery(textConvertToKeyword(info.getFieldName(), sideInfo), removeSpaceAndApostrophe(info.getCondition()))); - case "NOT_IN": - return boolQueryBuilder.mustNot(QueryBuilders.termsQuery(textConvertToKeyword(info.getFieldName(), sideInfo), removeSpaceAndApostrophe(info.getCondition()))); - case ">=": - case "GREATER_THAN_OR_EQUAL": - return boolQueryBuilder.must(QueryBuilders.rangeQuery(info.getFieldName()).gte(info.getCondition())); - case ">": - case "GREATER_THAN": - return boolQueryBuilder.must(QueryBuilders.rangeQuery(info.getFieldName()).gt(info.getCondition())); - case "<=": - case "LESS_THAN_OR_EQUAL": - return boolQueryBuilder.must(QueryBuilders.rangeQuery(info.getFieldName()).lte(info.getCondition())); - case "<": - case "LESS_THAN": - return boolQueryBuilder.must(QueryBuilders.rangeQuery(info.getFieldName()).lt(info.getCondition())); - case "BETWEEN": - return boolQueryBuilder.must(QueryBuilders.rangeQuery(info.getFieldName()).gte(StringUtils.split(info.getCondition().toUpperCase(), "AND")[0].trim()) - .lte(StringUtils.split(info.getCondition().toUpperCase(), "AND")[1].trim())); - case "IS_NULL": - return boolQueryBuilder.mustNot(QueryBuilders.existsQuery(info.getFieldName())); - case "IS_NOT_NULL": - return boolQueryBuilder.must(QueryBuilders.existsQuery(info.getFieldName())); - case "=": - case "EQUALS": - if (StringUtils.isBlank(info.getCondition())) { - return boolQueryBuilder; - } - return boolQueryBuilder.must(QueryBuilders.termQuery(textConvertToKeyword(info.getFieldName(), sideInfo), removeSpaceAndApostrophe(info.getCondition())[0])); - case "<>": - case "NOT_EQUALS": - return boolQueryBuilder.mustNot(QueryBuilders.termQuery(textConvertToKeyword(info.getFieldName(), sideInfo), removeSpaceAndApostrophe(info.getCondition())[0])); - default: - return boolQueryBuilder; - } - - } - - // remove extra spaces and apostrophes - public static String[] removeSpaceAndApostrophe(String str) { - String[] split = StringUtils.split(str, ","); - for (int i = 0; i < split.length; i++) { - split[i] = StringUtils.trim(split[i]); - if (StringUtils.startsWith(split[i], APOSTROPHE)) { - split[i] = StringUtils.substring(split[i], 1, split[i].length() - 1); - } - } - - return split; - } - - // prevent word segmentation - public static String textConvertToKeyword(String fieldName, BaseSideInfo sideInfo) { - String[] sideFieldTypes = sideInfo.getSideTableInfo().getFieldTypes(); - int fieldIndex = sideInfo.getSideTableInfo().getFieldList().indexOf(fieldName.trim()); - String fieldType = sideFieldTypes[fieldIndex]; - switch (fieldType.toLowerCase(Locale.ENGLISH)) { - case "varchar": - case "char": - case "text": - return fieldName + KEY_WORD_TYPE; - default: - return fieldName; - } - } - - public static Object getTarget(Object obj, String targetType) { - switch (targetType.toLowerCase(Locale.ENGLISH)) { - - case "smallint": - case "smallintunsigned": - case "tinyint": - case "tinyintunsigned": - case "mediumint": - case "mediumintunsigned": - case "integer": - case "int": - return MathUtil.getIntegerVal(obj); - - case "bigint": - case "bigintunsigned": - case "intunsigned": - case "integerunsigned": - return MathUtil.getLongVal(obj); - - case "boolean": - return MathUtil.getBoolean(obj); - - case "blob": - return MathUtil.getByte(obj); - - case "varchar": - case "char": - case "text": - return MathUtil.getString(obj); - - case "real": - case "float": - case "realunsigned": - case "floatunsigned": - return MathUtil.getFloatVal(obj); - - case "double": - case "doubleunsigned": - return MathUtil.getDoubleVal(obj); - - case "decimal": - case "decimalunsigned": - return MathUtil.getBigDecimal(obj); - - case "date": - return MathUtil.getDate(obj); - - case "timestamp": - case "datetime": - return MathUtil.getTimestamp(obj); - default: - } - return obj; - } - - -} diff --git a/elasticsearch7/elasticsearch7-side/pom.xml b/elasticsearch7/elasticsearch7-side/pom.xml deleted file mode 100644 index bf30b3685..000000000 --- a/elasticsearch7/elasticsearch7-side/pom.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - sql.elasticsearch7 - com.dtstack.flink - 1.0-SNAPSHOT - - 4.0.0 - - pom - sql.side.elasticsearch7 - elasticsearch7-side - - - elasticsearch7-all-side - elasticsearch7-async-side - elasticsearch7-side-core - - - - \ No newline at end of file diff --git a/elasticsearch7/elasticsearch7-sink/pom.xml b/elasticsearch7/elasticsearch7-sink/pom.xml deleted file mode 100644 index e0d7d43a4..000000000 --- a/elasticsearch7/elasticsearch7-sink/pom.xml +++ /dev/null @@ -1,145 +0,0 @@ - - - - sql.elasticsearch7 - com.dtstack.flink - 1.0-SNAPSHOT - - 4.0.0 - - sql.sink.elasticsearch7 - elasticsearch7-sink - - - - org.apache.flink - flink-streaming-java_2.11 - ${flink.version} - provided - - - - org.elasticsearch.client - elasticsearch-rest-high-level-client - ${elasticsearch.version} - - - - log4j - log4j - 1.2.17 - - - - slf4j-api - org.slf4j - 1.7.15 - - - - org.slf4j - slf4j-log4j12 - 1.6.1 - - - - - org.apache.flink - flink-connector-elasticsearch7_2.11 - ${flink.version} - - - log4j-to-slf4j - org.apache.logging.log4j - - - - - - - - com.google.code.gson - gson - 2.8.5 - - - - - org.apache.flink - flink-connector-elasticsearch-base_2.11 - ${flink.version} - - - - - - - org.apache.maven.plugins - maven-shade-plugin - 1.4 - - - package - - shade - - - - - - - - - - *:* - - META-INF/*.SF - META-INF/*.DSA - META-INF/*.RSA - - - - - - - - - - maven-antrun-plugin - 1.2 - - - copy-resources - - package - - run - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/elasticsearch7/elasticsearch7-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/CustomerSinkFunc.java b/elasticsearch7/elasticsearch7-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/CustomerSinkFunc.java deleted file mode 100644 index 4a7c90ae8..000000000 --- a/elasticsearch7/elasticsearch7-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/CustomerSinkFunc.java +++ /dev/null @@ -1,200 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.elasticsearch; - -import com.dtstack.flink.sql.util.DateUtil; -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheStats; -import com.google.common.cache.RemovalListener; -import com.google.common.cache.RemovalNotification; -import com.google.common.collect.ImmutableMap; -import org.apache.commons.lang3.StringUtils; -import org.apache.flink.api.common.functions.RuntimeContext; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.metrics.Counter; -import org.apache.flink.runtime.execution.SuppressRestartsException; -import org.apache.flink.streaming.connectors.elasticsearch.ElasticsearchSinkFunction; -import org.apache.flink.streaming.connectors.elasticsearch.RequestIndexer; -import org.apache.flink.streaming.connectors.elasticsearch.index.IndexGenerator; -import org.apache.flink.streaming.connectors.elasticsearch.index.IndexGeneratorFactory; -import org.apache.flink.table.types.DataType; -import org.apache.flink.types.Row; -import org.apache.lucene.analysis.da.DanishAnalyzer; -import org.elasticsearch.action.index.IndexRequest; -import org.elasticsearch.client.RequestOptions; -import org.elasticsearch.client.Requests; -import org.elasticsearch.client.RestHighLevelClient; -import org.elasticsearch.client.indices.CreateIndexRequest; -import org.elasticsearch.client.indices.GetIndexRequest; -import org.elasticsearch.common.xcontent.XContentType; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.annotation.Nullable; -import java.io.IOException; -import java.sql.Date; -import java.sql.Time; -import java.sql.Timestamp; -import java.util.List; -import java.util.Map; -import java.util.concurrent.Callable; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; - -/** - * @description: - * @program: flink.sql - * @author: lany - * @create: 2021/01/04 17:19 - */ -public class CustomerSinkFunc implements ElasticsearchSinkFunction { - - private final Logger logger = LoggerFactory.getLogger(CustomerSinkFunc.class); - /** - * 用作ID的属性值连接符号 - */ - private static final String ID_VALUE_SPLIT = "_"; - - private String index_definition; - - private List idFiledNames; - - private List fieldNames; - - private List fieldTypes; - - private IndexGenerator indexGenerator; - - private transient Counter outRecords; - - private transient Counter outDirtyRecords; - - private RestHighLevelClient rhlClient; - - // cache dynamic index and add expire time for index - private transient Cache dynamicIndexCache; - - public CustomerSinkFunc(String index, String index_definition, List fieldNames, List fieldTypes, TypeInformation[] typeInformatics, List idFiledNames) { - this.index_definition = index_definition; - this.fieldNames = fieldNames; - this.fieldTypes = fieldTypes; - this.idFiledNames = idFiledNames; - this.indexGenerator = IndexGeneratorFactory.createIndexGenerator(index,(String[]) fieldNames.toArray(), typeInformatics); - } - - @Override - public void process(Tuple2 tuple2, RuntimeContext ctx, RequestIndexer indexer) { - try { - Tuple2 tupleTrans = tuple2; - Boolean retract = tupleTrans.getField(0); - Row element = tupleTrans.getField(1); - if (!retract) { - return; - } - - indexer.add(createIndexRequest(element)); - outRecords.inc(); - } catch (RuntimeException e) { - throw new SuppressRestartsException(e); - } catch (Throwable e) { - outDirtyRecords.inc(); - logger.error("Failed to store source data {}. ", tuple2.getField(1)); - logger.error("Failed to create index request exception. ", e); - } - } - - public void setOutRecords(Counter outRecords) { - this.outRecords = outRecords; - } - - public void setOutDirtyRecords(Counter outDirtyRecords) { - this.outDirtyRecords = outDirtyRecords; - } - - public void setRhlClient(RestHighLevelClient rhlClient) { - this.rhlClient = rhlClient; - } - - public void getDynamicIndexCache() { - this.dynamicIndexCache = CacheBuilder.newBuilder() - .removalListener((RemovalListener) notification -> logger.warn("Index [{}] has been remove from cache because expired.", notification.getKey())) - .expireAfterAccess(10, TimeUnit.MINUTES) - .build(); - } - - public IndexGenerator getIndexGenerator() { - return indexGenerator; - } - - private IndexRequest createIndexRequest(Row element) { - - Map dataMap = Es7Util.rowToJsonMap(element, fieldNames, fieldTypes); - int length = Math.min(element.getArity(), fieldNames.size()); - for (int i = 0; i < length; i++) { - if (element.getField(i) instanceof Date) { - dataMap.put(fieldNames.get(i), DateUtil.transformSqlDateToUtilDate((Date) element.getField(i))); - continue; - } - if (element.getField(i) instanceof Timestamp) { - dataMap.put(fieldNames.get(i), ((Timestamp) element.getField(i)).getTime()); - continue; - } - dataMap.put(fieldNames.get(i), element.getField(i)); - } - - String index = indexGenerator.generate(element); - try { - if (null == dynamicIndexCache.getIfPresent(index) - && !rhlClient.indices().exists(new GetIndexRequest(index), RequestOptions.DEFAULT) - && index_definition != null) { - CreateIndexRequest indexRequest = new CreateIndexRequest(index).source(index_definition, XContentType.JSON); - rhlClient.indices().create(indexRequest, RequestOptions.DEFAULT); - logger.info(String.format("Dynamic index : {%s} is created.",index)); - dynamicIndexCache.put(index, index); - } - } catch (Exception e) { - throw new RuntimeException(String.format("Create index {%s} failed.The reason is {}", index, e.getMessage())); - } - - - String idFieldStr = ""; - if (null != idFiledNames) { - idFieldStr = idFiledNames.stream() - .map(idFiledName -> dataMap.get(idFiledName).toString()) - .collect(Collectors.joining(ID_VALUE_SPLIT)); - } - - if (StringUtils.isEmpty(idFieldStr)) { - return Requests.indexRequest() - .index(index) - .source(dataMap); - } - - return Requests.indexRequest() - .index(index) - .id(idFieldStr) - .source(dataMap); - } - -} diff --git a/elasticsearch7/elasticsearch7-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/ElasticsearchSink.java b/elasticsearch7/elasticsearch7-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/ElasticsearchSink.java deleted file mode 100644 index 433d4e76f..000000000 --- a/elasticsearch7/elasticsearch7-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/ElasticsearchSink.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.elasticsearch; - -import avro.shaded.com.google.common.base.Preconditions; -import com.dtstack.flink.sql.sink.IStreamSinkGener; -import com.dtstack.flink.sql.sink.elasticsearch.table.ElasticsearchTableInfo; -import com.dtstack.flink.sql.table.AbstractTargetTableInfo; -import com.google.common.collect.Maps; -import org.apache.commons.lang.StringUtils; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.api.java.typeutils.TupleTypeInfo; -import org.apache.flink.streaming.api.datastream.DataStream; -import org.apache.flink.streaming.api.datastream.DataStreamSink; -import org.apache.flink.streaming.api.functions.sink.RichSinkFunction; -import org.apache.flink.table.sinks.RetractStreamTableSink; -import org.apache.flink.table.sinks.TableSink; -import org.apache.flink.types.Row; -import org.apache.http.HttpHost; - -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.stream.Collectors; - -/** - * @description: - * @program: flink.sql - * @author: lany - * @create: 2021/01/04 17:20 - */ -public class ElasticsearchSink implements RetractStreamTableSink, IStreamSinkGener { - - private final int ES_DEFAULT_PORT = 9200; - private final String ES_DEFAULT_SCHEMA = "http"; - - private int bulkFlushMaxActions = 1; - - private List esAddressList; - - private String index = ""; - - private String index_definition; - - private List idFiledNames; - - protected String[] fieldNames; - - protected String[] columnTypes; - - private TypeInformation[] fieldTypes; - - private int parallelism = 1; - - protected String registerTableName; - - private ElasticsearchTableInfo esTableInfo; - - - @Override - public TableSink> configure(String[] fieldNames, TypeInformation[] fieldTypes) { - this.fieldNames = fieldNames; - this.fieldTypes = fieldTypes; - return this; - } - - @Override - public TupleTypeInfo> getOutputType() { - return new TupleTypeInfo(org.apache.flink.table.api.Types.BOOLEAN(), getRecordType()); - } - - @Override - public TypeInformation getRecordType() { - return new RowTypeInfo(fieldTypes, fieldNames); - } - - @Override - public String[] getFieldNames() { - return fieldNames; - } - - @Override - public TypeInformation[] getFieldTypes() { - return fieldTypes; - } - - - private RichSinkFunction createEsSinkFunction() { - - // check whether id fields is exists in columns - List filedNamesLists = Arrays.asList(fieldNames); - if (idFiledNames != null && idFiledNames.size() != 0) { - Preconditions.checkState(filedNamesLists.containsAll(idFiledNames), "elasticsearch7 type of id %s is should be exists in columns %s.", idFiledNames, filedNamesLists); - } - CustomerSinkFunc customerSinkFunc = new CustomerSinkFunc(index, index_definition, Arrays.asList(fieldNames), Arrays.asList(columnTypes), fieldTypes, idFiledNames); - - - Map userConfig = Maps.newHashMap(); - // This instructs the sink to emit after every element, otherwise they would be buffered - userConfig.put(org.apache.flink.streaming.connectors.elasticsearch7.ElasticsearchSink.CONFIG_KEY_BULK_FLUSH_MAX_ACTIONS, "" + bulkFlushMaxActions); - - List transports = esAddressList.stream() - .map(address -> address.split(":")) - .map(addressArray -> { - String host = addressArray[0].trim(); - int port = addressArray.length > 1 ? Integer.valueOf(addressArray[1].trim()) : ES_DEFAULT_PORT; - return new HttpHost(host.trim(), port, ES_DEFAULT_SCHEMA); - }).collect(Collectors.toList()); - ExtendEs7ApiCallBridge extendEs7ApiCallBridge = new ExtendEs7ApiCallBridge(transports, esTableInfo); - - return new MetricElasticsearch7Sink(userConfig, extendEs7ApiCallBridge, customerSinkFunc); - } - - @Override - public void emitDataStream(DataStream> dataStream) { - consumeDataStream(dataStream); - } - - @Override - public DataStreamSink consumeDataStream(DataStream> dataStream) { - RichSinkFunction richSinkFunction = createEsSinkFunction(); - DataStreamSink streamSink = dataStream.addSink(richSinkFunction).name(registerTableName); - if (parallelism > 0) { - streamSink.setParallelism(parallelism); - } - return streamSink; - } - - @Override - public ElasticsearchSink genStreamSink(AbstractTargetTableInfo targetTableInfo) { - esTableInfo = (ElasticsearchTableInfo) targetTableInfo; - index = esTableInfo.getIndex(); - index_definition = esTableInfo.getIndex_definition(); - columnTypes = esTableInfo.getFieldTypes(); - esAddressList = Arrays.asList(esTableInfo.getAddress().split(",")); - String id = esTableInfo.getId(); - registerTableName = esTableInfo.getName(); - parallelism = Objects.isNull(esTableInfo.getParallelism()) ? parallelism : esTableInfo.getParallelism(); - - if (!StringUtils.isEmpty(id)) { - idFiledNames = Arrays.stream(StringUtils.split(id, ",")).map(String::valueOf).collect(Collectors.toList()); - } - return this; - } - -} diff --git a/elasticsearch7/elasticsearch7-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/Es7Util.java b/elasticsearch7/elasticsearch7-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/Es7Util.java deleted file mode 100644 index d75d0509d..000000000 --- a/elasticsearch7/elasticsearch7-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/Es7Util.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.elasticsearch; - -import com.dtstack.flink.sql.util.DtStringUtil; -import com.google.gson.JsonParser; -import com.google.gson.JsonSyntaxException; -import org.apache.commons.lang3.StringUtils; -import org.apache.flink.shaded.guava18.com.google.common.collect.Maps; -import org.apache.flink.types.Row; -import org.apache.flink.util.Preconditions; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * @description: parse utils - * @program: flink.sql - * @author: lany - * @create: 2021/01/04 17:20 - */ -public class Es7Util { - - public static Map rowToJsonMap(Row row, List fields, List types) { - Preconditions.checkArgument(row.getArity() == fields.size()); - Map jsonMap = Maps.newHashMap(); - int i = 0; - for(; i < fields.size(); ++i) { - String field = fields.get(i); - String[] parts = field.split("\\."); - Map currMap = jsonMap; - for(int j = 0; j < parts.length - 1; ++j) { - String key = parts[j]; - if(currMap.get(key) == null) { - HashMap hashMap = Maps.newHashMap(); - currMap.put(key, hashMap); - } - currMap = (Map) currMap.get(key); - } - String key = parts[parts.length - 1]; - Object col = row.getField(i); - if(col != null) { - Object value = DtStringUtil.col2string(col, types.get(i)); - currMap.put(key, value); - } - - } - - return jsonMap; - } - - /** - * check whether str is json format - * @param json - * @return - */ - public static boolean isJson(String json) { - if (StringUtils.isEmpty(json)) { - return false; - } - try { - new JsonParser().parse(json); - return true; - } catch (JsonSyntaxException e) { - return false; - } - } - -} diff --git a/elasticsearch7/elasticsearch7-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/ExtendEs7ApiCallBridge.java b/elasticsearch7/elasticsearch7-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/ExtendEs7ApiCallBridge.java deleted file mode 100644 index a551be0a3..000000000 --- a/elasticsearch7/elasticsearch7-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/ExtendEs7ApiCallBridge.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.elasticsearch; - -import com.dtstack.flink.sql.sink.elasticsearch.table.ElasticsearchTableInfo; -import org.apache.flink.streaming.connectors.elasticsearch.ElasticsearchApiCallBridge; -import org.apache.flink.streaming.connectors.elasticsearch.ElasticsearchSinkBase; -import org.apache.flink.util.Preconditions; -import org.apache.http.HttpHost; -import org.apache.http.auth.AuthScope; -import org.apache.http.auth.UsernamePasswordCredentials; -import org.apache.http.client.CredentialsProvider; -import org.apache.http.impl.client.BasicCredentialsProvider; -import org.elasticsearch.action.bulk.BackoffPolicy; -import org.elasticsearch.action.bulk.BulkItemResponse; -import org.elasticsearch.action.bulk.BulkProcessor; -import org.elasticsearch.client.RequestOptions; -import org.elasticsearch.client.RestClient; -import org.elasticsearch.client.RestClientBuilder; -import org.elasticsearch.client.RestHighLevelClient; -import org.elasticsearch.common.unit.TimeValue; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.annotation.Nullable; -import java.io.IOException; -import java.util.List; -import java.util.Map; - -/** - * @description: - * @program: flink.sql - * @author: lany - * @create: 2021/01/04 17:20 - */ -public class ExtendEs7ApiCallBridge implements ElasticsearchApiCallBridge { - - private static final Logger LOG = LoggerFactory.getLogger(ExtendEs7ApiCallBridge.class); - - private final List HttpAddresses; - - - private RestHighLevelClient rhlClient = null; - - protected ElasticsearchTableInfo es7TableInfo; - - public ExtendEs7ApiCallBridge(List httpAddresses, ElasticsearchTableInfo es7TableInfo) { - Preconditions.checkArgument(httpAddresses != null && !httpAddresses.isEmpty()); - this.HttpAddresses = httpAddresses; - this.es7TableInfo = es7TableInfo; - } - - public RestHighLevelClient getRhlClient() { - return this.rhlClient; - } - - @Override - public RestHighLevelClient createClient(Map clientConfig) { - - if (this.rhlClient != null) { - return this.rhlClient; - } - - RestClientBuilder restClientBuilder = RestClient.builder(HttpAddresses.toArray(new HttpHost[HttpAddresses.size()])); - if (es7TableInfo.isAuthMesh()) { - // 进行用户和密码认证 - final CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); - credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(es7TableInfo.getUserName(), es7TableInfo.getPassword())); - restClientBuilder.setHttpClientConfigCallback(httpAsyncClientBuilder -> - httpAsyncClientBuilder.setDefaultCredentialsProvider(credentialsProvider)); - } - - this.rhlClient = new RestHighLevelClient(restClientBuilder); - - if (LOG.isInfoEnabled()) { - LOG.info("Pinging Elasticsearch cluster via hosts {} ...", HttpAddresses); - } - - try{ - if (!rhlClient.ping(RequestOptions.DEFAULT)) { - throw new RuntimeException("There are no reachable Elasticsearch nodes!"); - } - } catch (IOException e){ - LOG.warn("", e); - } - - - if (LOG.isInfoEnabled()) { - LOG.info("Created Elasticsearch RestHighLevelClient connected to {}", HttpAddresses.toString()); - } - - return rhlClient; - } - - @Override - public BulkProcessor.Builder createBulkProcessorBuilder(RestHighLevelClient client, BulkProcessor.Listener listener) { - return BulkProcessor.builder((request, bulkListener) -> client.bulkAsync(request, RequestOptions.DEFAULT, bulkListener), listener); - } - - @Override - public Throwable extractFailureCauseFromBulkItemResponse(BulkItemResponse bulkItemResponse) { - if (!bulkItemResponse.isFailed()) { - return null; - } else { - return bulkItemResponse.getFailure().getCause(); - } - } - - @Override - public void configureBulkProcessorBackoff( - BulkProcessor.Builder builder, - @Nullable ElasticsearchSinkBase.BulkFlushBackoffPolicy flushBackoffPolicy) { - - BackoffPolicy backoffPolicy; - if (flushBackoffPolicy != null) { - switch (flushBackoffPolicy.getBackoffType()) { - case CONSTANT: - backoffPolicy = BackoffPolicy.constantBackoff( - new TimeValue(flushBackoffPolicy.getDelayMillis()), - flushBackoffPolicy.getMaxRetryCount()); - break; - case EXPONENTIAL: - default: - backoffPolicy = BackoffPolicy.exponentialBackoff( - new TimeValue(flushBackoffPolicy.getDelayMillis()), - flushBackoffPolicy.getMaxRetryCount()); - } - } else { - backoffPolicy = BackoffPolicy.noBackoff(); - } - - builder.setBackoffPolicy(backoffPolicy); - } - -} diff --git a/elasticsearch7/elasticsearch7-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/MetricElasticsearch7Sink.java b/elasticsearch7/elasticsearch7-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/MetricElasticsearch7Sink.java deleted file mode 100644 index aa9750f52..000000000 --- a/elasticsearch7/elasticsearch7-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/MetricElasticsearch7Sink.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.elasticsearch; - -import com.dtstack.flink.sql.metric.MetricConstant; -import com.dtstack.flink.sql.sink.elasticsearch.table.ElasticsearchTableInfo; -import org.apache.flink.configuration.Configuration; -import org.apache.flink.metrics.Counter; -import org.apache.flink.metrics.Meter; -import org.apache.flink.metrics.MeterView; -import org.apache.flink.streaming.connectors.elasticsearch.ElasticsearchSinkBase; -import org.apache.flink.streaming.connectors.elasticsearch.ElasticsearchSinkFunction; -import org.apache.flink.streaming.connectors.elasticsearch.util.NoOpFailureHandler; -import org.elasticsearch.client.RestHighLevelClient; - -import java.util.List; -import java.util.Map; - -/** - * @description: - * @program: flink.sql - * @author: lany - * @create: 2021/01/04 17:20 - */ -public class MetricElasticsearch7Sink extends ElasticsearchSinkBase { - - protected CustomerSinkFunc customerSinkFunc; - - protected ExtendEs7ApiCallBridge extendEs7ApiCallBridge; - - protected transient Meter outRecordsRate; - - protected Map userConfig; - - - public MetricElasticsearch7Sink(Map userConfig,ExtendEs7ApiCallBridge extendEs7ApiCallBridge, - ElasticsearchSinkFunction elasticsearchSinkFunction) { - super(extendEs7ApiCallBridge, userConfig, elasticsearchSinkFunction, new NoOpFailureHandler()); - this.customerSinkFunc = (CustomerSinkFunc) elasticsearchSinkFunction; - this.extendEs7ApiCallBridge = extendEs7ApiCallBridge; - this.userConfig = userConfig; - } - - @Override - public void open(Configuration parameters) throws Exception { - super.open(parameters); - this.customerSinkFunc.setRhlClient(extendEs7ApiCallBridge.getRhlClient()); - this.customerSinkFunc.getIndexGenerator().open(); - this.customerSinkFunc.getDynamicIndexCache(); - initMetric(); - } - - - public void initMetric() { - Counter counter = getRuntimeContext().getMetricGroup().counter(MetricConstant.DT_NUM_RECORDS_OUT); - Counter outDirtyRecords = getRuntimeContext().getMetricGroup().counter(MetricConstant.DT_NUM_DIRTY_RECORDS_OUT); - - customerSinkFunc.setOutRecords(counter); - customerSinkFunc.setOutDirtyRecords(outDirtyRecords); - outRecordsRate = getRuntimeContext().getMetricGroup().meter(MetricConstant.DT_NUM_RECORDS_OUT_RATE, new MeterView(counter, 20)); - } - -} diff --git a/elasticsearch7/elasticsearch7-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/table/ElasticsearchSinkParser.java b/elasticsearch7/elasticsearch7-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/table/ElasticsearchSinkParser.java deleted file mode 100644 index 5243361f0..000000000 --- a/elasticsearch7/elasticsearch7-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/table/ElasticsearchSinkParser.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.elasticsearch.table; - -import com.dtstack.flink.sql.table.AbstractTableInfo; -import com.dtstack.flink.sql.table.AbstractTableParser; -import com.dtstack.flink.sql.util.MathUtil; -import org.apache.commons.lang3.StringUtils; - -import java.util.Map; - -/** - * @description: - * @program: flink.sql - * @author: lany - * @create: 2021/01/04 17:19 - */ -public class ElasticsearchSinkParser extends AbstractTableParser { - - private static final String KEY_ES7_ADDRESS = "address"; - - private static final String KEY_ES7_INDEX = "index"; - - private static final String KEY_ES7_INDEX_DEFINITION = "index_definition"; - - private static final String KEY_ES7_ID_FIELD_INDEX_LIST = "id"; - - private static final String KEY_ES7_AUTHMESH = "authMesh"; - - private static final String KEY_ES7_USERNAME = "userName"; - - private static final String KEY_ES7_PASSWORD = "password"; - - private static final String KEY_TRUE = "true"; - - private static final String KEY_ES7_PARALLELISM = "parallelism"; - - @Override - protected boolean fieldNameNeedsUpperCase() { - return false; - } - - @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { - ElasticsearchTableInfo elasticsearchTableInfo = new ElasticsearchTableInfo(); - elasticsearchTableInfo.setName(tableName); - parseFieldsInfo(fieldsInfo, elasticsearchTableInfo); - elasticsearchTableInfo.setAddress((String) props.get(KEY_ES7_ADDRESS.toLowerCase())); - elasticsearchTableInfo.setId((String) props.get(KEY_ES7_ID_FIELD_INDEX_LIST.toLowerCase())); - elasticsearchTableInfo.setIndex((String) props.get(KEY_ES7_INDEX.toLowerCase())); - elasticsearchTableInfo.setIndex_definition((String) props.get(KEY_ES7_INDEX_DEFINITION)); - elasticsearchTableInfo.setParallelism(MathUtil.getIntegerVal(props.getOrDefault(KEY_ES7_PARALLELISM.toLowerCase(), 1))); - - String authMeshStr = (String) props.get(KEY_ES7_AUTHMESH.toLowerCase()); - if (authMeshStr != null && StringUtils.equalsIgnoreCase(KEY_TRUE, authMeshStr)) { - elasticsearchTableInfo.setAuthMesh(MathUtil.getBoolean(authMeshStr)); - elasticsearchTableInfo.setUserName(MathUtil.getString(props.get(KEY_ES7_USERNAME.toLowerCase()))); - elasticsearchTableInfo.setPassword(MathUtil.getString(props.get(KEY_ES7_PASSWORD.toLowerCase()))); - } - elasticsearchTableInfo.check(); - return elasticsearchTableInfo; - } - -} diff --git a/elasticsearch7/elasticsearch7-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/table/ElasticsearchTableInfo.java b/elasticsearch7/elasticsearch7-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/table/ElasticsearchTableInfo.java deleted file mode 100644 index 7d1bf0daa..000000000 --- a/elasticsearch7/elasticsearch7-sink/src/main/java/com/dtstack/flink/sql/sink/elasticsearch/table/ElasticsearchTableInfo.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.elasticsearch.table; - -import com.dtstack.flink.sql.sink.elasticsearch.Es7Util; -import com.dtstack.flink.sql.table.AbstractTargetTableInfo; -import com.google.common.base.Preconditions; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang3.math.NumberUtils; - -import java.util.Arrays; - -/** - * @description: - * @program: flink.sql - * @author: lany - * @create: 2021/01/04 17:19 - */ -public class ElasticsearchTableInfo extends AbstractTargetTableInfo { - - private static final String CURR_TYPE = "elasticsearch7"; - - private String address; - - private String index; - - private String id; - - private boolean authMesh = false; - - private String userName; - - private String password; - - private String index_definition; - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getAddress() { - return address; - } - - public void setAddress(String address) { - this.address = address; - } - - public String getIndex() { - return index; - } - - public void setIndex(String index) { - this.index = index; - } - - @Override - public String getType() { - //return super.getType().toLowerCase() + TARGET_SUFFIX; - return super.getType().toLowerCase(); - } - - public boolean isAuthMesh() { - return authMesh; - } - - public void setAuthMesh(boolean authMesh) { - this.authMesh = authMesh; - } - - public String getUserName() { - return userName; - } - - public void setUserName(String userName) { - this.userName = userName; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public void setIndex_definition(String index_definition) { - this.index_definition = index_definition; - } - - public String getIndex_definition() { - return index_definition; - } - - public ElasticsearchTableInfo() { - setType(CURR_TYPE); - } - - @Override - public boolean check() { - Preconditions.checkNotNull(address, "elasticsearch7 type of address is required"); - Preconditions.checkNotNull(index, "elasticsearch7 type of index is required"); - - if (index_definition != null && !Es7Util.isJson(index_definition)) { - throw new IllegalArgumentException("elasticsearch7 type of index_definition must be json format!"); - } - if (isAuthMesh()) { - Preconditions.checkNotNull(userName, "elasticsearch7 type of userName is required"); - Preconditions.checkNotNull(password, "elasticsearch7 type of password is required"); - } - - return true; - } - -} diff --git a/elasticsearch7/elasticsearch7-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/index/AbstractTimeIndexGenerator.java b/elasticsearch7/elasticsearch7-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/index/AbstractTimeIndexGenerator.java deleted file mode 100644 index 521414500..000000000 --- a/elasticsearch7/elasticsearch7-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/index/AbstractTimeIndexGenerator.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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.streaming.connectors.elasticsearch.index; - -import java.time.format.DateTimeFormatter; - -/** - * Abstract class for time related {@link IndexGenerator}. - */ -public abstract class AbstractTimeIndexGenerator extends IndexGeneratorBase { - - private final String dateTimeFormat; - protected transient DateTimeFormatter dateTimeFormatter; - - public AbstractTimeIndexGenerator(String index, String dateTimeFormat) { - super(index); - this.dateTimeFormat = dateTimeFormat; - } - - @Override - public void open() { - this.dateTimeFormatter = DateTimeFormatter.ofPattern(dateTimeFormat); - } -} diff --git a/elasticsearch7/elasticsearch7-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/index/IndexGenerator.java b/elasticsearch7/elasticsearch7-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/index/IndexGenerator.java deleted file mode 100644 index d45fc1be8..000000000 --- a/elasticsearch7/elasticsearch7-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/index/IndexGenerator.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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.streaming.connectors.elasticsearch.index; - -import org.apache.flink.annotation.Internal; -import org.apache.flink.types.Row; - -import java.io.Serializable; - -/** - * This interface is responsible to generate index name from given {@link Row} record. - */ -@Internal -public interface IndexGenerator extends Serializable { - - /** - * Initialize the index generator, this will be called only once before {@link #generate(Row)} is called. - */ - default void open() {} - - /** - * Generate index name according the the given row. - */ - String generate(Row row); -} diff --git a/elasticsearch7/elasticsearch7-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/index/IndexGeneratorBase.java b/elasticsearch7/elasticsearch7-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/index/IndexGeneratorBase.java deleted file mode 100644 index 00d95e9e5..000000000 --- a/elasticsearch7/elasticsearch7-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/index/IndexGeneratorBase.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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.streaming.connectors.elasticsearch.index; - -import java.util.Objects; - -/** - * Base class for {@link IndexGenerator}. - */ -public abstract class IndexGeneratorBase implements IndexGenerator { - - private static final long serialVersionUID = 1L; - protected final String index; - - public IndexGeneratorBase(String index) { - this.index = index; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof IndexGeneratorBase)) { - return false; - } - IndexGeneratorBase that = (IndexGeneratorBase) o; - return index.equals(that.index); - } - - @Override - public int hashCode() { - return Objects.hash(index); - } -} diff --git a/elasticsearch7/elasticsearch7-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/index/IndexGeneratorFactory.java b/elasticsearch7/elasticsearch7-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/index/IndexGeneratorFactory.java deleted file mode 100644 index 09e8ae1c4..000000000 --- a/elasticsearch7/elasticsearch7-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/index/IndexGeneratorFactory.java +++ /dev/null @@ -1,281 +0,0 @@ -/* - * 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.streaming.connectors.elasticsearch.index; - -import com.google.common.base.Preconditions; -import org.apache.flink.annotation.Internal; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.common.typeinfo.Types; -import org.apache.flink.table.api.TableException; -import org.apache.flink.table.api.TableSchema; -import org.apache.flink.table.types.DataType; -import org.apache.flink.table.types.utils.TypeConversions; -import org.apache.flink.types.Row; - -import java.sql.Date; -import java.sql.Time; -import java.sql.Timestamp; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Factory of {@link IndexGenerator}. - * - *

Flink supports both static index and dynamic index. - * - *

If you want to have a static index, this option value should be a plain string, e.g. 'myusers', - * all the records will be consistently written into "myusers" index. - * - *

If you want to have a dynamic index, you can use '{field_name}' to reference a field value in the - * record to dynamically generate a target index. You can also use '{field_name|date_format_string}' to - * convert a field value of TIMESTAMP/DATE/TIME type into the format specified by date_format_string. The - * date_format_string is compatible with {@link java.text.SimpleDateFormat}. For example, if the option - * value is 'myusers_{log_ts|yyyy-MM-dd}', then a record with log_ts field value 2020-03-27 12:25:55 will - * be written into "myusers-2020-03-27" index. - */ -@Internal -public class IndexGeneratorFactory { - - private IndexGeneratorFactory() {} - - public static IndexGenerator createIndexGenerator(String index, String[] fieldNames, TypeInformation[] typeInformatics) { - final IndexHelper indexHelper = new IndexHelper(); - if (indexHelper.checkIsDynamicIndex(index)) { - return createRuntimeIndexGenerator(index, fieldNames, typeInformatics, indexHelper); - } else { - return new StaticIndexGenerator(index); - } - } - - private static IndexGenerator createRuntimeIndexGenerator( - String index, - String[] fieldNames, - TypeInformation[] typeInformatics, - IndexHelper indexHelper) { - final String dynamicIndexPatternStr = indexHelper.extractDynamicIndexPatternStr(index); - final String indexPrefix = index.substring(0, index.indexOf(dynamicIndexPatternStr)); - final String indexSuffix = index.substring(indexPrefix.length() + dynamicIndexPatternStr.length()); - - final boolean isDynamicIndexWithFormat = indexHelper.checkIsDynamicIndexWithFormat(index); - final int indexFieldPos = indexHelper.extractIndexFieldPos(index, fieldNames, isDynamicIndexWithFormat); - final TypeInformation indexFieldType = typeInformatics[indexFieldPos]; - - // validate index field type - indexHelper.validateIndexFieldType(indexFieldType); - - // time extract dynamic index pattern - if (isDynamicIndexWithFormat) { - final String dateTimeFormat = indexHelper.extractDateFormat(index, indexFieldType); - // DataTypes.SQL_TIMESTAMP - if (indexFieldType.equals(Types.LOCAL_DATE_TIME)) { - return new AbstractTimeIndexGenerator(index, dateTimeFormat) { - @Override - public String generate(Row row) { - LocalDateTime indexField = (LocalDateTime) row.getField(indexFieldPos); - String indexFieldValueStr = indexField.format(dateTimeFormatter); - return indexPrefix.concat(indexFieldValueStr).concat(indexSuffix); - } - }; - } - else if (indexFieldType.equals(Types.SQL_TIMESTAMP)) { - return new AbstractTimeIndexGenerator(index, dateTimeFormat) { - @Override - public String generate(Row row) { - Timestamp indexField = (Timestamp) row.getField(indexFieldPos); - String indexFieldValueStr = indexField.toLocalDateTime().format(dateTimeFormatter); - return indexPrefix.concat(indexFieldValueStr).concat(indexSuffix); - } - }; - } - // DataTypes.SQL_DATE - else if (indexFieldType.equals(Types.LOCAL_DATE)) { - return new AbstractTimeIndexGenerator(index, dateTimeFormat) { - @Override - public String generate(Row row) { - LocalDate indexField = (LocalDate) row.getField(indexFieldPos); - String indexFieldValueStr = indexField.format(dateTimeFormatter); - return indexPrefix.concat(indexFieldValueStr).concat(indexSuffix); - } - }; - } else if (indexFieldType.equals(Types.SQL_DATE)) { - return new AbstractTimeIndexGenerator(index, dateTimeFormat) { - @Override - public String generate(Row row) { - Date indexField = (Date) row.getField(indexFieldPos); - String indexFieldValueStr = indexField.toLocalDate().format(dateTimeFormatter); - return indexPrefix.concat(indexFieldValueStr).concat(indexSuffix); - } - }; - } // DataTypes.TIME - else if (indexFieldType.equals(Types.LOCAL_TIME)) { - return new AbstractTimeIndexGenerator(index, dateTimeFormat) { - @Override - public String generate(Row row) { - LocalTime indexField = (LocalTime) row.getField(indexFieldPos); - String indexFieldValueStr = indexField.format(dateTimeFormatter); - return indexPrefix.concat(indexFieldValueStr).concat(indexSuffix); - } - }; - } else if (indexFieldType.equals(Types.SQL_TIME)) { - return new AbstractTimeIndexGenerator(index, dateTimeFormat) { - @Override - public String generate(Row row) { - Time indexField = (Time) row.getField(indexFieldPos); - String indexFieldValueStr = indexField.toLocalTime().format(dateTimeFormatter); - return indexPrefix.concat(indexFieldValueStr).concat(indexSuffix); - } - }; - } else { - throw new TableException(String.format("Unsupported type '%s' found in Elasticsearch dynamic index field, " + - "time-related pattern only support types are: DATE,TIME,TIMESTAMP.", - TypeConversions.fromLegacyInfoToDataType(indexFieldType))); - } - } - // general dynamic index pattern - return new IndexGeneratorBase(index) { - @Override - public String generate(Row row) { - Object indexField = row.getField(indexFieldPos); - Preconditions.checkNotNull(indexField, "Index field's value is not allow null."); - return indexPrefix.concat(indexField.toString()).concat(indexSuffix); - } - }; - } - - /** - * Helper class for {@link IndexGeneratorFactory}, this helper can use to validate index field type - * ans parse index format from pattern. - */ - private static class IndexHelper { - private static final Pattern dynamicIndexPattern = Pattern.compile("\\{[^\\{\\}]+\\}?"); - private static final Pattern dynamicIndexTimeExtractPattern = Pattern.compile(".*\\{.+\\|.*\\}.*"); - private static final List supportedTypes = new ArrayList<>(); - private static final Map defaultFormats = new HashMap<>(); - - static { - //time related types - supportedTypes.add(Types.LOCAL_DATE_TIME); - supportedTypes.add(Types.SQL_TIMESTAMP); - supportedTypes.add(Types.LOCAL_DATE); - supportedTypes.add(Types.SQL_DATE); - supportedTypes.add(Types.LOCAL_TIME); - supportedTypes.add(Types.SQL_TIME); - //general types - supportedTypes.add(Types.STRING); - supportedTypes.add(Types.SHORT); - supportedTypes.add(Types.INT); - supportedTypes.add(Types.LONG); - } - - static { - defaultFormats.put(Types.LOCAL_DATE_TIME, "yyyy_MM_dd_HH_mm_ss"); - defaultFormats.put(Types.SQL_TIMESTAMP, "yyyy_MM_dd_HH_mm_ss"); - defaultFormats.put(Types.LOCAL_DATE, "yyyy_MM_dd"); - defaultFormats.put(Types.SQL_DATE, "yyyy_MM_dd"); - defaultFormats.put(Types.LOCAL_TIME, "HH_mm_ss"); - defaultFormats.put(Types.SQL_TIME, "HH_mm_ss"); - } - - /** - * Validate the index field Type. - */ - void validateIndexFieldType(TypeInformation indexTypeInfo) { - if (!supportedTypes.contains(indexTypeInfo)) { - throw new IllegalArgumentException(String.format("Unsupported type %s of index field, " + - "Supported types are: %s", indexTypeInfo, supportedTypes)); - } - } - - /** - * Get the default date format. - */ - String getDefaultFormat(TypeInformation indexTypeInfo) { - return defaultFormats.get(indexTypeInfo); - } - - /** - * Check general dynamic index is enabled or not by index pattern. - */ - boolean checkIsDynamicIndex(String index) { - final Matcher matcher = dynamicIndexPattern.matcher(index); - int count = 0; - while (matcher.find()) { - count++; - } - if (count > 1) { - throw new TableException(String.format("Chaining dynamic index pattern %s is not supported," + - " only support single dynamic index pattern.", index)); - } - return count == 1; - } - - /** - * Check time extract dynamic index is enabled or not by index pattern. - */ - boolean checkIsDynamicIndexWithFormat(String index) { - return dynamicIndexTimeExtractPattern.matcher(index).matches(); - } - - /** - * Extract dynamic index pattern string from index pattern string. - */ - String extractDynamicIndexPatternStr(String index) { - int start = index.indexOf("{"); - int end = index.lastIndexOf("}"); - return index.substring(start, end + 1); - } - - /** - * Extract index field position in a fieldNames, return the field position. - */ - int extractIndexFieldPos(String index, String[] fieldNames, boolean isDynamicIndexWithFormat) { - List fieldList = Arrays.asList(fieldNames); - String indexFieldName; - if (isDynamicIndexWithFormat) { - indexFieldName = index.substring(index.indexOf("{") + 1, index.indexOf("|")); - } else { - indexFieldName = index.substring(index.indexOf("{") + 1, index.indexOf("}")); - } - if (!fieldList.contains(indexFieldName)) { - throw new TableException(String.format("Unknown field '%s' in index pattern '%s', please check the field name.", - indexFieldName, index)); - } - return fieldList.indexOf(indexFieldName); - } - - /** - * Extract dateTime format by the date format that extracted from index pattern string. - */ - private String extractDateFormat(String index, TypeInformation indexTypeInfo) { - String format = index.substring(index.indexOf("|") + 1, index.indexOf("}")); - if ("".equals(format)) { - format = getDefaultFormat(indexTypeInfo); - } - return format; - } - } -} diff --git a/elasticsearch7/elasticsearch7-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/index/StaticIndexGenerator.java b/elasticsearch7/elasticsearch7-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/index/StaticIndexGenerator.java deleted file mode 100644 index 994b94e23..000000000 --- a/elasticsearch7/elasticsearch7-sink/src/main/java/org/apache/flink/streaming/connectors/elasticsearch/index/StaticIndexGenerator.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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.streaming.connectors.elasticsearch.index; - -import org.apache.flink.types.Row; - -/** - * A static {@link IndexGenerator} which generate fixed index name. - */ -public class StaticIndexGenerator extends IndexGeneratorBase { - - public StaticIndexGenerator(String index) { - super(index); - } - - public String generate(Row row) { - return index; - } -} diff --git a/file/file-source/pom.xml b/file/file-source/pom.xml deleted file mode 100644 index c7870d9f5..000000000 --- a/file/file-source/pom.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - sql.file - com.dtstack.flink - 1.0-SNAPSHOT - ../pom.xml - - 4.0.0 - - sql.source.file - file-source - jar - - - - - org.apache.maven.plugins - maven-shade-plugin - 1.4 - - - package - - shade - - - false - - - org.slf4j - - - - - *:* - - META-INF/*.SF - META-INF/*.DSA - META-INF/*.RSA - - - - - - - - - - maven-antrun-plugin - 1.2 - - - copy-resources - - package - - run - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/file/file-source/src/main/java/com/dtstack/flink/sql/source/file/DTCsvRowDeserializationSchema.java b/file/file-source/src/main/java/com/dtstack/flink/sql/source/file/DTCsvRowDeserializationSchema.java deleted file mode 100644 index 51ad7a245..000000000 --- a/file/file-source/src/main/java/com/dtstack/flink/sql/source/file/DTCsvRowDeserializationSchema.java +++ /dev/null @@ -1,380 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.source.file; - -import com.dtstack.flink.sql.source.file.throwable.LengthMismatchException; -import org.apache.flink.annotation.PublicEvolving; -import org.apache.flink.api.common.serialization.DeserializationSchema; -import org.apache.flink.api.common.typeinfo.BasicArrayTypeInfo; -import org.apache.flink.api.common.typeinfo.PrimitiveArrayTypeInfo; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.common.typeinfo.Types; -import org.apache.flink.api.java.typeutils.ObjectArrayTypeInfo; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.formats.csv.CsvRowSchemaConverter; -import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.JsonNode; -import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.ObjectReader; -import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.dataformat.csv.CsvMapper; -import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.dataformat.csv.CsvSchema; -import org.apache.flink.types.Row; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.io.Serializable; -import java.lang.reflect.Array; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.sql.Date; -import java.sql.Time; -import java.sql.Timestamp; - -/** - * @author tiezhu - * @date 2021/4/14 星期三 - * Company dtstack - */ -@PublicEvolving -public class DTCsvRowDeserializationSchema implements DeserializationSchema { - private static final Logger LOG = LoggerFactory.getLogger(DTCsvRowDeserializationSchema.class); - - /** - * Type information describing the result type. - */ - private TypeInformation typeInfo; - - /** - * Runtime instance that performs the actual work. - */ - private RuntimeConverter runtimeConverter; - - /** - * Object reader used to read rows. It is configured by {@link CsvSchema}. - */ - private ObjectReader objectReader; - - /** - * 字段值的分割符,默认为',' - */ - private Character fieldDelimiter; - - /** - * 针对null的替换值,默认为"null"字符 - */ - private String nullLiteral; - - /** - * 默认为true - */ - private Boolean allowComments; - - /** - * 数组元素分割符,默认为',' - */ - private String arrayElementDelimiter; - - private Character quoteCharacter; - - private Character escapeCharacter; - - @Override - public Row deserialize(byte[] message) throws IOException { - try { - final JsonNode root = objectReader.readValue(message); - return (Row) runtimeConverter.convert(root); - } catch (Exception e) { - throw new IOException(e); - } - } - - @Override - public boolean isEndOfStream(Row nextElement) { - return false; - } - - @Override - public TypeInformation getProducedType() { - return typeInfo; - } - - private void init() { - runtimeConverter = createRowRuntimeConverter((RowTypeInfo) typeInfo, true); - CsvSchema csvSchema = initCsvSchema(typeInfo); - objectReader = new CsvMapper().readerFor(JsonNode.class).with(csvSchema); - } - - private CsvSchema initCsvSchema(TypeInformation typeInfo) { - - CsvSchema.Builder rebuild = CsvRowSchemaConverter - .convert((RowTypeInfo) typeInfo) - .rebuild() - .setAllowComments(allowComments); - - if (arrayElementDelimiter != null) { - rebuild.setArrayElementSeparator(arrayElementDelimiter); - } - - if (fieldDelimiter != null) { - rebuild.setColumnSeparator(fieldDelimiter); - } - - if (quoteCharacter != null) { - rebuild.setQuoteChar(quoteCharacter); - } - - if (nullLiteral != null) { - rebuild.setNullValue(nullLiteral); - } - - if (escapeCharacter != null) { - rebuild.setEscapeChar(escapeCharacter); - } - - return rebuild.build(); - } - - // -------------------------------------------------------------------------------------------- - // Setter - // -------------------------------------------------------------------------------------------- - - public void setFieldDelimiter(Character fieldDelimiter) { - this.fieldDelimiter = fieldDelimiter; - } - - public void setNullLiteral(String nullLiteral) { - this.nullLiteral = nullLiteral; - } - - public void setAllowComments(Boolean allowComments) { - this.allowComments = allowComments; - } - - public void setArrayElementDelimiter(String arrayElementDelimiter) { - this.arrayElementDelimiter = arrayElementDelimiter; - } - - public void setQuoteCharacter(Character quoteCharacter) { - this.quoteCharacter = quoteCharacter; - } - - public void setEscapeCharacter(Character escapeCharacter) { - this.escapeCharacter = escapeCharacter; - } - - public void setTypeInfo(TypeInformation typeInfo) { - this.typeInfo = typeInfo; - } - - // -------------------------------------------------------------------------------------------- - // Builder - // -------------------------------------------------------------------------------------------- - - public static class Builder { - - private final DTCsvRowDeserializationSchema deserializationSchema; - - public Builder() { - deserializationSchema = new DTCsvRowDeserializationSchema(); - } - - public Builder setFieldDelimiter(Character fieldDelimiter) { - deserializationSchema.setFieldDelimiter(fieldDelimiter); - return this; - } - - public Builder setNullLiteral(String nullLiteral) { - deserializationSchema.setNullLiteral(nullLiteral); - return this; - } - - public Builder setAllowComments(Boolean allowComments) { - deserializationSchema.setAllowComments(allowComments); - return this; - } - - public Builder setArrayElementDelimiter(String arrayElementDelimiter) { - deserializationSchema.setArrayElementDelimiter(arrayElementDelimiter); - return this; - } - - public Builder setQuoteCharacter(Character quoteCharacter) { - deserializationSchema.setQuoteCharacter(quoteCharacter); - return this; - } - - public Builder setEscapeCharacter(Character escapeCharacter) { - deserializationSchema.setEscapeCharacter(escapeCharacter); - return this; - } - - public Builder setTypeInfo(TypeInformation typeInfo) { - deserializationSchema.setTypeInfo(typeInfo); - return this; - } - - public DTCsvRowDeserializationSchema build() { - deserializationSchema.init(); - return deserializationSchema; - } - } - - // -------------------------------------------------------------------------------------------- - // RuntimeConverter - // -------------------------------------------------------------------------------------------- - - private interface RuntimeConverter extends Serializable { - Object convert(JsonNode node) throws IOException; - } - - private static RuntimeConverter createRowRuntimeConverter( - RowTypeInfo rowTypeInfo, - boolean isTopLevel) { - final TypeInformation[] fieldTypes = rowTypeInfo.getFieldTypes(); - final String[] fieldNames = rowTypeInfo.getFieldNames(); - - final RuntimeConverter[] fieldConverters = - createFieldRuntimeConverters(fieldTypes); - - return assembleRowRuntimeConverter(isTopLevel, fieldNames, fieldConverters); - } - - private static RuntimeConverter[] createFieldRuntimeConverters(TypeInformation[] fieldTypes) { - final RuntimeConverter[] fieldConverters = new RuntimeConverter[fieldTypes.length]; - for (int i = 0; i < fieldTypes.length; i++) { - fieldConverters[i] = createNullableRuntimeConverter(fieldTypes[i]); - } - return fieldConverters; - } - - private static RuntimeConverter assembleRowRuntimeConverter( - boolean isTopLevel, - String[] fieldNames, - RuntimeConverter[] fieldConverters) { - final int rowArity = fieldNames.length; - - return (node) -> { - final int nodeSize = node.size(); - - validateArity(rowArity, nodeSize); - - final Row row = new Row(rowArity); - for (int i = 0; i < Math.min(rowArity, nodeSize); i++) { - // Jackson only supports mapping by name in the first level - if (isTopLevel) { - row.setField(i, fieldConverters[i].convert(node.get(fieldNames[i]))); - } else { - row.setField(i, fieldConverters[i].convert(node.get(i))); - } - } - return row; - }; - } - - private static RuntimeConverter createNullableRuntimeConverter( - TypeInformation info) { - final RuntimeConverter valueConverter = createRuntimeConverter(info); - return (node) -> { - if (node.isNull()) { - return null; - } - return valueConverter.convert(node); - }; - } - - private static RuntimeConverter createRuntimeConverter(TypeInformation info) { - if (info.equals(Types.VOID)) { - return (node) -> null; - } else if (info.equals(Types.STRING)) { - return JsonNode::asText; - } else if (info.equals(Types.BOOLEAN)) { - return (node) -> Boolean.valueOf(node.asText().trim()); - } else if (info.equals(Types.BYTE)) { - return (node) -> Byte.valueOf(node.asText().trim()); - } else if (info.equals(Types.SHORT)) { - return (node) -> Short.valueOf(node.asText().trim()); - } else if (info.equals(Types.INT)) { - return (node) -> Integer.valueOf(node.asText().trim()); - } else if (info.equals(Types.LONG)) { - return (node) -> Long.valueOf(node.asText().trim()); - } else if (info.equals(Types.FLOAT)) { - return (node) -> Float.valueOf(node.asText().trim()); - } else if (info.equals(Types.DOUBLE)) { - return (node) -> Double.valueOf(node.asText().trim()); - } else if (info.equals(Types.BIG_DEC)) { - return (node) -> new BigDecimal(node.asText().trim()); - } else if (info.equals(Types.BIG_INT)) { - return (node) -> new BigInteger(node.asText().trim()); - } else if (info.equals(Types.SQL_DATE)) { - return (node) -> Date.valueOf(node.asText()); - } else if (info.equals(Types.SQL_TIME)) { - return (node) -> Time.valueOf(node.asText()); - } else if (info.equals(Types.SQL_TIMESTAMP)) { - return (node) -> Timestamp.valueOf(node.asText()); - } else if (info.equals(Types.LOCAL_DATE)) { - return (node) -> Date.valueOf(node.asText()).toLocalDate(); - } else if (info.equals(Types.LOCAL_TIME)) { - return (node) -> Time.valueOf(node.asText()).toLocalTime(); - } else if (info.equals(Types.LOCAL_DATE_TIME)) { - return (node) -> Timestamp.valueOf(node.asText()).toLocalDateTime(); - } else if (info instanceof RowTypeInfo) { - final RowTypeInfo rowTypeInfo = (RowTypeInfo) info; - return createRowRuntimeConverter(rowTypeInfo, false); - } else if (info instanceof BasicArrayTypeInfo) { - return createObjectArrayRuntimeConverter( - ((BasicArrayTypeInfo) info).getComponentInfo() - ); - } else if (info instanceof ObjectArrayTypeInfo) { - return createObjectArrayRuntimeConverter( - ((ObjectArrayTypeInfo) info).getComponentInfo() - ); - } else if (info instanceof PrimitiveArrayTypeInfo && - ((PrimitiveArrayTypeInfo) info).getComponentType() == Types.BYTE) { - return createByteArrayRuntimeConverter(); - } else { - throw new RuntimeException("Unsupported type information '" + info + "'."); - } - } - - private static RuntimeConverter createObjectArrayRuntimeConverter( - TypeInformation elementType) { - final Class elementClass = elementType.getTypeClass(); - final RuntimeConverter elementConverter = createNullableRuntimeConverter(elementType); - - return (node) -> { - final int nodeSize = node.size(); - final Object[] array = (Object[]) Array.newInstance(elementClass, nodeSize); - for (int i = 0; i < nodeSize; i++) { - array[i] = elementConverter.convert(node.get(i)); - } - return array; - }; - } - - private static RuntimeConverter createByteArrayRuntimeConverter() { - return JsonNode::binaryValue; - } - - private static void validateArity(int expected, int actual) { - if (expected != actual) { - throw new LengthMismatchException( - "Row length mismatch. " + expected + - " fields expected but was " + actual + "."); - } - } -} diff --git a/file/file-source/src/main/java/com/dtstack/flink/sql/source/file/FileSource.java b/file/file-source/src/main/java/com/dtstack/flink/sql/source/file/FileSource.java deleted file mode 100644 index f0bd9c5b6..000000000 --- a/file/file-source/src/main/java/com/dtstack/flink/sql/source/file/FileSource.java +++ /dev/null @@ -1,260 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.source.file; - -import com.dtstack.flink.sql.exception.ExceptionTrace; -import com.dtstack.flink.sql.metric.MetricConstant; -import com.dtstack.flink.sql.source.IStreamSourceGener; -import com.dtstack.flink.sql.source.file.table.FileSourceTableInfo; -import com.dtstack.flink.sql.table.AbstractSourceTableInfo; -import com.dtstack.flink.sql.util.ThreadUtil; -import org.apache.commons.lang3.StringUtils; -import org.apache.flink.api.common.functions.AbstractRichFunction; -import org.apache.flink.api.common.functions.RuntimeContext; -import org.apache.flink.api.common.serialization.DeserializationSchema; -import org.apache.flink.metrics.Counter; -import org.apache.flink.runtime.execution.SuppressRestartsException; -import org.apache.flink.streaming.api.datastream.DataStreamSource; -import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; -import org.apache.flink.streaming.api.functions.source.SourceFunction; -import org.apache.flink.table.api.Table; -import org.apache.flink.table.api.java.StreamTableEnvironment; -import org.apache.flink.types.Row; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.fs.FileSystem; -import org.apache.hadoop.fs.Path; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.URI; -import java.util.Locale; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * @author tiezhu - * @date 2021/3/9 星期二 - * Company dtstack - */ -public class FileSource extends AbstractRichFunction implements IStreamSourceGener, SourceFunction { - private static final Logger LOG = LoggerFactory.getLogger(FileSource.class); - - private static final Long METRIC_WAIT_TIME = 20L; - - private static final String SP = File.separator; - - private DeserializationSchema deserializationSchema; - - /** - * Flag to mark the main work loop as alive. - */ - private final AtomicBoolean running = new AtomicBoolean(true); - - private URI fileUri; - - private InputStream inputStream; - - private BufferedReader bufferedReader; - - private String charset; - - private int fromLine; - - protected transient Counter errorCounter; - - /** - * tps ransactions Per Second - */ - protected transient Counter numInRecord; - - /** - * rps Record Per Second: deserialize data and out record num - */ - protected transient Counter numInResolveRecord; - - @Override - public Table genStreamSource(AbstractSourceTableInfo sourceTableInfo, - StreamExecutionEnvironment env, - StreamTableEnvironment tableEnv) { - FileSource fileSource = new FileSource(); - FileSourceTableInfo tableInfo = (FileSourceTableInfo) sourceTableInfo; - - fileSource.initSource(tableInfo); - - String fields = StringUtils.join(tableInfo.getFields(), ","); - - DataStreamSource source = env.addSource(fileSource, tableInfo.getOperatorName(), tableInfo.getTypeInformation()); - - return tableEnv.fromDataStream(source, fields); - } - - /** - * 初始化指标 - */ - public void initMetric() { - RuntimeContext runtimeContext = getRuntimeContext(); - - errorCounter = runtimeContext.getMetricGroup().counter(MetricConstant.DT_DIRTY_DATA_COUNTER); - numInRecord = runtimeContext.getMetricGroup().counter(MetricConstant.DT_NUM_RECORDS_IN_COUNTER); - numInResolveRecord = runtimeContext.getMetricGroup().counter(MetricConstant.DT_NUM_RECORDS_RESOVED_IN_COUNTER); - } - - public void initSource(FileSourceTableInfo tableInfo) { - deserializationSchema = tableInfo.getDeserializationSchema(); - fileUri = URI.create(tableInfo.getFilePath() + SP + tableInfo.getFileName()); - - charset = tableInfo.getCharsetName(); - LOG.info("File charset: " + charset); - - fromLine = tableInfo.getFromLine(); - LOG.info("Read from line: " + fromLine); - } - - /** - * 根据存储位置的不同,获取不同的input stream - * - * @param fileUri file uri - * @return input stream - */ - private InputStream getInputStream(URI fileUri) { - try { - String scheme = fileUri.getScheme() == null ? FileSourceConstant.FILE_LOCAL : fileUri.getScheme(); - switch (scheme.toLowerCase(Locale.ROOT)) { - case FileSourceConstant.FILE_LOCAL: - return fromLocalFile(fileUri); - case FileSourceConstant.FILE_HDFS: - return fromHdfsFile(fileUri); - default: - throw new UnsupportedOperationException( - String.format("Unsupported type [%s] of file.", scheme) - ); - } - } catch (IOException e) { - throw new SuppressRestartsException(e); - } - } - - /** - * 从HDFS上获取文件内容 - * - * @param fileUri file uri of file - * @return hdfs file input stream - * @throws IOException reader exception - */ - private InputStream fromHdfsFile(URI fileUri) throws IOException { - Configuration conf = new Configuration(); - - // get conf from HADOOP_CONF_DIR - String hadoopConfDir = System.getenv("HADOOP_CONF_DIR"); - String confHome = hadoopConfDir == null ? "." : hadoopConfDir; - - conf.addResource(new Path(confHome + SP + "hdfs-site.xml")); - - FileSystem fs = FileSystem.get(fileUri, conf); - return fs.open(new Path(fileUri.getPath())); - } - - /** - * 从本地获取文件内容 - * - * @param fileUri file uri of file - * @return local file input stream - * @throws FileNotFoundException read exception - */ - private InputStream fromLocalFile(URI fileUri) throws FileNotFoundException { - File file = new File(fileUri.getPath()); - if (file.exists()) { - return new FileInputStream(file); - } else { - throw new SuppressRestartsException(new IOException( - String.format("File not exist. File path: [%s]", fileUri.getPath()))); - } - } - - @Override - public void run(SourceContext ctx) throws Exception { - initMetric(); - AtomicInteger currentLine = new AtomicInteger(0); - String line = ""; - inputStream = getInputStream(fileUri); - bufferedReader = new BufferedReader(new InputStreamReader(inputStream, charset)); - - try { - while (running.get()) { - try { - line = bufferedReader.readLine(); - if (line == null) { - running.compareAndSet(true, false); - inputStream.close(); - bufferedReader.close(); - break; - } else { - if (currentLine.incrementAndGet() < fromLine) { - continue; - } - - numInRecord.inc(); - Row row = deserializationSchema.deserialize(line.getBytes()); - if (row == null) { - throw new IOException("Deserialized row is null"); - } - ctx.collect(row); - numInResolveRecord.inc(); - } - } catch (IOException e) { - if (errorCounter.getCount() % 1000 == 0) { - LOG.error("Deserialize error! Record: " + line); - LOG.error("Cause: " + ExceptionTrace.traceOriginalCause(e)); - } - errorCounter.inc(); - } - } - } finally { - ThreadUtil.sleepSeconds(METRIC_WAIT_TIME); - } - } - - @Override - public void cancel() { - LOG.info("File source cancel.."); - running.compareAndSet(true, false); - if (inputStream != null) { - try { - inputStream.close(); - } catch (IOException ioException) { - LOG.error("File input stream close error!", ioException); - } - } - - if (bufferedReader != null) { - try { - bufferedReader.close(); - } catch (IOException ioException) { - LOG.error("File buffer reader close error!", ioException); - } - } - } -} diff --git a/file/file-source/src/main/java/com/dtstack/flink/sql/source/file/FileSourceConstant.java b/file/file-source/src/main/java/com/dtstack/flink/sql/source/file/FileSourceConstant.java deleted file mode 100644 index 1419f7d59..000000000 --- a/file/file-source/src/main/java/com/dtstack/flink/sql/source/file/FileSourceConstant.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.source.file; - -/** - * @author tiezhu - * @date 2021/3/22 星期一 - * Company dtstack - */ -public class FileSourceConstant { - public static final String TYPE_KEY = "type"; - - public static final String FORMAT_KEY = "format"; - - public static final String FIELD_DELIMITER_KEY = "fieldDelimiter"; - - public static final String FILE_NAME_KEY = "fileName"; - - public static final String FILE_PATH_KEY = "filePath"; - - public static final String CHARSET_NAME_KEY = "charsetName"; - - public static final String AVRO_FORMAT_KEY = "avroFormat"; - - public static final String NULL_LITERAL_KEY = "nullLiteral"; - - public static final String ALLOW_COMMENT_KEY = "allowComment"; - - public static final String ARRAY_ELEMENT_DELIMITER_KEY = "arrayElementDelimiter"; - - public static final String QUOTA_CHARACTER_KEY = "quoteCharacter"; - - public static final String ESCAPE_CHARACTER_KEY = "escapeCharacter"; - - public static final String FROM_LINE_KEY = "fromLine"; - - public static final Character DEFAULT_DELIMITER = ','; - - public static final String DEFAULT_FILE_FORMAT = "csv"; - - public static final String DEFAULT_CHARSET = "UTF-8"; - - public static final String DEFAULT_PATH = "."; - - public static final String FILE_LOCAL = "local"; - - public static final String FILE_HDFS = "hdfs"; - -} diff --git a/file/file-source/src/main/java/com/dtstack/flink/sql/source/file/table/ArvoSourceTableInfo.java b/file/file-source/src/main/java/com/dtstack/flink/sql/source/file/table/ArvoSourceTableInfo.java deleted file mode 100644 index 3e03d9d8c..000000000 --- a/file/file-source/src/main/java/com/dtstack/flink/sql/source/file/table/ArvoSourceTableInfo.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.source.file.table; - -import com.google.common.base.Preconditions; -import org.apache.flink.api.common.serialization.DeserializationSchema; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.formats.avro.AvroRowDeserializationSchema; -import org.apache.flink.types.Row; - -/** - * @author tiezhu - * @date 2021/3/22 星期一 - * Company dtstack - */ -public class ArvoSourceTableInfo extends FileSourceTableInfo { - /** - * 针对arvo特定参数 - */ - private String arvoFormat; - - public String getArvoFormat() { - return arvoFormat; - } - - public void setArvoFormat(String arvoFormat) { - this.arvoFormat = arvoFormat; - } - - public static Builder newBuilder(ArvoSourceTableInfo tableInfo) { - return new Builder(tableInfo); - } - - public static class Builder { - private final ArvoSourceTableInfo tableInfo; - - public Builder(ArvoSourceTableInfo tableInfo) { - this.tableInfo = tableInfo; - } - - public Builder setArvoFormat(String arvoFormat) { - tableInfo.setArvoFormat(arvoFormat); - return this; - } - - public Builder setTypeInformation(TypeInformation typeInformation) { - tableInfo.setTypeInformation(typeInformation); - return this; - } - - public ArvoSourceTableInfo buildTableInfo() { - DeserializationSchema deserializationSchema = buildDeserializationSchema(); - tableInfo.setDeserializationSchema(deserializationSchema); - - return tableInfo; - } - - public DeserializationSchema buildDeserializationSchema() { - String arvoFormat = tableInfo.getArvoFormat(); - Preconditions.checkNotNull(arvoFormat, "format [arvo] must set arvoFormat"); - return new AvroRowDeserializationSchema(arvoFormat); - } - } - -} diff --git a/file/file-source/src/main/java/com/dtstack/flink/sql/source/file/table/CsvSourceTableInfo.java b/file/file-source/src/main/java/com/dtstack/flink/sql/source/file/table/CsvSourceTableInfo.java deleted file mode 100644 index 1e41bec67..000000000 --- a/file/file-source/src/main/java/com/dtstack/flink/sql/source/file/table/CsvSourceTableInfo.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.source.file.table; - -import com.dtstack.flink.sql.source.file.DTCsvRowDeserializationSchema; - -/** - * @author tiezhu - * @date 2021/3/22 星期一 - * Company dtstack - */ -public class CsvSourceTableInfo extends FileSourceTableInfo { - - /** - * 字段值的分割符,默认为',' - */ - private Character fieldDelimiter; - - /** - * 针对null的替换值,默认为"null"字符 - */ - private String nullLiteral; - - /** - * 默认为true - */ - private Boolean allowComments; - - /** - * 数组元素分割符,默认为',' - */ - private String arrayElementDelimiter; - - private Character quoteCharacter; - - private Character escapeCharacter; - - public Character getFieldDelimiter() { - return fieldDelimiter; - } - - public void setFieldDelimiter(Character fieldDelimiter) { - this.fieldDelimiter = fieldDelimiter; - } - - public String getNullLiteral() { - return nullLiteral; - } - - public void setNullLiteral(String nullLiteral) { - this.nullLiteral = nullLiteral; - } - - public Boolean getAllowComments() { - return allowComments; - } - - public void setAllowComments(Boolean allowComments) { - this.allowComments = allowComments; - } - - public String getArrayElementDelimiter() { - return arrayElementDelimiter; - } - - public void setArrayElementDelimiter(String arrayElementDelimiter) { - this.arrayElementDelimiter = arrayElementDelimiter; - } - - public Character getQuoteCharacter() { - return quoteCharacter; - } - - public void setQuoteCharacter(Character quoteCharacter) { - this.quoteCharacter = quoteCharacter; - } - - public Character getEscapeCharacter() { - return escapeCharacter; - } - - public void setEscapeCharacter(Character escapeCharacter) { - this.escapeCharacter = escapeCharacter; - } - - public void buildDeserializationSchema() { - DTCsvRowDeserializationSchema dtCsvRowDeserializationSchema = new DTCsvRowDeserializationSchema - .Builder() - .setTypeInfo(this.buildRowTypeInfo()) - .setFieldDelimiter(this.getFieldDelimiter()) - .setNullLiteral(this.getNullLiteral()) - .setAllowComments(this.getAllowComments()) - .setArrayElementDelimiter(this.getArrayElementDelimiter()) - .setEscapeCharacter(this.getEscapeCharacter()) - .setQuoteCharacter(this.getQuoteCharacter()) - .build(); - this.setDeserializationSchema(dtCsvRowDeserializationSchema); - } -} \ No newline at end of file diff --git a/file/file-source/src/main/java/com/dtstack/flink/sql/source/file/table/FileSourceParser.java b/file/file-source/src/main/java/com/dtstack/flink/sql/source/file/table/FileSourceParser.java deleted file mode 100644 index 5d2b4f0a2..000000000 --- a/file/file-source/src/main/java/com/dtstack/flink/sql/source/file/table/FileSourceParser.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.source.file.table; - -import com.dtstack.flink.sql.source.file.FileSourceConstant; -import com.dtstack.flink.sql.table.AbstractSourceParser; -import com.dtstack.flink.sql.table.AbstractTableInfo; -import com.dtstack.flink.sql.util.MathUtil; - -import java.util.Locale; -import java.util.Map; - -/** - * @author tiezhu - * @date 2021/3/9 星期二 - * Company dtstack - */ -public class FileSourceParser extends AbstractSourceParser { - @Override - public AbstractTableInfo getTableInfo(String tableName, - String fieldsInfo, - Map props) { - FileSourceTableInfo tableInfo = switchTableType(tableName, fieldsInfo, props); - - tableInfo.setType(MathUtil.getString(props.get(FileSourceConstant.TYPE_KEY.toLowerCase()))); - tableInfo.setFileName(MathUtil.getString(props.get(FileSourceConstant.FILE_NAME_KEY.toLowerCase()))); - tableInfo.setFilePath(MathUtil.getString(props.getOrDefault(FileSourceConstant.FILE_PATH_KEY.toLowerCase(), FileSourceConstant.DEFAULT_PATH))); - tableInfo.setCharsetName(MathUtil.getString(props.getOrDefault(FileSourceConstant.CHARSET_NAME_KEY.toLowerCase(), FileSourceConstant.DEFAULT_CHARSET))); - tableInfo.setFromLine(MathUtil.getIntegerVal(props.getOrDefault(FileSourceConstant.FROM_LINE_KEY.toLowerCase(), 1))); - - tableInfo.check(); - - return tableInfo; - } - - private FileSourceTableInfo switchTableType(String tableName, - String fieldsInfo, - Map props) { - String format = MathUtil.getString(props.getOrDefault(FileSourceConstant.FORMAT_KEY.toLowerCase(), FileSourceConstant.DEFAULT_FILE_FORMAT)).toLowerCase(Locale.ROOT); - switch (format) { - case "csv": { - CsvSourceTableInfo tableInfo = new CsvSourceTableInfo(); - tableInfo.setName(tableName); - parseFieldsInfo(fieldsInfo, tableInfo); - - tableInfo.setTypeInformation(tableInfo.buildRowTypeInfo()); - tableInfo.setFieldDelimiter(MathUtil.getChar(props.getOrDefault(FileSourceConstant.FIELD_DELIMITER_KEY.toLowerCase(), FileSourceConstant.DEFAULT_DELIMITER))); - tableInfo.setNullLiteral(MathUtil.getString(props.get(FileSourceConstant.NULL_LITERAL_KEY.toLowerCase()))); - tableInfo.setAllowComments(MathUtil.getBoolean(props.getOrDefault(FileSourceConstant.ALLOW_COMMENT_KEY.toLowerCase(), FileSourceTableInfo.DEFAULT_TRUE))); - tableInfo.setArrayElementDelimiter(MathUtil.getString(props.get(FileSourceConstant.ARRAY_ELEMENT_DELIMITER_KEY.toLowerCase()))); - Character quoteChar = MathUtil.getChar(props.get(FileSourceConstant.QUOTA_CHARACTER_KEY.toLowerCase())); - if (quoteChar != null && !Character.isSpaceChar(quoteChar)) { - tableInfo.setQuoteCharacter(quoteChar); - } - - Character escapeChar = MathUtil.getChar(props.get(FileSourceConstant.ESCAPE_CHARACTER_KEY.toLowerCase())); - if (escapeChar != null && !Character.isSpaceChar(escapeChar)) { - tableInfo.setEscapeCharacter(escapeChar); - } - - tableInfo.buildDeserializationSchema(); - return tableInfo; - } - case "json": { - JsonSourceTableInfo tableInfo = new JsonSourceTableInfo(); - tableInfo.setName(tableName); - parseFieldsInfo(fieldsInfo, tableInfo); - return JsonSourceTableInfo - .newBuilder(tableInfo) - .setTypeInformation(tableInfo.buildRowTypeInfo()) - .buildTableInfo(); - } - case "avro": { - ArvoSourceTableInfo tableInfo = new ArvoSourceTableInfo(); - tableInfo.setName(tableName); - parseFieldsInfo(fieldsInfo, tableInfo); - - return ArvoSourceTableInfo - .newBuilder(tableInfo) - .setTypeInformation(tableInfo.buildRowTypeInfo()) - .setArvoFormat(MathUtil.getString(props.get(FileSourceConstant.AVRO_FORMAT_KEY.toLowerCase()))) - .buildTableInfo(); - } - default: - throw new IllegalStateException("Unexpected value: " + format); - } - } -} diff --git a/file/file-source/src/main/java/com/dtstack/flink/sql/source/file/table/FileSourceTableInfo.java b/file/file-source/src/main/java/com/dtstack/flink/sql/source/file/table/FileSourceTableInfo.java deleted file mode 100644 index f01196828..000000000 --- a/file/file-source/src/main/java/com/dtstack/flink/sql/source/file/table/FileSourceTableInfo.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.source.file.table; - -import com.dtstack.flink.sql.table.AbstractSourceTableInfo; -import com.dtstack.flink.sql.util.DataTypeUtils; -import com.google.common.base.Preconditions; -import org.apache.flink.api.common.serialization.DeserializationSchema; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.types.Row; - -import java.util.stream.IntStream; - -/** - * @author tiezhu - * @date 2021/3/9 星期二 - * Company dtstack - */ -public class FileSourceTableInfo extends AbstractSourceTableInfo { - - private static final String SOURCE_OPERATOR_NAME_TEMPLATE = "${fileName}_${tableName}"; - - /*-------------------------------------------------------------*/ - - /** - * 文件名 - */ - private String fileName; - - /** - * 文件存放路径 - */ - private String filePath; - - /** - * 文件编码格式,默认 UTF-8 - */ - private String charsetName; - - private DeserializationSchema deserializationSchema; - - private TypeInformation typeInformation; - - private int fromLine; - - /*-------------------------------------------------------------*/ - - public String getFileName() { - return fileName; - } - - public void setFileName(String fileName) { - this.fileName = fileName; - } - - public String getFilePath() { - return filePath; - } - - public void setFilePath(String filePath) { - this.filePath = filePath; - } - - public String getCharsetName() { - return charsetName; - } - - public void setCharsetName(String charsetName) { - this.charsetName = charsetName; - } - - public TypeInformation getTypeInformation() { - return typeInformation; - } - - public void setTypeInformation(TypeInformation typeInformation) { - this.typeInformation = typeInformation; - } - - public DeserializationSchema getDeserializationSchema() { - return deserializationSchema; - } - - public void setDeserializationSchema(DeserializationSchema deserializationSchema) { - this.deserializationSchema = deserializationSchema; - } - - public int getFromLine() { - return fromLine; - } - - public void setFromLine(int fromLine) { - this.fromLine = fromLine; - } - - @SuppressWarnings("unchecked") - public TypeInformation buildRowTypeInfo() { - String[] types = getFieldTypes(); - Class[] classes = getFieldClasses(); - - TypeInformation[] rowTypes = - IntStream.range(0, classes.length) - .mapToObj( - i -> { - if (classes[i].isArray()) { - return DataTypeUtils.convertToArray(types[i]); - } else { - return TypeInformation.of(classes[i]); - } - } - ) - .toArray(TypeInformation[]::new); - return new RowTypeInfo(rowTypes, getFields()); - } - - public String getOperatorName() { - return SOURCE_OPERATOR_NAME_TEMPLATE - .replace("${fileName}", getFileName()) - .replace("${tableName}", getName()); - } - - @Override - public boolean check() { - Preconditions.checkNotNull(getType(), "Type is required!"); - Preconditions.checkNotNull(fileName, "File name is required!"); - - return false; - } -} diff --git a/file/file-source/src/main/java/com/dtstack/flink/sql/source/file/table/JsonSourceTableInfo.java b/file/file-source/src/main/java/com/dtstack/flink/sql/source/file/table/JsonSourceTableInfo.java deleted file mode 100644 index 3673c1b7d..000000000 --- a/file/file-source/src/main/java/com/dtstack/flink/sql/source/file/table/JsonSourceTableInfo.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.source.file.table; - -import org.apache.flink.api.common.serialization.DeserializationSchema; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.formats.json.JsonRowDeserializationSchema; -import org.apache.flink.types.Row; - -/** - * @author tiezhu - * @date 2021/3/22 星期一 - * Company dtstack - */ -public class JsonSourceTableInfo extends FileSourceTableInfo { - public static Builder newBuilder(JsonSourceTableInfo tableInfo) { - return new Builder(tableInfo); - } - - public static class Builder { - private final JsonSourceTableInfo tableInfo; - - public Builder(JsonSourceTableInfo tableInfo) { - this.tableInfo = tableInfo; - } - - public Builder setTypeInformation(TypeInformation typeInformation) { - tableInfo.setTypeInformation(typeInformation); - return this; - } - - public JsonSourceTableInfo buildTableInfo() { - DeserializationSchema deserializationSchema = buildDeserializationSchema(); - tableInfo.setDeserializationSchema(deserializationSchema); - - return tableInfo; - } - - public DeserializationSchema buildDeserializationSchema() { - return new JsonRowDeserializationSchema - .Builder(tableInfo.getTypeInformation()) - .build(); - } - } -} \ No newline at end of file diff --git a/file/file-source/src/test/java/com/dtstack/flink/sql/source/file/FileSourceTest.java b/file/file-source/src/test/java/com/dtstack/flink/sql/source/file/FileSourceTest.java deleted file mode 100644 index 9ef2e7021..000000000 --- a/file/file-source/src/test/java/com/dtstack/flink/sql/source/file/FileSourceTest.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.source.file; - -/** - * @author tiezhu - * @date 2021/3/10 星期三 - * Company dtstack - */ -public class FileSourceTest { -} diff --git a/file/file-source/src/test/java/com/dtstack/flink/sql/source/file/table/FileSourceTableInfoTest.java b/file/file-source/src/test/java/com/dtstack/flink/sql/source/file/table/FileSourceTableInfoTest.java deleted file mode 100644 index a49d80882..000000000 --- a/file/file-source/src/test/java/com/dtstack/flink/sql/source/file/table/FileSourceTableInfoTest.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.source.file.table; - -import com.dtstack.flink.sql.table.AbstractSourceParser; -import com.dtstack.flink.sql.table.AbstractTableInfo; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.formats.csv.CsvRowDeserializationSchema; -import org.apache.flink.types.Row; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import java.util.HashMap; -import java.util.Map; - -/** - * @author tiezhu - * @date 2021/3/10 星期三 - * Company dtstack - */ -public class FileSourceTableInfoTest { - private static final AbstractSourceParser parser = new FileSourceParser(); - Map props; - - @Before - public void setUp() { - props = new HashMap<>(); - props.put("format", "csv"); - props.put("type", "file"); - props.put("filename", "testFile"); - props.put("filepath", "./"); - } - - @Test - public void testGetTableInfoWithCsv() throws Exception { - AbstractTableInfo tableInfo = parser.getTableInfo( - "Test", - "id int, name string", - props - ); - FileSourceTableInfo fileSourceTableInfo = (FileSourceTableInfo) tableInfo; - TypeInformation information = fileSourceTableInfo.buildRowTypeInfo(); - System.out.println(information); - Assert.assertEquals(fileSourceTableInfo.getOperatorName(), "testFile_Test"); - Assert.assertEquals( - CsvRowDeserializationSchema.class, - fileSourceTableInfo.getDeserializationSchema().getClass() - ); - } - -} diff --git a/file/pom.xml b/file/pom.xml deleted file mode 100644 index a4e112404..000000000 --- a/file/pom.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - flink.sql - com.dtstack.flink - 1.0-SNAPSHOT - ../pom.xml - - 4.0.0 - - sql.file - - - file-source - - pom - - - 8 - 8 - - - - - - com.dtstack.flink - sql.core - 1.0-SNAPSHOT - provided - - - - org.apache.flink - flink-avro - ${flink.version} - - - - org.apache.flink - flink-csv - ${flink.version} - - - - org.apache.flink - flink-json - ${flink.version} - - - - \ No newline at end of file diff --git a/hbase/hbase-side/hbase-all-side/pom.xml b/hbase/hbase-side/hbase-all-side/pom.xml index 65f91de99..4a72d0b07 100644 --- a/hbase/hbase-side/hbase-all-side/pom.xml +++ b/hbase/hbase-side/hbase-all-side/pom.xml @@ -50,7 +50,6 @@ shade - false org.apache.hadoop:hadoop-common @@ -87,14 +86,14 @@ - + - + diff --git a/hbase/hbase-side/hbase-all-side/src/main/java/com/dtstack/flink/sql/side/hbase/HbaseAllReqRow.java b/hbase/hbase-side/hbase-all-side/src/main/java/com/dtstack/flink/sql/side/hbase/HbaseAllReqRow.java index 1827fdbaf..0fe2d1720 100644 --- a/hbase/hbase-side/hbase-all-side/src/main/java/com/dtstack/flink/sql/side/hbase/HbaseAllReqRow.java +++ b/hbase/hbase-side/hbase-all-side/src/main/java/com/dtstack/flink/sql/side/hbase/HbaseAllReqRow.java @@ -20,54 +20,30 @@ package com.dtstack.flink.sql.side.hbase; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.BaseAllReqRow; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; +import com.dtstack.flink.sql.side.*; import com.dtstack.flink.sql.side.hbase.table.HbaseSideTableInfo; -import com.dtstack.flink.sql.side.hbase.utils.HbaseConfigUtils; -import com.dtstack.flink.sql.side.hbase.utils.HbaseUtils; -import com.dtstack.flink.sql.util.RowDataComplete; -import com.google.common.collect.Maps; -import org.apache.calcite.sql.JoinType; import org.apache.commons.collections.map.HashedMap; import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.table.dataformat.BaseRow; -import org.apache.flink.table.dataformat.GenericRow; +import com.google.common.collect.Maps; import org.apache.flink.table.typeutils.TimeIndicatorTypeInfo; +import org.apache.flink.types.Row; import org.apache.flink.util.Collector; import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hbase.AuthUtil; import org.apache.hadoop.hbase.Cell; import org.apache.hadoop.hbase.CellUtil; -import org.apache.hadoop.hbase.ChoreService; -import org.apache.hadoop.hbase.ScheduledChore; import org.apache.hadoop.hbase.TableName; -import org.apache.hadoop.hbase.client.Connection; -import org.apache.hadoop.hbase.client.ConnectionFactory; -import org.apache.hadoop.hbase.client.Result; -import org.apache.hadoop.hbase.client.ResultScanner; -import org.apache.hadoop.hbase.client.Scan; -import org.apache.hadoop.hbase.client.Table; +import org.apache.hadoop.hbase.client.*; import org.apache.hadoop.hbase.util.Bytes; -import org.apache.hadoop.security.UserGroupInformation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import sun.security.krb5.KrbException; -import java.io.File; import java.io.IOException; -import java.security.PrivilegedAction; import java.sql.SQLException; import java.sql.Timestamp; -import java.time.LocalDateTime; -import java.util.Calendar; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.concurrent.atomic.AtomicReference; -public class HbaseAllReqRow extends BaseAllReqRow { +public class HbaseAllReqRow extends AllReqRow { private static final Logger LOG = LoggerFactory.getLogger(HbaseAllReqRow.class); @@ -76,11 +52,8 @@ public class HbaseAllReqRow extends BaseAllReqRow { private Map aliasNameInversion; private AtomicReference>> cacheRef = new AtomicReference<>(); - private Connection conn = null; - private Table table = null; - private ResultScanner resultScanner = null; - public HbaseAllReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { + public HbaseAllReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, SideTableInfo sideTableInfo) { super(new HbaseAllSideInfo(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo)); tableName = ((HbaseSideTableInfo)sideTableInfo).getTableName(); @@ -93,21 +66,17 @@ public HbaseAllReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List sideInputList = (Map) sideInput; - GenericRow row = new GenericRow(sideInfo.getOutFieldInfoList().size()); - row.setHeader(genericRow.getHeader()); + Row row = new Row(sideInfo.getOutFieldInfoList().size()); for(Map.Entry entry : sideInfo.getInFieldIndex().entrySet()){ - Object obj = genericRow.getField(entry.getValue()); + Object obj = input.getField(entry.getValue()); boolean isTimeIndicatorTypeInfo = TimeIndicatorTypeInfo.class.isAssignableFrom(sideInfo.getRowTypeInfo().getTypeAt(entry.getValue()).getClass()); //Type information for indicating event or processing time. However, it behaves like a regular SQL timestamp but is serialized as Long. - if (obj instanceof LocalDateTime && isTimeIndicatorTypeInfo) { - //去除上一层OutputRowtimeProcessFunction 调用时区导致的影响 - obj = ((Timestamp) obj).getTime() + (long)LOCAL_TZ.getOffset(((Timestamp) obj).getTime()); + if(obj instanceof Timestamp && isTimeIndicatorTypeInfo){ + obj = ((Timestamp)obj).getTime(); } - row.setField(entry.getKey(), obj); } @@ -116,10 +85,10 @@ public BaseRow fillData(BaseRow input, Object sideInput) { row.setField(entry.getKey(), null); }else{ String key = sideInfo.getSideFieldNameIndex().get(entry.getKey()); - key = aliasNameInversion.get(key); row.setField(entry.getKey(), sideInputList.get(key)); } } + return row; } @@ -144,128 +113,77 @@ protected void reloadCache() { } @Override - public void flatMap(BaseRow input, Collector out) throws Exception { - GenericRow genericRow = (GenericRow) input; + public void flatMap(Row value, Collector out) throws Exception { Map refData = Maps.newHashMap(); for (int i = 0; i < sideInfo.getEqualValIndex().size(); i++) { Integer conValIndex = sideInfo.getEqualValIndex().get(i); - Object equalObj = genericRow.getField(conValIndex); - if (equalObj == null) { - if (sideInfo.getJoinType() == JoinType.LEFT) { - BaseRow data = fillData(input, null); - RowDataComplete.collectBaseRow(out, data); - } - return; + Object equalObj = value.getField(conValIndex); + if(equalObj == null){ + out.collect(null); } refData.put(sideInfo.getEqualFieldList().get(i), equalObj); } - String rowKeyStr = ((HbaseAllSideInfo) sideInfo).getRowKeyBuilder().getRowKey(refData); + String rowKeyStr = ((HbaseAllSideInfo)sideInfo).getRowKeyBuilder().getRowKey(refData); Map cacheList = null; - AbstractSideTableInfo sideTableInfo = sideInfo.getSideTableInfo(); + SideTableInfo sideTableInfo = sideInfo.getSideTableInfo(); HbaseSideTableInfo hbaseSideTableInfo = (HbaseSideTableInfo) sideTableInfo; - if (hbaseSideTableInfo.isPreRowKey()) { - for (Map.Entry> entry : cacheRef.get().entrySet()) { - if (entry.getKey().startsWith(rowKeyStr)) { + if (hbaseSideTableInfo.isPreRowKey()) + { + for (Map.Entry> entry : cacheRef.get().entrySet()){ + if (entry.getKey().startsWith(rowKeyStr)) + { cacheList = cacheRef.get().get(entry.getKey()); - BaseRow row = fillData(input, cacheList); - RowDataComplete.collectBaseRow(out, row); + Row row = fillData(value, cacheList); + out.collect(row); } } } else { cacheList = cacheRef.get().get(rowKeyStr); - BaseRow row = fillData(input, cacheList); - RowDataComplete.collectBaseRow(out, row); + Row row = fillData(value, cacheList); + out.collect(row); } } private void loadData(Map> tmpCache) throws SQLException { - AbstractSideTableInfo sideTableInfo = sideInfo.getSideTableInfo(); - Map colRefType = ((HbaseAllSideInfo)sideInfo).getColRefType(); + SideTableInfo sideTableInfo = sideInfo.getSideTableInfo(); HbaseSideTableInfo hbaseSideTableInfo = (HbaseSideTableInfo) sideTableInfo; - boolean openKerberos = hbaseSideTableInfo.isKerberosAuthEnable(); - Configuration conf; - int loadDataCount = 0; + Configuration conf = new Configuration(); + conf.set("hbase.zookeeper.quorum", hbaseSideTableInfo.getHost()); + Connection conn = null; + Table table = null; + ResultScanner resultScanner = null; try { - if (openKerberos) { - conf = HbaseConfigUtils.getHadoopConfiguration(hbaseSideTableInfo.getHbaseConfig()); - conf.set(HbaseConfigUtils.KEY_HBASE_ZOOKEEPER_QUORUM, hbaseSideTableInfo.getHost()); - conf.set(HbaseConfigUtils.KEY_HBASE_ZOOKEEPER_ZNODE_QUORUM, hbaseSideTableInfo.getParent()); - - String principal = HbaseConfigUtils.getPrincipal(hbaseSideTableInfo.getHbaseConfig()); - String keytab = HbaseConfigUtils.getKeytab(hbaseSideTableInfo.getHbaseConfig()); - - HbaseConfigUtils.fillSyncKerberosConfig(conf, hbaseSideTableInfo.getHbaseConfig()); - keytab = System.getProperty("user.dir") + File.separator + keytab; - - LOG.info("kerberos principal:{},keytab:{}", principal, keytab); - - conf.set(HbaseConfigUtils.KEY_HBASE_CLIENT_KEYTAB_FILE, keytab); - conf.set(HbaseConfigUtils.KEY_HBASE_CLIENT_KERBEROS_PRINCIPAL, principal); - - UserGroupInformation userGroupInformation = HbaseConfigUtils.loginAndReturnUGI2(conf, principal, keytab); - Configuration finalConf = conf; - conn = userGroupInformation.doAs((PrivilegedAction) () -> { - try { - ScheduledChore authChore = AuthUtil.getAuthChore(finalConf); - if (authChore != null) { - ChoreService choreService = new ChoreService("hbaseKerberosSink"); - choreService.scheduleChore(authChore); - } - - return ConnectionFactory.createConnection(finalConf); - - } catch (IOException e) { - LOG.error("Get connection fail with config:{}", finalConf); - throw new RuntimeException(e); - } - }); - - } else { - conf = HbaseConfigUtils.getConfig(hbaseSideTableInfo.getHbaseConfig()); - conf.set(HbaseConfigUtils.KEY_HBASE_ZOOKEEPER_QUORUM, hbaseSideTableInfo.getHost()); - conf.set(HbaseConfigUtils.KEY_HBASE_ZOOKEEPER_ZNODE_QUORUM, hbaseSideTableInfo.getParent()); - conn = ConnectionFactory.createConnection(conf); - } - + conn = ConnectionFactory.createConnection(conf); table = conn.getTable(TableName.valueOf(tableName)); resultScanner = table.getScanner(new Scan()); for (Result r : resultScanner) { Map kv = new HashedMap(); - for (Cell cell : r.listCells()) { + for (Cell cell : r.listCells()) + { String family = Bytes.toString(CellUtil.cloneFamily(cell)); String qualifier = Bytes.toString(CellUtil.cloneQualifier(cell)); + String value = Bytes.toString(CellUtil.cloneValue(cell)); StringBuilder key = new StringBuilder(); key.append(family).append(":").append(qualifier); - Object value = HbaseUtils.convertByte(CellUtil.cloneValue(cell), colRefType.get(key.toString())); + kv.put(aliasNameInversion.get(key.toString()), value); } - loadDataCount++; tmpCache.put(new String(r.getRow()), kv); } - } catch (IOException | KrbException e) { - throw new RuntimeException(e); + } catch (IOException e) { + e.printStackTrace(); } finally { - LOG.info("load Data count: {}", loadDataCount); try { - if (null != conn) { - conn.close(); - } - - if (null != table) { - table.close(); - } - - if (null != resultScanner) { - resultScanner.close(); - } + conn.close(); + table.close(); + resultScanner.close(); } catch (IOException e) { - LOG.error("", e); + e.printStackTrace(); } } } - } \ No newline at end of file diff --git a/hbase/hbase-side/hbase-all-side/src/main/java/com/dtstack/flink/sql/side/hbase/HbaseAllSideInfo.java b/hbase/hbase-side/hbase-all-side/src/main/java/com/dtstack/flink/sql/side/hbase/HbaseAllSideInfo.java index a57e858c7..ea51f46e4 100644 --- a/hbase/hbase-side/hbase-all-side/src/main/java/com/dtstack/flink/sql/side/hbase/HbaseAllSideInfo.java +++ b/hbase/hbase-side/hbase-all-side/src/main/java/com/dtstack/flink/sql/side/hbase/HbaseAllSideInfo.java @@ -22,71 +22,31 @@ import com.dtstack.flink.sql.side.FieldInfo; import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.BaseSideInfo; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.hbase.table.HbaseSideTableInfo; +import com.dtstack.flink.sql.side.SideInfo; +import com.dtstack.flink.sql.side.SideTableInfo; import com.dtstack.flink.sql.util.ParseUtils; -import com.google.common.collect.Maps; import org.apache.calcite.sql.SqlNode; import org.apache.flink.api.java.typeutils.RowTypeInfo; import com.google.common.collect.Lists; import java.util.List; -import java.util.Map; -public class HbaseAllSideInfo extends BaseSideInfo { +public class HbaseAllSideInfo extends SideInfo { private RowKeyBuilder rowKeyBuilder; - private Map colRefType; - - public HbaseAllSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { + public HbaseAllSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, SideTableInfo sideTableInfo) { super(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); } @Override - public void parseSelectFields(JoinInfo joinInfo) { - String sideTableName = joinInfo.getSideTableName(); - String nonSideTableName = joinInfo.getNonSideTable(); - List fields = Lists.newArrayList(); - int sideTableFieldIndex = 0; - - for( int i=0; i getColRefType() { - return colRefType; - } - } \ No newline at end of file diff --git a/hbase/hbase-side/hbase-all-side/src/test/java/com/dtstack/flink/sql/side/hbase/HbaseAllReqRowTest.java b/hbase/hbase-side/hbase-all-side/src/test/java/com/dtstack/flink/sql/side/hbase/HbaseAllReqRowTest.java deleted file mode 100644 index e10de2448..000000000 --- a/hbase/hbase-side/hbase-all-side/src/test/java/com/dtstack/flink/sql/side/hbase/HbaseAllReqRowTest.java +++ /dev/null @@ -1,214 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.hbase; - -import com.dtstack.flink.sql.side.BaseAllReqRow; -import com.dtstack.flink.sql.side.BaseAsyncReqRow; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.hbase.table.HbaseSideTableInfo; -import com.dtstack.flink.sql.side.hbase.utils.HbaseConfigUtils; -import com.google.common.collect.Maps; -import org.apache.calcite.sql.JoinType; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.shaded.curator.org.apache.curator.shaded.com.google.common.collect.Lists; -import org.apache.flink.table.dataformat.BaseRow; -import org.apache.flink.table.dataformat.GenericRow; -import org.apache.flink.types.Row; -import org.apache.flink.util.Collector; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hbase.Cell; -import org.apache.hadoop.hbase.CellUtil; -import org.apache.hadoop.hbase.NoTagsKeyValue; -import org.apache.hadoop.hbase.TableName; -import org.apache.hadoop.hbase.client.ClientScanner; -import org.apache.hadoop.hbase.client.Connection; -import org.apache.hadoop.hbase.client.ConnectionFactory; -import org.apache.hadoop.hbase.client.Result; -import org.apache.hadoop.hbase.client.ResultScanner; -import org.apache.hadoop.hbase.client.Scan; -import org.apache.hadoop.hbase.client.Table; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import org.powermock.reflect.Whitebox; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicReference; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.powermock.api.mockito.PowerMockito.mockStatic; -import static org.powermock.api.mockito.PowerMockito.when; -import static org.powermock.api.support.membermodification.MemberMatcher.constructor; -import static org.powermock.api.support.membermodification.MemberModifier.suppress; - -/** - * @author: chuixue - * @create: 2020-07-14 10:01 - * @description: - **/ -@RunWith(PowerMockRunner.class) -@PrepareForTest({HbaseAllReqRow.class - , BaseAllReqRow.class - , RowTypeInfo.class - , JoinInfo.class - , HbaseSideTableInfo.class - , LoggerFactory.class - , ConnectionFactory.class - , CellUtil.class - , HbaseConfigUtils.class}) -public class HbaseAllReqRowTest { - - private HbaseAllReqRow hbaseAllReqRow; - private HbaseSideTableInfo hbaseSideTableInfo; - private List outFieldInfoList = new ArrayList<>(); - private RowTypeInfo rowTypeInfo; - private Map inFieldIndex = Maps.newHashMap(); - private Map sideFieldIndex = Maps.newHashMap(); - private HbaseAllSideInfo sideInfo; - - @Before - public void setup() { - Logger log = mock(Logger.class); - mockStatic(LoggerFactory.class); - JoinInfo joinInfo = mock(JoinInfo.class); - FieldInfo fieldInfo1 = new FieldInfo(); - fieldInfo1.setTable("m"); - fieldInfo1.setFieldName("id"); - fieldInfo1.setTypeInformation(TypeInformation.of(Integer.class)); - FieldInfo fieldInfo2 = new FieldInfo(); - fieldInfo2.setTable("m"); - fieldInfo2.setFieldName("bb"); - fieldInfo2.setTypeInformation(TypeInformation.of(String.class)); - FieldInfo fieldInfo3 = new FieldInfo(); - fieldInfo3.setTable("s"); - fieldInfo3.setFieldName("channel"); - fieldInfo3.setTypeInformation(TypeInformation.of(String.class)); - FieldInfo fieldInfo4 = new FieldInfo(); - fieldInfo4.setTable("s"); - fieldInfo4.setFieldName("name"); - fieldInfo4.setTypeInformation(TypeInformation.of(String.class)); - rowTypeInfo = new RowTypeInfo(new TypeInformation[]{TypeInformation.of(Integer.class), TypeInformation.of(String.class), TypeInformation.of(Integer.class)}, new String[]{"id", "bb", "PROCTIME"}); - outFieldInfoList.add(fieldInfo1); - outFieldInfoList.add(fieldInfo2); - outFieldInfoList.add(fieldInfo3); - outFieldInfoList.add(fieldInfo4); - inFieldIndex.put(0, 0); - inFieldIndex.put(1, 1); - sideFieldIndex.put(2, 0); - sideFieldIndex.put(3, 1); - sideInfo = mock(HbaseAllSideInfo.class); - hbaseSideTableInfo = mock(HbaseSideTableInfo.class); - - String tableName = "bbb"; - Map aliasNameRef = new HashMap<>(); - aliasNameRef.put("cf:channel", "channel"); - aliasNameRef.put("cf:name", "name"); - - when(LoggerFactory.getLogger(BaseAllReqRow.class)).thenReturn(log); - when(LoggerFactory.getLogger(HbaseAllReqRow.class)).thenReturn(log); - suppress(constructor(HbaseAllSideInfo.class)); - suppress(constructor(BaseAsyncReqRow.class)); - when(hbaseSideTableInfo.getTableName()).thenReturn(tableName); - when(hbaseSideTableInfo.getAliasNameRef()).thenReturn(aliasNameRef); - when(sideInfo.getSideTableInfo()).thenReturn(hbaseSideTableInfo); - - hbaseAllReqRow = new HbaseAllReqRow(rowTypeInfo, joinInfo, outFieldInfoList, hbaseSideTableInfo); - - Whitebox.setInternalState(hbaseAllReqRow, "sideInfo", sideInfo); - } - - @Test - public void testFlatMap() throws Exception { - AtomicReference>> cacheRef = new AtomicReference<>(); - Map keyValue = Maps.newConcurrentMap(); - Map value = Maps.newHashMap(); - value.put("name", "dtstack"); - value.put("channel", "bigdata"); - value.put(null, "daishuyun"); - keyValue.put("1", value); - cacheRef.set(keyValue); - - Whitebox.setInternalState(hbaseAllReqRow, "cacheRef", cacheRef); - - GenericRow row = new GenericRow(3); - row.setField(0, 1); - row.setField(1, "bbbbbb"); - row.setField(2, "2020-07-14 01:27:43.969"); - - Collector out = mock(Collector.class); - RowKeyBuilder rowKeyBuilder = mock(RowKeyBuilder.class); - Map rowkeyMap = Maps.newHashMap(); - rowkeyMap.put("rowkey", 1); - - when(sideInfo.getEqualValIndex()).thenReturn(Lists.newArrayList(0)); - when(sideInfo.getJoinType()).thenReturn(JoinType.LEFT); - when(sideInfo.getEqualFieldList()).thenReturn(Lists.newArrayList("rowkey")); - when(sideInfo.getRowKeyBuilder()).thenReturn(rowKeyBuilder); - when(rowKeyBuilder.getRowKey(rowkeyMap)).thenReturn("1"); - when(hbaseSideTableInfo.isPreRowKey()).thenReturn(false); - when(sideInfo.getOutFieldInfoList()).thenReturn(outFieldInfoList); - when(sideInfo.getRowTypeInfo()).thenReturn(rowTypeInfo); - when(sideInfo.getInFieldIndex()).thenReturn(inFieldIndex); - when(sideInfo.getSideFieldIndex()).thenReturn(sideFieldIndex); - - hbaseAllReqRow.flatMap(row, out); - } - - @Test - public void testReloadCache() throws IOException { - mockStatic(ConnectionFactory.class); - Connection connection = mock(Connection.class); - Configuration configuration = mock(Configuration.class); - Table table = mock(Table.class); - ResultScanner resultScanner = mock(ClientScanner.class); - Iterator iterator = mock(Iterator.class); - Result result = mock(Result.class); - List cells = Lists.newArrayList(new NoTagsKeyValue("001/cf:channel/1587606427805/Put/vlen=3/seqid=0".getBytes(), 0, 35)); - mockStatic(CellUtil.class); - mockStatic(HbaseConfigUtils.class); - - when(HbaseConfigUtils.getConfig(new HashMap<>())).thenReturn(configuration); - when(ConnectionFactory.createConnection(any(Configuration.class))).thenReturn(connection); - when(hbaseSideTableInfo.getHost()).thenReturn("localhost:2181"); - when(connection.getTable(any(TableName.class))).thenReturn(table); - when(table.getScanner(any(Scan.class))).thenReturn(resultScanner); - when(resultScanner.iterator()).thenReturn(iterator); - when(iterator.hasNext()).thenReturn(true, false); - when(iterator.next()).thenReturn(result); - when(result.listCells()).thenReturn(cells); - when(result.getRow()).thenReturn("001".getBytes()); - when(CellUtil.cloneFamily(any(NoTagsKeyValue.class))).thenReturn("cf".getBytes()); - when(CellUtil.cloneQualifier(any(NoTagsKeyValue.class))).thenReturn("channel".getBytes()); - when(CellUtil.cloneValue(any(NoTagsKeyValue.class))).thenReturn("001/cf:channel/1587606427805/Put/vlen=3/seqid=0".getBytes()); - - hbaseAllReqRow.reloadCache(); - } -} diff --git a/hbase/hbase-side/hbase-all-side/src/test/java/com/dtstack/flink/sql/side/hbase/HbaseAllSideInfoTest.java b/hbase/hbase-side/hbase-all-side/src/test/java/com/dtstack/flink/sql/side/hbase/HbaseAllSideInfoTest.java deleted file mode 100644 index 3f14c0554..000000000 --- a/hbase/hbase-side/hbase-all-side/src/test/java/com/dtstack/flink/sql/side/hbase/HbaseAllSideInfoTest.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.hbase; - -import com.dtstack.flink.sql.side.BaseSideInfo; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.hbase.table.HbaseSideTableInfo; -import com.dtstack.flink.sql.util.ParseUtils; -import com.google.common.collect.Lists; -import org.apache.calcite.sql.SqlNode; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.api.java.typeutils.TypeExtractor; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.List; - -import static org.mockito.Mockito.mock; -import static org.powermock.api.mockito.PowerMockito.mockStatic; -import static org.powermock.api.mockito.PowerMockito.when; -import static org.powermock.api.support.membermodification.MemberMatcher.constructor; -import static org.powermock.api.support.membermodification.MemberMatcher.method; -import static org.powermock.api.support.membermodification.MemberModifier.suppress; - -/** - * @author: chuixue - * @create: 2020-07-16 20:24 - * @description: - **/ -@RunWith(PowerMockRunner.class) -@PrepareForTest({HbaseAllSideInfo.class - , BaseSideInfo.class - , ParseUtils.class - , TypeExtractor.class - , LoggerFactory.class}) -public class HbaseAllSideInfoTest { - - private HbaseAllSideInfo hbaseAllSideInfo; - - @Test - public void testBuildEqualInfo() { - Logger log = mock(Logger.class); - mockStatic(LoggerFactory.class); - mockStatic(ParseUtils.class); - JoinInfo joinInfo = mock(JoinInfo.class); - HbaseSideTableInfo sideTableInfo = mock(HbaseSideTableInfo.class); - when(sideTableInfo.getColumnRealNames()).thenReturn(new String[]{"cf:a"}); - when(sideTableInfo.getFieldTypes()).thenReturn(new String[]{"varchar"}); - RowTypeInfo rowTypeInfo = new RowTypeInfo(new TypeInformation[]{TypeInformation.of(Integer.class), TypeInformation.of(String.class), TypeInformation.of(Integer.class)}, new String[]{"id", "bb", "PROCTIME"}); - List outFieldInfoList = new ArrayList<>(); - SqlNode sqlNode = mock(SqlNode.class); - - when(LoggerFactory.getLogger(TypeExtractor.class)).thenReturn(log); - suppress(constructor(BaseSideInfo.class)); - when(sideTableInfo.getPrimaryKeys()).thenReturn(Lists.newArrayList("rowkey")); - when(joinInfo.getSideTableName()).thenReturn("s"); - when(joinInfo.getCondition()).thenReturn(sqlNode); - suppress(method(ParseUtils.class, "parseAnd", SqlNode.class, List.class)); - - hbaseAllSideInfo = new HbaseAllSideInfo(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); - hbaseAllSideInfo.buildEqualInfo(joinInfo, sideTableInfo); - - } -} diff --git a/hbase/hbase-side/hbase-async-side/pom.xml b/hbase/hbase-side/hbase-async-side/pom.xml index 2261df9c3..d02498881 100644 --- a/hbase/hbase-side/hbase-async-side/pom.xml +++ b/hbase/hbase-side/hbase-async-side/pom.xml @@ -47,7 +47,6 @@ shade - false org.apache.hadoop:hadoop-common @@ -85,14 +84,14 @@ - + - + diff --git a/hbase/hbase-side/hbase-async-side/src/main/java/com/dtstack/flink/sql/side/hbase/HbaseAsyncReqRow.java b/hbase/hbase-side/hbase-async-side/src/main/java/com/dtstack/flink/sql/side/hbase/HbaseAsyncReqRow.java index 9a2b75808..05751d61e 100644 --- a/hbase/hbase-side/hbase-async-side/src/main/java/com/dtstack/flink/sql/side/hbase/HbaseAsyncReqRow.java +++ b/hbase/hbase-side/hbase-async-side/src/main/java/com/dtstack/flink/sql/side/hbase/HbaseAsyncReqRow.java @@ -20,36 +20,30 @@ package com.dtstack.flink.sql.side.hbase; -import com.dtstack.flink.sql.factory.DTThreadFactory; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.BaseAsyncReqRow; +import com.dtstack.flink.sql.enums.ECacheContentType; +import com.dtstack.flink.sql.side.AsyncReqRow; import com.dtstack.flink.sql.side.FieldInfo; import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.hbase.rowkeydealer.AbstractRowKeyModeDealer; +import com.dtstack.flink.sql.side.SideTableInfo; +import com.dtstack.flink.sql.side.cache.CacheObj; +import com.dtstack.flink.sql.side.hbase.rowkeydealer.AbsRowKeyModeDealer; import com.dtstack.flink.sql.side.hbase.rowkeydealer.PreRowKeyModeDealerDealer; import com.dtstack.flink.sql.side.hbase.rowkeydealer.RowKeyEqualModeDealer; import com.dtstack.flink.sql.side.hbase.table.HbaseSideTableInfo; -import com.dtstack.flink.sql.side.hbase.utils.HbaseConfigUtils; -import com.dtstack.flink.sql.util.DtFileUtils; +import com.dtstack.flink.sql.factory.DTThreadFactory; +import com.google.common.collect.Maps; import com.stumbleupon.async.Deferred; -import org.apache.commons.collections.MapUtils; -import org.apache.commons.lang3.StringUtils; import org.apache.flink.api.java.typeutils.RowTypeInfo; import org.apache.flink.configuration.Configuration; -import org.apache.flink.runtime.security.DynamicConfiguration; -import org.apache.flink.runtime.security.KerberosUtils; import org.apache.flink.streaming.api.functions.async.ResultFuture; -import org.apache.flink.table.dataformat.BaseRow; -import org.apache.flink.table.dataformat.GenericRow; -import org.apache.hadoop.security.authentication.util.KerberosName; -import org.hbase.async.Config; +import org.apache.flink.table.typeutils.TimeIndicatorTypeInfo; +import org.apache.flink.types.Row; import org.hbase.async.HBaseClient; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import sun.security.krb5.KrbException; -import javax.security.auth.login.AppConfigurationEntry; -import java.io.File; +import java.sql.Timestamp; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.concurrent.ExecutorService; @@ -63,7 +57,7 @@ * @author xuchao */ -public class HbaseAsyncReqRow extends BaseAsyncReqRow { +public class HbaseAsyncReqRow extends AsyncReqRow { private static final long serialVersionUID = 2098635104857937717L; @@ -78,57 +72,29 @@ public class HbaseAsyncReqRow extends BaseAsyncReqRow { private transient HBaseClient hBaseClient; - private transient AbstractRowKeyModeDealer rowKeyMode; + private transient AbsRowKeyModeDealer rowKeyMode; private String tableName; private String[] colNames; - public HbaseAsyncReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { + public HbaseAsyncReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, SideTableInfo sideTableInfo) { super(new HbaseAsyncSideInfo(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo)); tableName = ((HbaseSideTableInfo)sideTableInfo).getTableName(); - colNames = StringUtils.split(sideInfo.getSideSelectFields(), ","); + colNames = ((HbaseSideTableInfo)sideTableInfo).getColumnRealNames(); } @Override public void open(Configuration parameters) throws Exception { - super.open(parameters); - AbstractSideTableInfo sideTableInfo = sideInfo.getSideTableInfo(); + SideTableInfo sideTableInfo = sideInfo.getSideTableInfo(); HbaseSideTableInfo hbaseSideTableInfo = (HbaseSideTableInfo) sideTableInfo; - Map hbaseConfig = hbaseSideTableInfo.getHbaseConfig(); - ExecutorService executorService =new ThreadPoolExecutor(DEFAULT_POOL_SIZE, DEFAULT_POOL_SIZE, 0L, TimeUnit.MILLISECONDS, - new LinkedBlockingQueue<>(), new DTThreadFactory("hbase-async")); - - Config config = new Config(); - config.overrideConfig(HbaseConfigUtils.KEY_HBASE_ZOOKEEPER_QUORUM, hbaseSideTableInfo.getHost()); - config.overrideConfig(HbaseConfigUtils.KEY_HBASE_ZOOKEEPER_ZNODE_QUORUM, hbaseSideTableInfo.getParent()); - hbaseConfig.entrySet().forEach(entity -> { - config.overrideConfig(entity.getKey(), (String) entity.getValue()); - }); - - if (HbaseConfigUtils.isEnableKerberos(hbaseConfig)) { - HbaseConfigUtils.loadKrb5Conf(hbaseConfig); - String principal = MapUtils.getString(hbaseConfig, HbaseConfigUtils.KEY_PRINCIPAL); - HbaseConfigUtils.checkOpt(principal, HbaseConfigUtils.KEY_PRINCIPAL); - String regionserverPrincipal = MapUtils.getString(hbaseConfig, HbaseConfigUtils.KEY_HBASE_KERBEROS_REGIONSERVER_PRINCIPAL); - HbaseConfigUtils.checkOpt(regionserverPrincipal, HbaseConfigUtils.KEY_HBASE_KERBEROS_REGIONSERVER_PRINCIPAL); - String keytab = MapUtils.getString(hbaseConfig, HbaseConfigUtils.KEY_KEY_TAB); - HbaseConfigUtils.checkOpt(keytab, HbaseConfigUtils.KEY_KEY_TAB); - String keytabPath = System.getProperty("user.dir") + File.separator + keytab; - DtFileUtils.checkExists(keytabPath); - - LOG.info("Kerberos login with keytab: {} and principal: {}", keytab, principal); - String name = "HBaseClient"; - config.overrideConfig("hbase.sasl.clientconfig", name); - appendJaasConf(name, keytab, principal); - refreshConfig(); - } + new LinkedBlockingQueue<>(), new DTThreadFactory("hbase-aysnc")); - hBaseClient = new HBaseClient(config, executorService); + hBaseClient = new HBaseClient(hbaseSideTableInfo.getHost(), hbaseSideTableInfo.getParent(), executorService); try { Deferred deferred = hBaseClient.ensureTableExists(tableName) @@ -155,42 +121,58 @@ public void open(Configuration parameters) throws Exception { } } - private void refreshConfig() throws KrbException { - sun.security.krb5.Config.refresh(); - KerberosName.resetDefaultRealm(); - //reload java.security.auth.login.config - // javax.security.auth.login.Configuration.setConfiguration(null); - } + @Override + public void asyncInvoke(Row input, ResultFuture resultFuture) throws Exception { + Map refData = Maps.newHashMap(); + for (int i = 0; i < sideInfo.getEqualValIndex().size(); i++) { + Integer conValIndex = sideInfo.getEqualValIndex().get(i); + Object equalObj = input.getField(conValIndex); + if(equalObj == null){ + resultFuture.complete(null); + return; + } - private void appendJaasConf(String name, String keytab, String principal) { - javax.security.auth.login.Configuration priorConfig = javax.security.auth.login.Configuration.getConfiguration(); - // construct a dynamic JAAS configuration - DynamicConfiguration currentConfig = new DynamicConfiguration(priorConfig); - // wire up the configured JAAS login contexts to use the krb5 entries - AppConfigurationEntry krb5Entry = KerberosUtils.keytabEntry(keytab, principal); - currentConfig.addAppConfigurationEntry(name, krb5Entry); - javax.security.auth.login.Configuration.setConfiguration(currentConfig); - } + refData.put(sideInfo.getEqualFieldList().get(i), equalObj); + } - @Override - public void handleAsyncInvoke(Map inputParams, BaseRow input, ResultFuture resultFuture) throws Exception { - rowKeyMode.asyncGetData(tableName, buildCacheKey(inputParams), input, resultFuture, sideInfo.getSideCache()); - } + String rowKeyStr = ((HbaseAsyncSideInfo)sideInfo).getRowKeyBuilder().getRowKey(refData); + + //get from cache + if(openCache()){ + CacheObj val = getFromCache(rowKeyStr); + if(val != null){ + if(ECacheContentType.MissVal == val.getType()){ + dealMissKey(input, resultFuture); + return; + }else if(ECacheContentType.SingleLine == val.getType()){ + Row row = fillData(input, val); + resultFuture.complete(Collections.singleton(row)); + }else if(ECacheContentType.MultiLine == val.getType()){ + for(Object one : (List)val.getContent()){ + Row row = fillData(input, one); + resultFuture.complete(Collections.singleton(row)); + } + } + return; + } + } - @Override - public String buildCacheKey(Map inputParams) { - return ((HbaseAsyncSideInfo)sideInfo).getRowKeyBuilder().getRowKey(inputParams); + rowKeyMode.asyncGetData(tableName, rowKeyStr, input, resultFuture, sideInfo.getSideCache()); } @Override - public BaseRow fillData(BaseRow input, Object sideInput){ - GenericRow genericRow = (GenericRow) input; + public Row fillData(Row input, Object sideInput){ + List sideInputList = (List) sideInput; - GenericRow row = new GenericRow(sideInfo.getOutFieldInfoList().size()); - row.setHeader(genericRow.getHeader()); + Row row = new Row(sideInfo.getOutFieldInfoList().size()); for(Map.Entry entry : sideInfo.getInFieldIndex().entrySet()){ - Object obj = genericRow.getField(entry.getValue()); - obj = convertTimeIndictorTypeInfo(entry.getValue(), obj); + Object obj = input.getField(entry.getValue()); + boolean isTimeIndicatorTypeInfo = TimeIndicatorTypeInfo.class.isAssignableFrom(sideInfo.getRowTypeInfo().getTypeAt(entry.getValue()).getClass()); + + if(obj instanceof Timestamp && isTimeIndicatorTypeInfo){ + obj = ((Timestamp)obj).getTime(); + } + row.setField(entry.getKey(), obj); } @@ -211,6 +193,7 @@ public void close() throws Exception { hBaseClient.shutdown(); } + class CheckResult{ private boolean connect; diff --git a/hbase/hbase-side/hbase-async-side/src/main/java/com/dtstack/flink/sql/side/hbase/HbaseAsyncSideInfo.java b/hbase/hbase-side/hbase-async-side/src/main/java/com/dtstack/flink/sql/side/hbase/HbaseAsyncSideInfo.java index bdff97e74..2bfdd0d44 100644 --- a/hbase/hbase-side/hbase-async-side/src/main/java/com/dtstack/flink/sql/side/hbase/HbaseAsyncSideInfo.java +++ b/hbase/hbase-side/hbase-async-side/src/main/java/com/dtstack/flink/sql/side/hbase/HbaseAsyncSideInfo.java @@ -2,8 +2,8 @@ import com.dtstack.flink.sql.side.FieldInfo; import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.BaseSideInfo; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; +import com.dtstack.flink.sql.side.SideInfo; +import com.dtstack.flink.sql.side.SideTableInfo; import com.dtstack.flink.sql.side.hbase.table.HbaseSideTableInfo; import com.dtstack.flink.sql.util.ParseUtils; import org.apache.calcite.sql.SqlNode; @@ -21,7 +21,7 @@ * @author xuchao */ -public class HbaseAsyncSideInfo extends BaseSideInfo { +public class HbaseAsyncSideInfo extends SideInfo { private static final long serialVersionUID = 257688427401088045L; @@ -29,46 +29,19 @@ public class HbaseAsyncSideInfo extends BaseSideInfo { private Map colRefType; - public HbaseAsyncSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { + public HbaseAsyncSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, SideTableInfo sideTableInfo) { super(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); } @Override - public void parseSelectFields(JoinInfo joinInfo) { - String sideTableName = joinInfo.getSideTableName(); - String nonSideTableName = joinInfo.getNonSideTable(); - List fields = Lists.newArrayList(); - int sideTableFieldIndex = 0; - - for( int i=0; i colRefType; @@ -60,9 +59,9 @@ public abstract class AbstractRowKeyModeDealer { protected Map sideFieldIndex = Maps.newHashMap(); - public AbstractRowKeyModeDealer(Map colRefType, String[] colNames, HBaseClient hBaseClient, - boolean openCache, JoinType joinType, List outFieldInfoList, - Map inFieldIndex, Map sideFieldIndex){ + public AbsRowKeyModeDealer(Map colRefType, String[] colNames, HBaseClient hBaseClient, + boolean openCache, JoinType joinType, List outFieldInfoList, + Map inFieldIndex, Map sideFieldIndex){ this.colRefType = colRefType; this.colNames = colNames; this.hBaseClient = hBaseClient; @@ -73,27 +72,25 @@ public AbstractRowKeyModeDealer(Map colRefType, String[] colName this.sideFieldIndex = sideFieldIndex; } - protected void dealMissKey(BaseRow input, ResultFuture resultFuture) { - if (joinType == JoinType.LEFT) { - try { - //保留left 表数据 - BaseRow row = fillData(input, null); - RowDataComplete.completeBaseRow(resultFuture, row); - } catch (Exception e) { - resultFuture.completeExceptionally(e); - } - } else { - resultFuture.complete(Collections.EMPTY_LIST); + protected void dealMissKey(Row input, ResultFuture resultFuture){ + if(joinType == JoinType.LEFT){ + //保留left 表数据 + Row row = fillData(input, null); + resultFuture.complete(Collections.singleton(row)); + }else{ + resultFuture.complete(null); } } - protected BaseRow fillData(BaseRow input, Object sideInput){ - GenericRow genericRow = (GenericRow) input; + protected Row fillData(Row input, Object sideInput){ + List sideInputList = (List) sideInput; - GenericRow row = new GenericRow(outFieldInfoList.size()); - row.setHeader(genericRow.getHeader()); + Row row = new Row(outFieldInfoList.size()); for(Map.Entry entry : inFieldIndex.entrySet()){ - Object obj = genericRow.getField(entry.getValue()); + Object obj = input.getField(entry.getValue()); + if(obj instanceof Timestamp){ + obj = ((Timestamp)obj).getTime(); + } row.setField(entry.getKey(), obj); } @@ -108,6 +105,6 @@ protected BaseRow fillData(BaseRow input, Object sideInput){ return row; } - public abstract void asyncGetData(String tableName, String rowKeyStr, BaseRow input, ResultFuture resultFuture, - AbstractSideCache sideCache); + public abstract void asyncGetData(String tableName, String rowKeyStr, Row input, ResultFuture resultFuture, + AbsSideCache sideCache); } diff --git a/hbase/hbase-side/hbase-async-side/src/main/java/com/dtstack/flink/sql/side/hbase/rowkeydealer/PreRowKeyModeDealerDealer.java b/hbase/hbase-side/hbase-async-side/src/main/java/com/dtstack/flink/sql/side/hbase/rowkeydealer/PreRowKeyModeDealerDealer.java index dd4794c0e..b75bca40c 100644 --- a/hbase/hbase-side/hbase-async-side/src/main/java/com/dtstack/flink/sql/side/hbase/rowkeydealer/PreRowKeyModeDealerDealer.java +++ b/hbase/hbase-side/hbase-async-side/src/main/java/com/dtstack/flink/sql/side/hbase/rowkeydealer/PreRowKeyModeDealerDealer.java @@ -23,15 +23,14 @@ import com.dtstack.flink.sql.enums.ECacheContentType; import com.dtstack.flink.sql.side.CacheMissVal; import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.cache.AbstractSideCache; +import com.dtstack.flink.sql.side.cache.AbsSideCache; import com.dtstack.flink.sql.side.cache.CacheObj; import com.dtstack.flink.sql.side.hbase.utils.HbaseUtils; -import com.dtstack.flink.sql.util.RowDataComplete; -import com.google.common.collect.Lists; import com.google.common.collect.Maps; import org.apache.calcite.sql.JoinType; +import com.google.common.collect.Lists; import org.apache.flink.streaming.api.functions.async.ResultFuture; -import org.apache.flink.table.dataformat.BaseRow; +import org.apache.flink.types.Row; import org.hbase.async.BinaryPrefixComparator; import org.hbase.async.Bytes; import org.hbase.async.CompareFilter; @@ -55,7 +54,7 @@ * @author xuchao */ -public class PreRowKeyModeDealerDealer extends AbstractRowKeyModeDealer { +public class PreRowKeyModeDealerDealer extends AbsRowKeyModeDealer { private static final Logger LOG = LoggerFactory.getLogger(PreRowKeyModeDealerDealer.class); @@ -66,8 +65,8 @@ public PreRowKeyModeDealerDealer(Map colRefType, String[] colNam } @Override - public void asyncGetData(String tableName, String rowKeyStr, BaseRow input, ResultFuture resultFuture, - AbstractSideCache sideCache) { + public void asyncGetData(String tableName, String rowKeyStr, Row input, ResultFuture resultFuture, + AbsSideCache sideCache) { Scanner prefixScanner = hBaseClient.newScanner(tableName); ScanFilter scanFilter = new RowFilter(CompareFilter.CompareOp.EQUAL, new BinaryPrefixComparator(Bytes.UTF8(rowKeyStr))); prefixScanner.setFilter(scanFilter); @@ -80,8 +79,7 @@ public void asyncGetData(String tableName, String rowKeyStr, BaseRow input, Resu } - private String dealOneRow(ArrayList> args, String rowKeyStr, BaseRow input, - ResultFuture resultFuture, AbstractSideCache sideCache) { + private String dealOneRow(ArrayList> args, String rowKeyStr, Row input, ResultFuture resultFuture, AbsSideCache sideCache) { if(args == null || args.size() == 0){ dealMissKey(input, resultFuture); if (openCache) { @@ -90,7 +88,7 @@ private String dealOneRow(ArrayList> args, String rowKeyStr, } List cacheContent = Lists.newArrayList(); - List rowList = Lists.newArrayList(); + List rowList = Lists.newArrayList(); for(List oneRow : args){ try { @@ -105,44 +103,35 @@ private String dealOneRow(ArrayList> args, String rowKeyStr, Object val = HbaseUtils.convertByte(keyValue.value(), colType); sideMap.put(mapKey, val); } - try { - if (oneRow.size() > 0) { - //The order of the fields defined in the data conversion table - List sideVal = Lists.newArrayList(); - for (String key : colNames) { - - if (!sideMap.containsKey(key)) { - sideVal.add(rowKeyStr); - continue; - } - - Object val = sideMap.get(key); - if (val == null) { - LOG.error("can't get data with column {}", key); - } - - sideVal.add(val); - } - BaseRow row = fillData(input, sideVal); - if (openCache) { - cacheContent.add(sideVal); + if (oneRow.size() > 0) { + //The order of the fields defined in the data conversion table + List sideVal = Lists.newArrayList(); + for (String key : colNames) { + Object val = sideMap.get(key); + if (val == null) { + System.out.println("can't get data with column " + key); + LOG.error("can't get data with column " + key); } - rowList.add(row); + sideVal.add(val); + } + + Row row = fillData(input, sideVal); + if (openCache) { + cacheContent.add(sideVal); } - }catch (Exception e) { - resultFuture.completeExceptionally(e); + rowList.add(row); } } catch (Exception e) { - resultFuture.complete(Collections.EMPTY_LIST); + resultFuture.complete(null); LOG.error("record:" + input); LOG.error("get side record exception:", e); } } if (rowList.size() > 0){ - RowDataComplete.completeBaseRow(resultFuture, rowList); + resultFuture.complete(rowList); } if(openCache){ @@ -152,10 +141,10 @@ private String dealOneRow(ArrayList> args, String rowKeyStr, return ""; } - private String dealFail(Object arg2, BaseRow input, ResultFuture resultFuture){ + private String dealFail(Object arg2, Row input, ResultFuture resultFuture){ LOG.error("record:" + input); LOG.error("get side record exception:" + arg2); - resultFuture.complete(Collections.EMPTY_LIST); + resultFuture.complete(null); return ""; } } diff --git a/hbase/hbase-side/hbase-async-side/src/main/java/com/dtstack/flink/sql/side/hbase/rowkeydealer/RowKeyEqualModeDealer.java b/hbase/hbase-side/hbase-async-side/src/main/java/com/dtstack/flink/sql/side/hbase/rowkeydealer/RowKeyEqualModeDealer.java index 7d8682bd8..8604db18e 100644 --- a/hbase/hbase-side/hbase-async-side/src/main/java/com/dtstack/flink/sql/side/hbase/rowkeydealer/RowKeyEqualModeDealer.java +++ b/hbase/hbase-side/hbase-async-side/src/main/java/com/dtstack/flink/sql/side/hbase/rowkeydealer/RowKeyEqualModeDealer.java @@ -23,15 +23,14 @@ import com.dtstack.flink.sql.enums.ECacheContentType; import com.dtstack.flink.sql.side.CacheMissVal; import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.cache.AbstractSideCache; +import com.dtstack.flink.sql.side.cache.AbsSideCache; import com.dtstack.flink.sql.side.cache.CacheObj; import com.dtstack.flink.sql.side.hbase.utils.HbaseUtils; -import com.dtstack.flink.sql.util.RowDataComplete; -import com.google.common.collect.Lists; import com.google.common.collect.Maps; import org.apache.calcite.sql.JoinType; +import com.google.common.collect.Lists; import org.apache.flink.streaming.api.functions.async.ResultFuture; -import org.apache.flink.table.dataformat.BaseRow; +import org.apache.flink.types.Row; import org.hbase.async.GetRequest; import org.hbase.async.HBaseClient; import org.hbase.async.KeyValue; @@ -49,7 +48,7 @@ * @author xuchao */ -public class RowKeyEqualModeDealer extends AbstractRowKeyModeDealer { +public class RowKeyEqualModeDealer extends AbsRowKeyModeDealer { private static final Logger LOG = LoggerFactory.getLogger(RowKeyEqualModeDealer.class); @@ -61,8 +60,8 @@ public RowKeyEqualModeDealer(Map colRefType, String[] colNames, @Override - public void asyncGetData(String tableName, String rowKeyStr, BaseRow input, ResultFuture resultFuture, - AbstractSideCache sideCache){ + public void asyncGetData(String tableName, String rowKeyStr, Row input, ResultFuture resultFuture, + AbsSideCache sideCache){ //TODO 是否有查询多个col family 和多个col的方法 GetRequest getRequest = new GetRequest(tableName, rowKeyStr); hBaseClient.get(getRequest).addCallbacks(arg -> { @@ -80,34 +79,28 @@ public void asyncGetData(String tableName, String rowKeyStr, BaseRow input, Resu } if(arg.size() > 0){ - try { - //The order of the fields defined in the data conversion table - List sideVal = Lists.newArrayList(); - for(String key : colNames){ - - if (!sideMap.containsKey(key)) { - sideVal.add(rowKeyStr); - continue; - } - - Object val = sideMap.get(key); - if(val == null){ - LOG.error("can't get data with column {}", key); - } - - sideVal.add(val); + //The order of the fields defined in the data conversion table + List sideVal = Lists.newArrayList(); + for(String key : colNames){ + Object val = sideMap.get(key); + if(val == null){ + System.out.println("can't get data with column " + key); + LOG.error("can't get data with column " + key); } - BaseRow row = fillData(input, sideVal); - if(openCache){ - sideCache.putCache(rowKeyStr, CacheObj.buildCacheObj(ECacheContentType.SingleLine, sideVal)); - } - RowDataComplete.completeBaseRow(resultFuture, row); - } catch (Exception e) { - resultFuture.completeExceptionally(e); + sideVal.add(val); } + + Row row = fillData(input, sideVal); + if(openCache){ + sideCache.putCache(rowKeyStr, CacheObj.buildCacheObj(ECacheContentType.SingleLine, row)); + } + + resultFuture.complete(Collections.singleton(row)); }else{ + dealMissKey(input, resultFuture); + if(openCache){ sideCache.putCache(rowKeyStr, CacheMissVal.getMissKeyObj()); } @@ -122,7 +115,7 @@ public void asyncGetData(String tableName, String rowKeyStr, BaseRow input, Resu }, arg2 -> { LOG.error("record:" + input); LOG.error("get side record exception:" + arg2); - resultFuture.complete(Collections.EMPTY_LIST); + resultFuture.complete(null); return ""; }); } diff --git a/hbase/hbase-side/hbase-async-side/src/test/java/com/dtstack/flink/sql/side/hbase/HbaseAsyncReqRowTest.java b/hbase/hbase-side/hbase-async-side/src/test/java/com/dtstack/flink/sql/side/hbase/HbaseAsyncReqRowTest.java deleted file mode 100644 index 1f53d20a7..000000000 --- a/hbase/hbase-side/hbase-async-side/src/test/java/com/dtstack/flink/sql/side/hbase/HbaseAsyncReqRowTest.java +++ /dev/null @@ -1,269 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.hbase; - -import com.dtstack.flink.sql.side.BaseAsyncReqRow; -import com.dtstack.flink.sql.side.BaseSideInfo; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.hbase.table.HbaseSideTableInfo; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.stumbleupon.async.Callback; -import com.stumbleupon.async.Deferred; -import org.apache.calcite.config.Lex; -import org.apache.calcite.sql.SqlJoin; -import org.apache.calcite.sql.SqlNode; -import org.apache.calcite.sql.SqlSelect; -import org.apache.calcite.sql.parser.SqlParseException; -import org.apache.calcite.sql.parser.SqlParser; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.configuration.Configuration; -import org.apache.flink.streaming.api.functions.async.ResultFuture; -import org.apache.flink.table.dataformat.BaseRow; -import org.apache.flink.table.dataformat.GenericRow; -import org.apache.flink.types.Row; -import org.hbase.async.GetRequest; -import org.hbase.async.HBaseClient; -import org.hbase.async.KeyValue; -import org.hbase.async.Scanner; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static org.junit.Assert.assertNotEquals; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.powermock.api.mockito.PowerMockito.mock; -import static org.powermock.api.mockito.PowerMockito.whenNew; - -/** - * @author: chuixue - * @create: 2020-07-10 19:00 - * @description: - **/ -@RunWith(PowerMockRunner.class) -@PrepareForTest({HbaseAsyncReqRow.class - , HBaseClient.class - , Deferred.class - , HbaseAsyncReqRow.CheckResult.class - , LoggerFactory.class - , Scanner.class}) -public class HbaseAsyncReqRowTest { - - private HbaseAsyncReqRow hbaseAsyncReqRow; - private RowTypeInfo rowTypeInfo = getRowTypeInfo(); - private HbaseSideTableInfo sideTableInfo = getSideTableInfo(); - private JoinInfo joinInfo = getJoinInfo(); - private List outFieldInfoList = getOutFieldInfoList(); - private HBaseClient hBaseClient; - private Deferred deferred; - private Configuration parameters = new Configuration(); - private Map inputParams = Maps.newHashMap(); - private GenericRow cRow = new GenericRow(3); - private ArrayList keyValues = Lists.newArrayList(); - private ArrayList> preKeyValues = Lists.newArrayList(); - private Deferred deferredDealer; - private ResultFuture resultFuture; - - @Captor - private ArgumentCaptor>> rowkeycb; - @Captor - private ArgumentCaptor>>> preRowkeycb; - @Captor - private ArgumentCaptor> eb; - - @Before - public void setup() throws Exception { - inputParams.put("rowkey", 1); - cRow.setField(0, 1); - cRow.setField(1, "bbbbbb"); - cRow.setField(2, "2020-07-14 01:27:43.969"); - - keyValues.add(new KeyValue("1".getBytes(), "cf".getBytes(), "channel".getBytes(), 1591917901129L, "bigtdata".getBytes())); - preKeyValues.add(keyValues); - - deferredDealer = mock(Deferred.class); - hBaseClient = mock(HBaseClient.class); - deferred = mock(Deferred.class); - HbaseAsyncReqRow.CheckResult result = mock(HbaseAsyncReqRow.CheckResult.class); - resultFuture = mock(ResultFuture.class); - - when(hBaseClient.get(any(GetRequest.class))).thenReturn(deferredDealer); - PowerMockito.suppress(BaseAsyncReqRow.class.getMethod("open", Configuration.class)); - whenNew(HBaseClient.class).withAnyArguments().thenReturn(hBaseClient); - when(hBaseClient.ensureTableExists(any(String.class))).thenReturn(deferred); - when(deferred.addCallbacks(any(), any())).thenReturn(deferred); - when(deferred.join()).thenReturn(result); - when(result.isConnect()).thenReturn(true); - sideTableInfo.setPreRowKey(false); - - hbaseAsyncReqRow = new HbaseAsyncReqRow(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); - hbaseAsyncReqRow.open(parameters); - } - - @Test - public void testHandleAsyncInvokeRowkey() throws Exception { - hbaseAsyncReqRow.handleAsyncInvoke(inputParams, cRow, resultFuture); - verify(deferredDealer).addCallbacks(rowkeycb.capture(), eb.capture()); - assertNotEquals(hbaseAsyncReqRow.new CheckResult(true, "msg"), rowkeycb.getValue().call(keyValues)); - } - - @Test - public void testHandleAsyncInvokePreRowkey() throws Exception { - Scanner prefixScanner = mock(Scanner.class); - - sideTableInfo.setPreRowKey(true); - hbaseAsyncReqRow = new HbaseAsyncReqRow(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); - hbaseAsyncReqRow.open(parameters); - - when(hBaseClient.newScanner("bbb")).thenReturn(prefixScanner); - when(prefixScanner.nextRows()).thenReturn(deferredDealer); - hbaseAsyncReqRow.handleAsyncInvoke(inputParams, cRow, resultFuture); - - verify(deferredDealer).addCallbacks(preRowkeycb.capture(), eb.capture()); - - HbaseAsyncReqRow.CheckResult checkResult = hbaseAsyncReqRow.new CheckResult(false, "msg"); - checkResult.setConnect(true); - checkResult.setExceptionMsg("error"); - assertNotEquals(checkResult, preRowkeycb.getValue().call(preKeyValues)); - } - - - public List getOutFieldInfoList() { - List outFieldInfoList = new ArrayList<>(); - FieldInfo fieldInfoa = new FieldInfo(); - fieldInfoa.setTable("m"); - fieldInfoa.setFieldName("id"); - fieldInfoa.setTypeInformation(TypeInformation.of(Integer.class)); - outFieldInfoList.add(fieldInfoa); - FieldInfo fieldInfob = new FieldInfo(); - fieldInfob.setTable("m"); - fieldInfob.setFieldName("bb"); - fieldInfob.setTypeInformation(TypeInformation.of(String.class)); - outFieldInfoList.add(fieldInfob); - FieldInfo fieldInfoc = new FieldInfo(); - fieldInfoc.setTable("s"); - fieldInfoc.setFieldName("channel"); - fieldInfoc.setTypeInformation(TypeInformation.of(String.class)); - outFieldInfoList.add(fieldInfoc); - FieldInfo fieldInfod = new FieldInfo(); - fieldInfod.setTable("s"); - fieldInfod.setFieldName("name"); - fieldInfod.setTypeInformation(TypeInformation.of(String.class)); - outFieldInfoList.add(fieldInfod); - return outFieldInfoList; - } - - public JoinInfo getJoinInfo() { - String sql = "select \n" + - " m.id as mid \n" + - " ,m.bb mbb \n" + - " ,s.channel as sid\n" + - " ,s.name as sbb \n" + - " from MyTable m left join hbaseSide s\n" + - " on m.id = s.rowkey"; - SqlParser.Config config = SqlParser - .configBuilder() - .setLex(Lex.MYSQL) - .build(); - SqlParser sqlParser = SqlParser.create(sql, config); - SqlNode sqlNode = null; - try { - sqlNode = sqlParser.parseStmt(); - } catch (SqlParseException e) { - throw new RuntimeException("", e); - } - - JoinInfo joinInfo = new JoinInfo(); - joinInfo.setLeftIsSideTable(false); - joinInfo.setRightIsSideTable(true); - joinInfo.setLeftTableName("MyTable"); - joinInfo.setLeftTableAlias("m"); - joinInfo.setRightTableName("hbaseSide"); - joinInfo.setRightTableAlias("s"); - joinInfo.setLeftNode(((SqlJoin) ((SqlSelect) sqlNode).getFrom()).getLeft()); - joinInfo.setRightNode(((SqlJoin) ((SqlSelect) sqlNode).getFrom()).getRight()); - joinInfo.setCondition(((SqlJoin) ((SqlSelect) sqlNode).getFrom()).getCondition()); - joinInfo.setSelectFields(((SqlSelect) sqlNode).getSelectList()); - joinInfo.setSelectNode(((SqlSelect) sqlNode).getSelectList()); - joinInfo.setJoinType(((SqlJoin) ((SqlSelect) sqlNode).getFrom()).getJoinType()); - joinInfo.setScope("0"); - Map leftSelectField = new HashMap(); - leftSelectField.put("bb", "bb"); - leftSelectField.put("id", "id"); - joinInfo.setLeftSelectFieldInfo(leftSelectField); - Map rightSelectField = new HashMap(); - rightSelectField.put("channel", "channel"); - rightSelectField.put("name", "name"); - rightSelectField.put("rowkey", "rowkey"); - joinInfo.setRightSelectFieldInfo(rightSelectField); - return joinInfo; - } - - public HbaseSideTableInfo getSideTableInfo() { - HbaseSideTableInfo sideTableInfo = new HbaseSideTableInfo(); - sideTableInfo.setHost("localhost:2181"); - sideTableInfo.setParent("/hbase"); - sideTableInfo.setTableName("bbb"); - sideTableInfo.setColumnRealNames(new String[]{"cf:channel", "cf:name"}); - sideTableInfo.addColumnRealName("cf:channel"); - sideTableInfo.addColumnRealName("cf:name"); - sideTableInfo.putAliasNameRef("channel", "cf:channel"); - sideTableInfo.putAliasNameRef("name", "cf:name"); - sideTableInfo.setName("hbaseSide"); - sideTableInfo.setType("hbase"); - sideTableInfo.setFields(new String[]{"name", "channel"}); - sideTableInfo.setFieldTypes(new String[]{"varchar", "varchar"}); - sideTableInfo.setFieldClasses(new Class[]{String.class, String.class}); - - sideTableInfo.addField("channel"); - sideTableInfo.addField("name"); - sideTableInfo.addPhysicalMappings("channel", "cf:channel"); - sideTableInfo.addPhysicalMappings("name", "cf:name"); - sideTableInfo.addFieldType("channel"); - sideTableInfo.addFieldType("name"); - sideTableInfo.addFieldClass(String.class); - sideTableInfo.addFieldClass(String.class); - sideTableInfo.setPrimaryKeys(Arrays.asList("rowkey")); - return sideTableInfo; - } - - public RowTypeInfo getRowTypeInfo() { - return new RowTypeInfo(new TypeInformation[]{TypeInformation.of(Integer.class), TypeInformation.of(String.class)}, new String[]{"id", "bb"}); - } - - public BaseSideInfo getSideInfo() { - return new HbaseAsyncSideInfo(getRowTypeInfo(), getJoinInfo(), getOutFieldInfoList(), getSideTableInfo()); - } -} diff --git a/hbase/hbase-side/hbase-side-core/src/main/java/com/dtstack/flink/sql/side/hbase/Md5ReplaceOperator.java b/hbase/hbase-side/hbase-side-core/src/main/java/com/dtstack/flink/sql/side/hbase/Md5ReplaceOperator.java index ab826c98f..af5e24dd6 100644 --- a/hbase/hbase-side/hbase-side-core/src/main/java/com/dtstack/flink/sql/side/hbase/Md5ReplaceOperator.java +++ b/hbase/hbase-side/hbase-side-core/src/main/java/com/dtstack/flink/sql/side/hbase/Md5ReplaceOperator.java @@ -30,7 +30,7 @@ * @author xuchao */ -public class Md5ReplaceOperator extends AbstractReplaceOperator { +public class Md5ReplaceOperator extends ReplaceOperator{ public Md5ReplaceOperator(EReplaceOpType opType) { super(opType); diff --git a/hbase/hbase-side/hbase-side-core/src/main/java/com/dtstack/flink/sql/side/hbase/ReplaceInfo.java b/hbase/hbase-side/hbase-side-core/src/main/java/com/dtstack/flink/sql/side/hbase/ReplaceInfo.java index c2d36b5c1..92d8f6d45 100644 --- a/hbase/hbase-side/hbase-side-core/src/main/java/com/dtstack/flink/sql/side/hbase/ReplaceInfo.java +++ b/hbase/hbase-side/hbase-side-core/src/main/java/com/dtstack/flink/sql/side/hbase/ReplaceInfo.java @@ -20,11 +20,10 @@ package com.dtstack.flink.sql.side.hbase; -import java.io.Serializable; -import java.util.List; - import com.dtstack.flink.sql.side.hbase.enums.EReplaceType; +import java.io.Serializable; + /** * Reason: * Date: 2018/8/23 @@ -40,8 +39,6 @@ public class ReplaceInfo implements Serializable { private EReplaceType type; private String param; - - private List subReplaceInfos; public ReplaceInfo(EReplaceType type){ this.type = type; @@ -62,12 +59,4 @@ public String getParam() { public void setParam(String param) { this.param = param; } - - public List getSubReplaceInfos() { - return subReplaceInfos; - } - - public void setSubReplaceInfos(List subReplaceInfos) { - this.subReplaceInfos = subReplaceInfos; - } } diff --git a/hbase/hbase-side/hbase-side-core/src/main/java/com/dtstack/flink/sql/side/hbase/AbstractReplaceOperator.java b/hbase/hbase-side/hbase-side-core/src/main/java/com/dtstack/flink/sql/side/hbase/ReplaceOperator.java similarity index 93% rename from hbase/hbase-side/hbase-side-core/src/main/java/com/dtstack/flink/sql/side/hbase/AbstractReplaceOperator.java rename to hbase/hbase-side/hbase-side-core/src/main/java/com/dtstack/flink/sql/side/hbase/ReplaceOperator.java index c75fa43c1..c3c9b5cfe 100644 --- a/hbase/hbase-side/hbase-side-core/src/main/java/com/dtstack/flink/sql/side/hbase/AbstractReplaceOperator.java +++ b/hbase/hbase-side/hbase-side-core/src/main/java/com/dtstack/flink/sql/side/hbase/ReplaceOperator.java @@ -31,11 +31,11 @@ * @author xuchao */ -public abstract class AbstractReplaceOperator { +public abstract class ReplaceOperator { private EReplaceOpType opType; - public AbstractReplaceOperator(EReplaceOpType opType){ + public ReplaceOperator(EReplaceOpType opType){ this.opType = opType; } diff --git a/hbase/hbase-side/hbase-side-core/src/main/java/com/dtstack/flink/sql/side/hbase/RowKeyBuilder.java b/hbase/hbase-side/hbase-side-core/src/main/java/com/dtstack/flink/sql/side/hbase/RowKeyBuilder.java index ae6c72c98..114b7fa6a 100644 --- a/hbase/hbase-side/hbase-side-core/src/main/java/com/dtstack/flink/sql/side/hbase/RowKeyBuilder.java +++ b/hbase/hbase-side/hbase-side-core/src/main/java/com/dtstack/flink/sql/side/hbase/RowKeyBuilder.java @@ -20,12 +20,8 @@ package com.dtstack.flink.sql.side.hbase; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; import com.dtstack.flink.sql.side.hbase.enums.EReplaceType; -import com.dtstack.flink.sql.util.MD5Utils; -import com.dtstack.flink.sql.util.TableUtils; import com.google.common.collect.Lists; -import org.apache.commons.collections.CollectionUtils; import java.io.Serializable; import java.util.List; @@ -46,17 +42,31 @@ public class RowKeyBuilder implements Serializable{ private static Pattern Md5Operator = Pattern.compile("(?i)^md5\\(\\s*(.*)\\s*\\)$"); - private List operatorChain = Lists.newArrayList(); + private List> operatorChain = Lists.newArrayList(); - private AbstractSideTableInfo sideTableInfo; + public void init(String rowKeyTempl){ - public void init(String rowKeyTempl) { - operatorChain.addAll(makeFormula(rowKeyTempl)); - } + String[] strArr = splitIgnoreQuotaBrackets(rowKeyTempl, "\\+"); + + for(String infoAlias : strArr){ + infoAlias = infoAlias.trim(); + Matcher matcher = Md5Operator.matcher(infoAlias); + String fieldCols = null; + if(matcher.find()){ + fieldCols = matcher.group(1); + }else{ + fieldCols = infoAlias; + } + + String[] fieldArr = fieldCols.split("\\+"); + List fieldList = Lists.newArrayList(); + for(String oneField : fieldArr){ + ReplaceInfo replaceInfo = getReplaceInfo(oneField); + fieldList.add(replaceInfo); + } - public void init(String rowKeyTempl, AbstractSideTableInfo sideTableInfo) { - this.init(rowKeyTempl); - this.sideTableInfo = sideTableInfo; + operatorChain.add(fieldList); + } } /** @@ -64,16 +74,20 @@ public void init(String rowKeyTempl, AbstractSideTableInfo sideTableInfo) { * @param refData * @return */ - public String getRowKey(Map refData) { - TableUtils.addConstant(refData, sideTableInfo); - return buildStr(operatorChain, refData); + public String getRowKey(Map refData){ + + StringBuilder sb = new StringBuilder(""); + for(List fieldList : operatorChain){ + sb.append(buildStr(fieldList, refData)); + } + + return sb.toString(); } + + private String buildStr(List fieldList, Map refData){ - if(CollectionUtils.isEmpty(fieldList)){ - return ""; - } - StringBuilder sb = new StringBuilder(""); + StringBuffer sb = new StringBuffer(""); for(ReplaceInfo replaceInfo : fieldList){ if(replaceInfo.getType() == EReplaceType.CONSTANT){ @@ -81,10 +95,6 @@ private String buildStr(List fieldList, Map refData continue; } - if(replaceInfo.getType() == EReplaceType.FUNC){ - sb.append(MD5Utils.getMD5String(buildStr(replaceInfo.getSubReplaceInfos(), refData))); - continue; - } String replaceName = replaceInfo.getParam(); if(!refData.containsKey(replaceName)){ throw new RuntimeException(String.format("build rowKey with field %s which value not found.", replaceName)); @@ -109,7 +119,7 @@ public static String[] splitIgnoreQuotaBrackets(String str, String delimiter){ public ReplaceInfo getReplaceInfo(String field){ field = field.trim(); - if(field.length() <= 0){ + if(field.length() <= 2){ throw new RuntimeException(field + " \n" + "Format defined exceptions"); } @@ -127,22 +137,4 @@ public ReplaceInfo getReplaceInfo(String field){ return replaceInfo; } - private List makeFormula(String formula){ - if(formula == null || formula.length() <= 0){ - return Lists.newArrayList(); - } - - List result = Lists.newArrayList(); - for(String meta: splitIgnoreQuotaBrackets(formula, "\\+")){ - Matcher matcher = Md5Operator.matcher(meta.trim()); - if(matcher.find()){ - ReplaceInfo replaceInfo = new ReplaceInfo(EReplaceType.FUNC); - replaceInfo.setSubReplaceInfos(makeFormula(matcher.group(1))); - result.add(replaceInfo); - } else { - result.add(getReplaceInfo(meta)); - } - } - return result; - } } diff --git a/hbase/hbase-side/hbase-side-core/src/main/java/com/dtstack/flink/sql/side/hbase/enums/EReplaceOpType.java b/hbase/hbase-side/hbase-side-core/src/main/java/com/dtstack/flink/sql/side/hbase/enums/EReplaceOpType.java index ac9a3b87c..834edf9ae 100644 --- a/hbase/hbase-side/hbase-side-core/src/main/java/com/dtstack/flink/sql/side/hbase/enums/EReplaceOpType.java +++ b/hbase/hbase-side/hbase-side-core/src/main/java/com/dtstack/flink/sql/side/hbase/enums/EReplaceOpType.java @@ -28,12 +28,5 @@ */ public enum EReplaceOpType { - /** - * 没有func - */ - NO_FUNC, - /** - * md5 func - */ - MD5_FUNC; + NO_FUNC, MD5_FUNC; } diff --git a/hbase/hbase-side/hbase-side-core/src/main/java/com/dtstack/flink/sql/side/hbase/enums/EReplaceType.java b/hbase/hbase-side/hbase-side-core/src/main/java/com/dtstack/flink/sql/side/hbase/enums/EReplaceType.java index bb4b1556b..3768d7c5e 100644 --- a/hbase/hbase-side/hbase-side-core/src/main/java/com/dtstack/flink/sql/side/hbase/enums/EReplaceType.java +++ b/hbase/hbase-side/hbase-side-core/src/main/java/com/dtstack/flink/sql/side/hbase/enums/EReplaceType.java @@ -28,16 +28,6 @@ * @author xuchao */ public enum EReplaceType { - /** - * 参数 - */ PARAM, - /** - * 函数 - */ - FUNC, - /** - * 常量 - */ CONSTANT; } diff --git a/hbase/hbase-side/hbase-side-core/src/main/java/com/dtstack/flink/sql/side/hbase/table/HbaseSideParser.java b/hbase/hbase-side/hbase-side-core/src/main/java/com/dtstack/flink/sql/side/hbase/table/HbaseSideParser.java index f7e4f91a0..3031de100 100644 --- a/hbase/hbase-side/hbase-side-core/src/main/java/com/dtstack/flink/sql/side/hbase/table/HbaseSideParser.java +++ b/hbase/hbase-side/hbase-side-core/src/main/java/com/dtstack/flink/sql/side/hbase/table/HbaseSideParser.java @@ -20,15 +20,16 @@ package com.dtstack.flink.sql.side.hbase.table; -import com.dtstack.flink.sql.table.AbstractSideTableParser; -import com.dtstack.flink.sql.table.AbstractTableInfo; +import com.dtstack.flink.sql.table.AbsSideTableParser; +import com.dtstack.flink.sql.table.TableInfo; +import com.dtstack.flink.sql.util.ClassUtil; import com.dtstack.flink.sql.util.MathUtil; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; -import static com.dtstack.flink.sql.table.AbstractTableInfo.PARALLELISM_KEY; +import static com.dtstack.flink.sql.table.TableInfo.PARALLELISM_KEY; /** * hbase field information must include the definition of an alias -> sql which does not allow ":" @@ -37,7 +38,7 @@ * @author xuchao */ -public class HbaseSideParser extends AbstractSideTableParser { +public class HbaseSideParser extends AbsSideTableParser { private final static String FIELD_KEY = "fieldKey"; @@ -47,23 +48,23 @@ public class HbaseSideParser extends AbstractSideTableParser { public static final String ZOOKEEPER_PARENT = "zookeeperParent"; - public static final String KERBEROS_ENABLE = "hbase.security.auth.enable"; - public static final String TABLE_NAME_KEY = "tableName"; public static final String PRE_ROW_KEY = "preRowKey"; public static final String CACHE = "cache"; - public HbaseSideParser() { - addParserHandler(FIELD_KEY, FIELD_PATTERN, this::dealField); + + static { + keyPatternMap.put(FIELD_KEY, FIELD_PATTERN); + keyHandlerMap.put(FIELD_KEY, HbaseSideParser::dealField); } + @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { + public TableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { HbaseSideTableInfo hbaseTableInfo = new HbaseSideTableInfo(); hbaseTableInfo.setName(tableName); - parseCacheProp(hbaseTableInfo, props); parseFieldsInfo(fieldsInfo, hbaseTableInfo); hbaseTableInfo.setTableName((String) props.get(TABLE_NAME_KEY.toLowerCase())); hbaseTableInfo.setParallelism(MathUtil.getIntegerVal(props.get(PARALLELISM_KEY.toLowerCase()))); @@ -71,16 +72,6 @@ public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map entity.getKey().contains(".")) - .map(entity -> hbaseTableInfo.getHbaseConfig().put(entity.getKey(), String.valueOf(entity.getValue()))) - .count(); return hbaseTableInfo; } @@ -90,7 +81,7 @@ public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map columnNameFamily; - private Map hbaseConfig = Maps.newHashMap(); - private String tableName; - private boolean kerberosAuthEnable; - - private String regionserverKeytabFile; - - private String regionserverPrincipal; - - private String jaasPrincipal; - - private String securityKrb5Conf; - - private String zookeeperSaslClient; - private String[] columnRealNames; private List columnRealNameList = Lists.newArrayList(); @@ -162,63 +148,6 @@ public void setPreRowKey(boolean preRowKey) { this.preRowKey = preRowKey; } - public boolean isKerberosAuthEnable() { - return kerberosAuthEnable; - } - - public void setKerberosAuthEnable(boolean kerberosAuthEnable) { - this.kerberosAuthEnable = kerberosAuthEnable; - } - - public String getRegionserverKeytabFile() { - return regionserverKeytabFile; - } - - public void setRegionserverKeytabFile(String regionserverKeytabFile) { - this.regionserverKeytabFile = regionserverKeytabFile; - } - - public String getRegionserverPrincipal() { - return regionserverPrincipal; - } - - public void setRegionserverPrincipal(String regionserverPrincipal) { - this.regionserverPrincipal = regionserverPrincipal; - } - - public String getJaasPrincipal() { - return jaasPrincipal; - } - - public void setJaasPrincipal(String jaasPrincipal) { - this.jaasPrincipal = jaasPrincipal; - } - - public String getSecurityKrb5Conf() { - return securityKrb5Conf; - } - - public void setSecurityKrb5Conf(String securityKrb5Conf) { - this.securityKrb5Conf = securityKrb5Conf; - } - - public String getZookeeperSaslClient() { - return zookeeperSaslClient; - } - - public void setZookeeperSaslClient(String zookeeperSaslClient) { - this.zookeeperSaslClient = zookeeperSaslClient; - } - - public Map getHbaseConfig() { - return hbaseConfig; - } - - public void setHbaseConfig(Map hbaseConfig) { - this.hbaseConfig = hbaseConfig; - } - - @Override public void finish(){ super.finish(); diff --git a/hbase/hbase-side/hbase-side-core/src/main/java/com/dtstack/flink/sql/side/hbase/utils/HbaseConfigUtils.java b/hbase/hbase-side/hbase-side-core/src/main/java/com/dtstack/flink/sql/side/hbase/utils/HbaseConfigUtils.java deleted file mode 100644 index e81cce261..000000000 --- a/hbase/hbase-side/hbase-side-core/src/main/java/com/dtstack/flink/sql/side/hbase/utils/HbaseConfigUtils.java +++ /dev/null @@ -1,234 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.hbase.utils; - -import com.dtstack.flink.sql.util.DtFileUtils; -import com.google.common.base.Preconditions; -import com.google.common.base.Strings; -import org.apache.commons.collections.MapUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hbase.HBaseConfiguration; -import org.apache.hadoop.hbase.exceptions.IllegalArgumentIOException; -import org.apache.hadoop.security.UserGroupInformation; -import org.apache.hadoop.security.authentication.util.KerberosName; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import sun.security.krb5.Config; -import sun.security.krb5.KrbException; - -import java.io.File; -import java.io.IOException; -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -/** - * - * The utility class of HBase connection - * - * Date: 2019/12/24 - * Company: www.dtstack.com - * @author maqi - */ -public class HbaseConfigUtils { - - private static final Logger LOG = LoggerFactory.getLogger(HbaseConfigUtils.class); - // sync side kerberos - private final static String AUTHENTICATION_TYPE = "Kerberos"; - private final static String KEY_HBASE_SECURITY_AUTHENTICATION = "hbase.security.authentication"; - private final static String KEY_HBASE_SECURITY_AUTHORIZATION = "hbase.security.authorization"; - private final static String KEY_HBASE_MASTER_KERBEROS_PRINCIPAL = "hbase.master.kerberos.principal"; - private final static String KEY_HBASE_REGIONSERVER_KERBEROS_PRINCIPAL = "hbase.regionserver.kerberos.principal"; - - public final static String KEY_HBASE_CLIENT_KEYTAB_FILE = "hbase.client.keytab.file"; - public final static String KEY_HBASE_CLIENT_KERBEROS_PRINCIPAL = "hbase.client.kerberos.principal"; - - public static final String KEY_HADOOP_SECURITY_AUTHENTICATION = "hadoop.security.authentication"; - public static final String KEY_HADOOP_SECURITY_AUTH_TO_LOCAL = "hadoop.security.auth_to_local"; - public static final String KEY_HADOOP_SECURITY_AUTHORIZATION = "hadoop.security.authorization"; - - // async side kerberos - private final static String KEY_HBASE_SECURITY_AUTH_ENABLE = "hbase.security.auth.enable"; - public final static String KEY_HBASE_KERBEROS_REGIONSERVER_PRINCIPAL = "hbase.kerberos.regionserver.principal"; - public static final String KEY_KEY_TAB = "hbase.keytab"; - public static final String KEY_PRINCIPAL = "hbase.principal"; - - public final static String KEY_HBASE_ZOOKEEPER_QUORUM = "hbase.zookeeper.quorum"; - public final static String KEY_HBASE_ZOOKEEPER_ZNODE_QUORUM = "hbase.zookeeper.znode.parent"; - - public static final String KEY_ZOOKEEPER_SASL_CLIENT = "zookeeper.sasl.client"; - private static final String KEY_JAVA_SECURITY_KRB5_CONF = "java.security.krb5.conf"; - - private static List KEYS_KERBEROS_REQUIRED = Arrays.asList( - KEY_HBASE_SECURITY_AUTHENTICATION, - KEY_HBASE_KERBEROS_REGIONSERVER_PRINCIPAL, - KEY_PRINCIPAL, - KEY_KEY_TAB, - KEY_JAVA_SECURITY_KRB5_CONF - ); - - public static Configuration getConfig(Map hbaseConfigMap) { - Configuration hConfiguration = HBaseConfiguration.create(); - - for (Map.Entry entry : hbaseConfigMap.entrySet()) { - if (entry.getValue() != null && !(entry.getValue() instanceof Map)) { - hConfiguration.set(entry.getKey(), entry.getValue().toString()); - } - } - return hConfiguration; - } - - public static boolean isEnableKerberos(Map hbaseConfigMap) { - boolean hasAuthorization = AUTHENTICATION_TYPE.equalsIgnoreCase( - MapUtils.getString(hbaseConfigMap, KEY_HBASE_SECURITY_AUTHORIZATION) - ); - boolean hasAuthentication = AUTHENTICATION_TYPE.equalsIgnoreCase( - MapUtils.getString(hbaseConfigMap, KEY_HBASE_SECURITY_AUTHENTICATION) - ); - boolean hasAuthEnable = MapUtils.getBooleanValue(hbaseConfigMap, KEY_HBASE_SECURITY_AUTH_ENABLE); - - if(hasAuthentication || hasAuthorization || hasAuthEnable) { - LOG.info("Enable kerberos for hbase."); - setKerberosConf(hbaseConfigMap); - return true; - } - return false; - } - - private static void setKerberosConf(Map hbaseConfigMap) { - hbaseConfigMap.put(KEY_HBASE_SECURITY_AUTHORIZATION, AUTHENTICATION_TYPE); - hbaseConfigMap.put(KEY_HBASE_SECURITY_AUTHENTICATION, AUTHENTICATION_TYPE); - hbaseConfigMap.put(KEY_HBASE_SECURITY_AUTH_ENABLE, true); - } - - public static Configuration getHadoopConfiguration(Map hbaseConfigMap) { - for (String key : KEYS_KERBEROS_REQUIRED) { - if (StringUtils.isEmpty(MapUtils.getString(hbaseConfigMap, key))) { - throw new IllegalArgumentException(String.format("Must provide [%s] when authentication is Kerberos", key)); - } - } - return HBaseConfiguration.create(); - } - - public static String getPrincipal(Map hbaseConfigMap) { - String principal = MapUtils.getString(hbaseConfigMap, KEY_PRINCIPAL); - if (StringUtils.isNotEmpty(principal)) { - return principal; - } - - throw new IllegalArgumentException(""); - } - - public static String getKeytab(Map hbaseConfigMap) { - String keytab = MapUtils.getString(hbaseConfigMap, KEY_KEY_TAB); - if (StringUtils.isNotEmpty(keytab)) { - return keytab; - } - - throw new IllegalArgumentException(""); - } - - public static void fillSyncKerberosConfig(org.apache.hadoop.conf.Configuration config, Map hbaseConfigMap) throws IOException { - if (StringUtils.isEmpty(MapUtils.getString(hbaseConfigMap, KEY_HBASE_KERBEROS_REGIONSERVER_PRINCIPAL))) { - throw new IllegalArgumentException("Must provide regionserverPrincipal when authentication is Kerberos"); - } - - String regionserverPrincipal = MapUtils.getString(hbaseConfigMap, KEY_HBASE_KERBEROS_REGIONSERVER_PRINCIPAL); - config.set(HbaseConfigUtils.KEY_HBASE_MASTER_KERBEROS_PRINCIPAL, regionserverPrincipal); - config.set(HbaseConfigUtils.KEY_HBASE_REGIONSERVER_KERBEROS_PRINCIPAL, regionserverPrincipal); - config.set(HbaseConfigUtils.KEY_HBASE_SECURITY_AUTHORIZATION, "true"); - config.set(HbaseConfigUtils.KEY_HBASE_SECURITY_AUTHENTICATION, "kerberos"); - - if (!StringUtils.isEmpty(MapUtils.getString(hbaseConfigMap, KEY_ZOOKEEPER_SASL_CLIENT))) { - System.setProperty(HbaseConfigUtils.KEY_ZOOKEEPER_SASL_CLIENT, MapUtils.getString(hbaseConfigMap, KEY_ZOOKEEPER_SASL_CLIENT)); - } - - String securityKrb5Conf = MapUtils.getString(hbaseConfigMap, KEY_JAVA_SECURITY_KRB5_CONF); - if (!StringUtils.isEmpty(securityKrb5Conf)) { - String krb5ConfPath = System.getProperty("user.dir") + File.separator + securityKrb5Conf; - LOG.info("krb5ConfPath:{}", krb5ConfPath); - System.setProperty(HbaseConfigUtils.KEY_JAVA_SECURITY_KRB5_CONF, krb5ConfPath); - } - } - - public static void loadKrb5Conf(Map config) { - String krb5conf = MapUtils.getString(config, KEY_JAVA_SECURITY_KRB5_CONF); - checkOpt(krb5conf, KEY_JAVA_SECURITY_KRB5_CONF); - String krb5FilePath = System.getProperty("user.dir") + File.separator + MapUtils.getString(config, KEY_JAVA_SECURITY_KRB5_CONF); - DtFileUtils.checkExists(krb5FilePath); - System.setProperty(KEY_JAVA_SECURITY_KRB5_CONF, krb5FilePath); - LOG.info("{} is set to {}", KEY_JAVA_SECURITY_KRB5_CONF, krb5FilePath); - } - - // TODO 日后改造可以下沉到Core模块 - public static void checkOpt(String opt, String key) { - Preconditions.checkState(!Strings.isNullOrEmpty(opt), "%s must be set!", key); - } - - public static UserGroupInformation loginAndReturnUGI(Configuration conf, String principal, String keytab) throws IOException { - if (conf == null) { - throw new IllegalArgumentException("kerberos conf can not be null"); - } - - if (org.apache.commons.lang.StringUtils.isEmpty(principal)) { - throw new IllegalArgumentException("principal can not be null"); - } - - if (org.apache.commons.lang.StringUtils.isEmpty(keytab)) { - throw new IllegalArgumentException("keytab can not be null"); - } - - conf.set("hadoop.security.authentication", "Kerberos"); - UserGroupInformation.setConfiguration(conf); - - return UserGroupInformation.loginUserFromKeytabAndReturnUGI(principal, keytab); - } - - public static UserGroupInformation loginAndReturnUGI2(Configuration conf, String principal, String keytab) throws IOException, KrbException { - LOG.info("loginAndReturnUGI principal {}",principal); - LOG.info("loginAndReturnUGI keytab {}",keytab); - if (conf == null) { - throw new IllegalArgumentException("kerberos conf can not be null"); - } - - if (org.apache.commons.lang.StringUtils.isEmpty(principal)) { - throw new IllegalArgumentException("principal can not be null"); - } - - if (org.apache.commons.lang.StringUtils.isEmpty(keytab)) { - throw new IllegalArgumentException("keytab can not be null"); - } - - if (!new File(keytab).exists()){ - throw new IllegalArgumentIOException("keytab ["+ keytab + "] not exist"); - } - - conf.set(KEY_HADOOP_SECURITY_AUTHENTICATION, "Kerberos"); - //conf.set("hadoop.security.auth_to_local", "DEFAULT"); - conf.set(KEY_HADOOP_SECURITY_AUTH_TO_LOCAL, "RULE:[1:$1] RULE:[2:$1]"); - conf.set(KEY_HADOOP_SECURITY_AUTHORIZATION, "true"); - - Config.refresh(); - KerberosName.resetDefaultRealm(); - UserGroupInformation.setConfiguration(conf); - - return UserGroupInformation.loginUserFromKeytabAndReturnUGI(principal, keytab); - } -} diff --git a/hbase/hbase-side/hbase-side-core/src/main/java/com/dtstack/flink/sql/side/hbase/utils/HbaseUtils.java b/hbase/hbase-side/hbase-side-core/src/main/java/com/dtstack/flink/sql/side/hbase/utils/HbaseUtils.java index 5a08b278a..39df3c913 100644 --- a/hbase/hbase-side/hbase-side-core/src/main/java/com/dtstack/flink/sql/side/hbase/utils/HbaseUtils.java +++ b/hbase/hbase-side/hbase-side-core/src/main/java/com/dtstack/flink/sql/side/hbase/utils/HbaseUtils.java @@ -66,12 +66,9 @@ public static Object convertByte(byte[] hbaseData, String type){ case "double": return Bytes.toDouble(hbaseData); - case "decimal": - return Bytes.toBigDecimal(hbaseData); - default: - throw new RuntimeException("not support type of " + type); - } - } + } + throw new RuntimeException("not support type of " + type); + } } diff --git a/hbase/hbase-side/hbase-side-core/src/test/java/com/dtstack/flink/sql/side/hbase/HbaseSideParserTest.java b/hbase/hbase-side/hbase-side-core/src/test/java/com/dtstack/flink/sql/side/hbase/HbaseSideParserTest.java deleted file mode 100644 index d1fb38d99..000000000 --- a/hbase/hbase-side/hbase-side-core/src/test/java/com/dtstack/flink/sql/side/hbase/HbaseSideParserTest.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.hbase; - -import com.dtstack.flink.sql.side.hbase.table.HbaseSideParser; -import org.junit.Test; - -import java.util.HashMap; -import java.util.Map; - -/** - * @author: chuixue - * @create: 2020-07-09 09:19 - * @description: - **/ -public class HbaseSideParserTest { - @Test - public void testGetTableInfo() { - String fieldsInfo = "cf:name varchar as f1," + - " cf:info varchar as f2, " + - " cf:other varchar as f3" + - " , PRIMARY KEY (f1)"; - - Map prop = new HashMap(); - - prop.put("type", "hbase"); - prop.put("zookeeperQuorum", "172.16.101.247:2181"); - prop.put("zookeeperParent", "/hbase"); - prop.put("tableName", "test"); - - HbaseSideParser hbaseSideParser = new HbaseSideParser(); - hbaseSideParser.getTableInfo("tableName", fieldsInfo, prop); - } -} diff --git a/hbase/hbase-side/hbase-side-core/src/test/java/com/dtstack/flink/sql/side/hbase/Md5ReplaceOperatorTest.java b/hbase/hbase-side/hbase-side-core/src/test/java/com/dtstack/flink/sql/side/hbase/Md5ReplaceOperatorTest.java deleted file mode 100644 index 0152e9bf3..000000000 --- a/hbase/hbase-side/hbase-side-core/src/test/java/com/dtstack/flink/sql/side/hbase/Md5ReplaceOperatorTest.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.hbase; - -import com.dtstack.flink.sql.side.hbase.enums.EReplaceOpType; -import com.dtstack.flink.sql.util.MD5Utils; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.InjectMocks; -import org.mockito.MockitoAnnotations; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -import static org.junit.Assert.assertEquals; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.when; - -/** - * @author: chuixue - * @create: 2020-07-07 15:31 - * @description: - **/ -public class Md5ReplaceOperatorTest { - - private Md5ReplaceOperator md5ReplaceOperator; - - @Before - public void setUp() { - md5ReplaceOperator = new Md5ReplaceOperator(EReplaceOpType.MD5_FUNC); - } - - @Test - public void testDoFun() { - String md5 = md5ReplaceOperator.doFunc("md5"); - assertEquals("1bc29b36f623ba82aaf6724fd3b16718", md5); - } -} diff --git a/hbase/hbase-side/hbase-side-core/src/test/java/com/dtstack/flink/sql/side/hbase/RowKeyBuilderTest.java b/hbase/hbase-side/hbase-side-core/src/test/java/com/dtstack/flink/sql/side/hbase/RowKeyBuilderTest.java deleted file mode 100644 index f25b626ee..000000000 --- a/hbase/hbase-side/hbase-side-core/src/test/java/com/dtstack/flink/sql/side/hbase/RowKeyBuilderTest.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.hbase; - -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.hbase.enums.EReplaceType; -import com.dtstack.flink.sql.util.TableUtils; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.InjectMocks; -import org.mockito.MockitoAnnotations; -import org.powermock.api.support.membermodification.MemberModifier; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static org.powermock.api.support.membermodification.MemberMatcher.method; -import static org.powermock.api.support.membermodification.MemberModifier.suppress; - -/** - * @author: chuixue - * @create: 2020-07-08 20:44 - * @description: - **/ -@RunWith(PowerMockRunner.class) -@PrepareForTest({RowKeyBuilder.class, TableUtils.class}) -public class RowKeyBuilderTest { - @InjectMocks - RowKeyBuilder rowKeyBuilder; - - @Before - public void setup() { - MockitoAnnotations.initMocks(this); - } - - @Test - public void testInit() { - rowKeyBuilder.init("md5(rowkey)"); - } - - @Test - public void testGetRowKey() throws IllegalAccessException { - List list = new ArrayList(); - ReplaceInfo replaceInfoa = new ReplaceInfo(EReplaceType.CONSTANT); - replaceInfoa.setParam("f:a"); - - ReplaceInfo replaceInfob = new ReplaceInfo(EReplaceType.FUNC); - replaceInfob.setParam("f:b"); - - ReplaceInfo replaceInfoc = new ReplaceInfo(EReplaceType.PARAM); - replaceInfoc.setParam("f:c"); - list.add(replaceInfoa); - list.add(replaceInfob); - list.add(replaceInfoc); - - MemberModifier.field(RowKeyBuilder.class, "operatorChain").set(rowKeyBuilder, list); - - Map columnNameFamily = new HashMap(); - columnNameFamily.put("f:a", "a"); - columnNameFamily.put("f:b", "b"); - columnNameFamily.put("f:c", "c"); - - suppress(method(TableUtils.class, "addConstant", Map.class, AbstractSideTableInfo.class)); - - rowKeyBuilder.getRowKey(columnNameFamily); - } -} diff --git a/hbase/hbase-side/hbase-side-core/src/test/java/com/dtstack/flink/sql/side/hbase/utils/HbaseConfigUtilsTest.java b/hbase/hbase-side/hbase-side-core/src/test/java/com/dtstack/flink/sql/side/hbase/utils/HbaseConfigUtilsTest.java deleted file mode 100644 index 6eb2d11f6..000000000 --- a/hbase/hbase-side/hbase-side-core/src/test/java/com/dtstack/flink/sql/side/hbase/utils/HbaseConfigUtilsTest.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.hbase.utils; - -import com.dtstack.flink.sql.util.DtFileUtils; -import com.google.common.collect.Maps; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.security.UserGroupInformation; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -import java.io.File; -import java.util.Map; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.powermock.api.mockito.PowerMockito.whenNew; -import static org.powermock.api.support.membermodification.MemberMatcher.method; -import static org.powermock.api.support.membermodification.MemberModifier.suppress; - -/** - * @author: chuixue - * @create: 2020-08-12 15:35 - * @description: - **/ -@RunWith(PowerMockRunner.class) -@PrepareForTest({HbaseConfigUtils.class, - UserGroupInformation.class, - DtFileUtils.class}) -public class HbaseConfigUtilsTest { - - @Test - public void testIsEnableKerberos(){ - Map hbaseConfigMap = Maps.newHashMap(); - hbaseConfigMap.put("hbase.security.authentication","Kerberos"); - HbaseConfigUtils.isEnableKerberos(hbaseConfigMap); - } - - // @Test - public void testGetHadoopConfiguration(){ - Map hbaseConfigMap = Maps.newHashMap(); - hbaseConfigMap.put("hbase.security.authentication","hbase.security.authentication"); - hbaseConfigMap.put("hbase.master.kerberos.principal","hbase.master.kerberos.principal"); - hbaseConfigMap.put("hbase.master.keytab.file","hbase.master.keytab.file"); - hbaseConfigMap.put("hbase.regionserver.keytab.file","hbase.regionserver.keytab.file"); - hbaseConfigMap.put("hbase.regionserver.kerberos.principal","hbase.regionserver.kerberos.principal"); - hbaseConfigMap.put("java.security.krb5.conf","hbase.regionserver.kerberos.principal"); - - suppress(method(DtFileUtils.class, "checkExists", String.class)); - - HbaseConfigUtils.getHadoopConfiguration(hbaseConfigMap); - } - - @Test - public void testLoginAndReturnUGI() throws Exception { - suppress(UserGroupInformation.class.getMethod("setConfiguration", Configuration.class)); - suppress(UserGroupInformation.class.getMethod("loginUserFromKeytabAndReturnUGI", String.class, String.class)); - - File myFile = mock(File.class); - whenNew(File.class).withAnyArguments().thenReturn(myFile); - when(myFile.exists()).thenReturn(true); - - HbaseConfigUtils.loginAndReturnUGI(new Configuration(), "principal", "keytab"); - } -} diff --git a/hbase/hbase-side/hbase-side-core/src/test/java/com/dtstack/flink/sql/side/hbase/utils/HbaseUtilTest.java b/hbase/hbase-side/hbase-side-core/src/test/java/com/dtstack/flink/sql/side/hbase/utils/HbaseUtilTest.java deleted file mode 100644 index 18727c517..000000000 --- a/hbase/hbase-side/hbase-side-core/src/test/java/com/dtstack/flink/sql/side/hbase/utils/HbaseUtilTest.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.hbase.utils; - -import org.apache.flink.api.common.typeinfo.IntegerTypeInfo; -import org.apache.flink.api.java.tuple.Tuple2; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -/** - * @author: chuixue - * @create: 2020-07-07 15:44 - * @description: - **/ -public class HbaseUtilTest { - - @Test - public void testColumnTypeToTypeInformation() { - Tuple2[] types = new Tuple2[]{new Tuple2("1".getBytes(), "boolean"), new Tuple2("1111".getBytes(),"int"), new Tuple2("11111111".getBytes(),"bigint"), new Tuple2("11111111".getBytes(),"tinyint"), new Tuple2("11".getBytes(),"short"), new Tuple2("1".getBytes(),"char"), new Tuple2("1111".getBytes(),"float"), new Tuple2("11111111".getBytes(),"double"), new Tuple2("1111".getBytes(),"decimal")}; - for (Tuple2 type : types) { - HbaseUtils.convertByte(type.f0, type.f1); - - } - } -} diff --git a/hbase/hbase-sink/pom.xml b/hbase/hbase-sink/pom.xml index ee3364a3e..11ecf0a35 100644 --- a/hbase/hbase-sink/pom.xml +++ b/hbase/hbase-sink/pom.xml @@ -25,7 +25,6 @@ shade - false org.slf4j:* @@ -62,14 +61,14 @@ - + - + diff --git a/hbase/hbase-sink/src/main/java/com/dtstack/flink/sql/sink/hbase/AbstractReplaceOperator.java b/hbase/hbase-sink/src/main/java/com/dtstack/flink/sql/sink/hbase/AbstractReplaceOperator.java deleted file mode 100644 index c3e5701aa..000000000 --- a/hbase/hbase-sink/src/main/java/com/dtstack/flink/sql/sink/hbase/AbstractReplaceOperator.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.hbase; - - -import com.dtstack.flink.sql.sink.hbase.enums.EReplaceOpType; - -import java.util.Map; - -/** - * Reason: - * Date: 2018/8/23 - * Company: www.dtstack.com - * @author xuchao - */ - -public abstract class AbstractReplaceOperator { - - private EReplaceOpType opType; - - public AbstractReplaceOperator(EReplaceOpType opType){ - this.opType = opType; - } - - public String doOperator(Map refData){ - String replaceStr = replaceStr(refData); - return doFunc(replaceStr); - } - - public String replaceStr(Map refData){ - return ""; - } - - /** - * The processing function to provide custom - * @param replaceStr - * @return - */ - abstract String doFunc(String replaceStr); -} diff --git a/hbase/hbase-sink/src/main/java/com/dtstack/flink/sql/sink/hbase/HbaseConfigUtils.java b/hbase/hbase-sink/src/main/java/com/dtstack/flink/sql/sink/hbase/HbaseConfigUtils.java deleted file mode 100644 index 86bd7c1a7..000000000 --- a/hbase/hbase-sink/src/main/java/com/dtstack/flink/sql/sink/hbase/HbaseConfigUtils.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.hbase; - -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hbase.exceptions.IllegalArgumentIOException; -import org.apache.hadoop.security.UserGroupInformation; -import org.apache.hadoop.security.authentication.util.KerberosName; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import sun.security.krb5.Config; -import sun.security.krb5.KrbException; - -import java.io.File; -import java.io.IOException; - -/** - * - * The utility class of HBase connection - * - * Date: 2019/12/24 - * Company: www.dtstack.com - * @author maqi - */ -public class HbaseConfigUtils { - - private static final Logger LOG = LoggerFactory.getLogger(HbaseConfigUtils.class); - // sync side kerberos - public final static String KEY_HBASE_SECURITY_AUTHENTICATION = "hbase.security.authentication"; - public final static String KEY_HBASE_SECURITY_AUTHORIZATION = "hbase.security.authorization"; - public final static String KEY_HBASE_MASTER_KEYTAB_FILE = "hbase.master.keytab.file"; - public final static String KEY_HBASE_MASTER_KERBEROS_PRINCIPAL = "hbase.master.kerberos.principal"; - public final static String KEY_HBASE_REGIONSERVER_KEYTAB_FILE = "hbase.regionserver.keytab.file"; - public final static String KEY_HBASE_REGIONSERVER_KERBEROS_PRINCIPAL = "hbase.regionserver.kerberos.principal"; - - public final static String KEY_HBASE_ZOOKEEPER_QUORUM = "hbase.zookeeper.quorum"; - public final static String KEY_HBASE_ZOOKEEPER_ZNODE_QUORUM = "zookeeper.znode.parent"; - - public final static String KEY_HBASE_CLIENT_KEYTAB_FILE = "hbase.client.keytab.file"; - public final static String KEY_HBASE_CLIENT_KERBEROS_PRINCIPAL = "hbase.client.kerberos.principal"; - - - public static final String KEY_JAVA_SECURITY_KRB5_CONF = "java.security.krb5.conf"; - public static final String KEY_ZOOKEEPER_SASL_CLIENT = "zookeeper.sasl.client"; - - public static final String KEY_HADOOP_SECURITY_AUTHENTICATION = "hadoop.security.authentication"; - public static final String KEY_HADOOP_SECURITY_AUTH_TO_LOCAL = "hadoop.security.auth_to_local"; - public static final String KEY_HADOOP_SECURITY_AUTHORIZATION = "hadoop.security.authorization"; - - public static UserGroupInformation loginAndReturnUGI(Configuration conf, String principal, String keytab) throws IOException, KrbException { - LOG.info("loginAndReturnUGI principal {}",principal); - LOG.info("loginAndReturnUGI keytab {}",keytab); - if (conf == null) { - throw new IllegalArgumentException("kerberos conf can not be null"); - } - - if (org.apache.commons.lang.StringUtils.isEmpty(principal)) { - throw new IllegalArgumentException("principal can not be null"); - } - - if (org.apache.commons.lang.StringUtils.isEmpty(keytab)) { - throw new IllegalArgumentException("keytab can not be null"); - } - - if (!new File(keytab).exists()){ - throw new IllegalArgumentIOException("keytab ["+ keytab + "] not exist"); - } - - conf.set(KEY_HADOOP_SECURITY_AUTHENTICATION, "Kerberos"); - //conf.set("hadoop.security.auth_to_local", "DEFAULT"); - conf.set(KEY_HADOOP_SECURITY_AUTH_TO_LOCAL, "RULE:[1:$1] RULE:[2:$1]"); - conf.set(KEY_HADOOP_SECURITY_AUTHORIZATION, "true"); - - Config.refresh(); - KerberosName.resetDefaultRealm(); - UserGroupInformation.setConfiguration(conf); - - return UserGroupInformation.loginUserFromKeytabAndReturnUGI(principal, keytab); - } -} diff --git a/hbase/hbase-sink/src/main/java/com/dtstack/flink/sql/sink/hbase/HbaseOutputFormat.java b/hbase/hbase-sink/src/main/java/com/dtstack/flink/sql/sink/hbase/HbaseOutputFormat.java index 3a8785586..e88f34372 100644 --- a/hbase/hbase-sink/src/main/java/com/dtstack/flink/sql/sink/hbase/HbaseOutputFormat.java +++ b/hbase/hbase-sink/src/main/java/com/dtstack/flink/sql/sink/hbase/HbaseOutputFormat.java @@ -16,405 +16,150 @@ * limitations under the License. */ + package com.dtstack.flink.sql.sink.hbase; -import com.dtstack.flink.sql.dirtyManager.manager.DirtyDataManager; -import com.dtstack.flink.sql.exception.ExceptionTrace; -import com.dtstack.flink.sql.factory.DTThreadFactory; -import com.dtstack.flink.sql.outputformat.AbstractDtRichOutputFormat; -import com.google.common.collect.Maps; +import com.dtstack.flink.sql.sink.MetricOutputFormat; import org.apache.commons.lang3.StringUtils; import org.apache.flink.api.java.tuple.Tuple2; import org.apache.flink.configuration.Configuration; import org.apache.flink.types.Row; import org.apache.flink.util.Preconditions; -import org.apache.hadoop.hbase.AuthUtil; -import org.apache.hadoop.hbase.ChoreService; import org.apache.hadoop.hbase.HBaseConfiguration; -import org.apache.hadoop.hbase.ScheduledChore; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.client.Connection; import org.apache.hadoop.hbase.client.ConnectionFactory; import org.apache.hadoop.hbase.client.Put; import org.apache.hadoop.hbase.client.Table; -import org.apache.hadoop.security.UserGroupInformation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - -import java.io.File; import java.io.IOException; -import java.security.PrivilegedAction; +import java.text.SimpleDateFormat; import java.util.ArrayList; -import java.util.LinkedList; import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.TimeUnit; /** - * @author: jingzhen@dtstack.com + * author: jingzhen@dtstack.com * date: 2017-6-29 */ -public class HbaseOutputFormat extends AbstractDtRichOutputFormat> { +public class HbaseOutputFormat extends MetricOutputFormat { private static final Logger LOG = LoggerFactory.getLogger(HbaseOutputFormat.class); + private String host; private String zkParent; - private String rowkey; + private String[] rowkey; private String tableName; private String[] columnNames; - private Map columnNameFamily; - private boolean kerberosAuthEnable; - private String regionserverKeytabFile; - private String regionserverPrincipal; - private String securityKrb5Conf; - private String zookeeperSaslClient; - private String clientPrincipal; - private String clientKeytabFile; + private String[] columnTypes; + private String[] families; private String[] qualifiers; + private transient org.apache.hadoop.conf.Configuration conf; private transient Connection conn; private transient Table table; - private transient ChoreService choreService; - private transient List records; - private transient volatile boolean closed = false; - /** - * 批量写入的参数 - */ - private Integer batchSize; - private Long batchWaitInterval; - /** - * 定时任务 - */ - private transient ScheduledExecutorService scheduler; - private transient ScheduledFuture scheduledFuture; - - /** - * 脏数据管理 - */ - private DirtyDataManager dirtyDataManager; - - private HbaseOutputFormat() { - } - public static HbaseOutputFormatBuilder buildHbaseOutputFormat() { - return new HbaseOutputFormatBuilder(); - } + public final SimpleDateFormat ROWKEY_DATE_FORMAT = new SimpleDateFormat("yyyyMMddHHmmss"); + public final SimpleDateFormat FIELD_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + + private static int rowLenth = 1000; @Override public void configure(Configuration parameters) { - // 这里不要做耗时较长的操作,否则会导致AKKA通信超时 - // DO NOTHING + LOG.warn("---configure---"); + conf = HBaseConfiguration.create(); + conf.set("hbase.zookeeper.quorum", host); + if(zkParent != null && !"".equals(zkParent)){ + conf.set("zookeeper.znode.parent", zkParent); + } + LOG.warn("---configure end ---"); } @Override public void open(int taskNumber, int numTasks) throws IOException { LOG.warn("---open---"); - records = new ArrayList<>(); - conf = HBaseConfiguration.create(); - openConn(); + conn = ConnectionFactory.createConnection(conf); table = conn.getTable(TableName.valueOf(tableName)); LOG.warn("---open end(get table from hbase) ---"); initMetric(); } - private void openConn() { - try { - if (kerberosAuthEnable) { - LOG.info("open kerberos conn"); - openKerberosConn(); - } else { - LOG.info("open conn"); - conf.set(HbaseConfigUtils.KEY_HBASE_ZOOKEEPER_QUORUM, host); - conf.set(HbaseConfigUtils.KEY_HBASE_ZOOKEEPER_ZNODE_QUORUM, zkParent); - conn = ConnectionFactory.createConnection(conf); - } - } catch (Exception e) { - throw new RuntimeException(e); - } - initScheduledTask(batchWaitInterval); - } - - /** - * 初始化定时写入任务 - * - * @param batchWaitInterval 定时任务时间 - */ - private void initScheduledTask(Long batchWaitInterval) { - try { - if (batchWaitInterval > 0) { - this.scheduler = new ScheduledThreadPoolExecutor( - 1, - new DTThreadFactory("hbase-batch-flusher") - ); - - this.scheduledFuture = this.scheduler.scheduleWithFixedDelay( - () -> { - synchronized (HbaseOutputFormat.this) { - if (!records.isEmpty()) { - dealBatchOperation(records); - } - } - }, batchWaitInterval, batchWaitInterval, TimeUnit.MILLISECONDS - ); - } - } catch (Exception e) { - LOG.error("init schedule task failed !"); - throw new RuntimeException(e); - } - } - - private void openKerberosConn() throws Exception { - conf.set(HbaseConfigUtils.KEY_HBASE_ZOOKEEPER_QUORUM, host); - conf.set(HbaseConfigUtils.KEY_HBASE_ZOOKEEPER_ZNODE_QUORUM, zkParent); - - LOG.info("kerberos config:{}", this.conf.toString()); - Preconditions.checkArgument(!StringUtils.isEmpty(clientPrincipal), " clientPrincipal not null!"); - Preconditions.checkArgument(!StringUtils.isEmpty(clientKeytabFile), " clientKeytabFile not null!"); - - fillSyncKerberosConfig(conf, regionserverPrincipal, zookeeperSaslClient, securityKrb5Conf); - - clientKeytabFile = System.getProperty("user.dir") + File.separator + clientKeytabFile; - clientPrincipal = !StringUtils.isEmpty(clientPrincipal) ? clientPrincipal : regionserverPrincipal; - - conf.set(HbaseConfigUtils.KEY_HBASE_CLIENT_KEYTAB_FILE, clientKeytabFile); - conf.set(HbaseConfigUtils.KEY_HBASE_CLIENT_KERBEROS_PRINCIPAL, clientPrincipal); - - UserGroupInformation userGroupInformation = HbaseConfigUtils.loginAndReturnUGI(conf, clientPrincipal, clientKeytabFile); - org.apache.hadoop.conf.Configuration finalConf = conf; - conn = userGroupInformation.doAs((PrivilegedAction) () -> { - try { - ScheduledChore authChore = AuthUtil.getAuthChore(finalConf); - if (authChore != null) { - choreService = new ChoreService("hbaseKerberosSink"); - choreService.scheduleChore(authChore); - } - - return ConnectionFactory.createConnection(finalConf); - } catch (IOException e) { - LOG.error("Get connection fail with config:{}", finalConf); - throw new RuntimeException(e); - } - }); - } - @Override - public void writeRecord(Tuple2 record) { - if (record.f0) { - if (this.batchSize > 1) { - writeBatchRecord(record.f1); - } else { - dealInsert(record.f1); - } - } - } + public void writeRecord(Tuple2 tuple2) throws IOException { - public void writeBatchRecord(Row row) { - records.add(row); - // 数据累计到batchSize之后开始处理 - if (records.size() == this.batchSize) { - dealBatchOperation(records); + Tuple2 tupleTrans = tuple2; + Boolean retract = tupleTrans.getField(0); + if(!retract){ + //FIXME 暂时不处理hbase删除操作--->hbase要求有key,所有认为都是可以执行update查找 + return; } - } - protected synchronized void dealBatchOperation(List records) { - // A null in the result array means that the call for that action failed, even after retries. - Object[] results = null; - try { - List puts = new ArrayList<>(); - for (Row record : records) { - addPut(puts, record); - } - results = new Object[puts.size()]; - table.batch(puts, results); + Row record = tupleTrans.getField(1); - // 打印结果 - if (outRecords.getCount() % ROW_PRINT_FREQUENCY == 0) { - // 只打印最后一条数据 - LOG.info(records.get(records.size() - 1).toString()); + List list = new ArrayList<>(); + for(int i = 0; i < rowkey.length; ++i) { + String colName = rowkey[i]; + int j = 0; + for(; j < columnNames.length; ++j) { + if(columnNames[j].equals(colName)) { + break; + } } - } catch (IOException | InterruptedException e) { - // ignore exception - } finally { - // 判断数据是否插入成功 - for (int i = 0; i < Objects.requireNonNull(results).length; i++) { - if (results[i] instanceof Exception) { - dirtyDataManager.execute(); - // 脏数据记录 - dirtyDataManager.collectDirtyData( - records.get(i).toString(), - ExceptionTrace.traceOriginalCause((Exception) results[i]) - ); - outDirtyRecords.inc(); + if(j != columnNames.length && record.getField(i) != null) { + Object field = record.getField(j); + if(field == null ) { + list.add("null"); + } else if (field instanceof java.util.Date){ + java.util.Date d = (java.util.Date)field; + list.add(ROWKEY_DATE_FORMAT.format(d)); } else { - // 输出结果条数记录 - outRecords.inc(); + list.add(field.toString()); } } - // 添加完数据之后数据清空records - records.clear(); } - } - private void addPut(List puts, Row record) { - try { - Put put = getPutByRow(record); - if (put == null || put.isEmpty()) { - throw new RuntimeException("HBase put is empty, check record please!"); - } else { - puts.add(put); + String key = StringUtils.join(list, "-"); + Put put = new Put(key.getBytes()); + for(int i = 0; i < record.getArity(); ++i) { + Object field = record.getField(i); + byte[] val = null; + if (field != null) { + val = field.toString().getBytes(); } - } catch (Exception e) { - dirtyDataManager.execute(); - dirtyDataManager.collectDirtyData( - record.toString(), ExceptionTrace.traceOriginalCause(e)); - outDirtyRecords.inc(); - } - } - - protected void dealInsert(Row record) { - Put put = getPutByRow(record); - if (put == null || put.isEmpty()) { - // 记录脏数据 - outDirtyRecords.inc(); - return; - } + byte[] cf = families[i].getBytes(); + byte[] qualifier = qualifiers[i].getBytes(); + put.addColumn(cf, qualifier, val); - try { - table.put(put); - if (outRecords.getCount() % ROW_PRINT_FREQUENCY == 0) { - LOG.info(record.toString()); - } - } catch (Exception e) { - dirtyDataManager.collectDirtyData( - record.toString(), - ExceptionTrace.traceOriginalCause(e)); - outDirtyRecords.inc(); } - outRecords.inc(); - } - - private Put getPutByRow(Row record) { - String rowKey = buildRowKey(record); - if (StringUtils.isEmpty(rowKey)) { - return null; - } - Put put = new Put(rowKey.getBytes()); - for (int i = 0; i < record.getArity(); ++i) { - Object fieldVal = record.getField(i); - if (fieldVal != null) { - byte[] val = fieldVal.toString().getBytes(); - byte[] cf = families[i].getBytes(); - byte[] qualifier = qualifiers[i].getBytes(); - - put.addColumn(cf, qualifier, val); - } - } - return put; - } + table.put(put); - private String buildRowKey(Row record) { - String rowKeyValues = getRowKeyValues(record); - // all rowkey not null - if (StringUtils.isBlank(rowKeyValues)) { - LOG.error("row key value must not null,record is ..{}", record); - outDirtyRecords.inc(); - return ""; + if (outRecords.getCount()%rowLenth == 0){ + LOG.info(record.toString()); } - return rowKeyValues; - } - - private String getRowKeyValues(Row record) { - Map row = rowConvertMap(record); - RowKeyBuilder rowKeyBuilder = new RowKeyBuilder(); - rowKeyBuilder.init(rowkey); - return rowKeyBuilder.getRowKey(row); - } + outRecords.inc(); - private Map rowConvertMap(Row record) { - Map rowValue = Maps.newHashMap(); - for (int i = 0; i < columnNames.length; i++) { - rowValue.put(columnNames[i], record.getField(i)); - } - return rowValue; } @Override - public synchronized void close() throws IOException { - if (closed) { - return; - } - - closed = true; - if (!records.isEmpty()) { - dealBatchOperation(records); - } - - if (scheduledFuture != null) { - scheduledFuture.cancel(false); - if (scheduler != null) { - scheduler.shutdownNow(); - } - } - - if (conn != null) { + public void close() throws IOException { + if(conn != null) { conn.close(); conn = null; } - - if (dirtyDataManager != null) { - dirtyDataManager.close(); - } } - private void fillSyncKerberosConfig(org.apache.hadoop.conf.Configuration config, - String regionserverPrincipal, - String zookeeperSaslClient, - String securityKrb5Conf) { - if (StringUtils.isEmpty(regionserverPrincipal)) { - throw new IllegalArgumentException("Must provide regionserverPrincipal when authentication is Kerberos"); - } - config.set(HbaseConfigUtils.KEY_HBASE_MASTER_KERBEROS_PRINCIPAL, regionserverPrincipal); - config.set(HbaseConfigUtils.KEY_HBASE_REGIONSERVER_KERBEROS_PRINCIPAL, regionserverPrincipal); - config.set(HbaseConfigUtils.KEY_HBASE_SECURITY_AUTHORIZATION, "true"); - config.set(HbaseConfigUtils.KEY_HBASE_SECURITY_AUTHENTICATION, "kerberos"); - - - if (!StringUtils.isEmpty(zookeeperSaslClient)) { - System.setProperty(HbaseConfigUtils.KEY_ZOOKEEPER_SASL_CLIENT, zookeeperSaslClient); - } - - if (!StringUtils.isEmpty(securityKrb5Conf)) { - String krb5ConfPath = System.getProperty("user.dir") + File.separator + securityKrb5Conf; - LOG.info("krb5ConfPath:{}", krb5ConfPath); - System.setProperty(HbaseConfigUtils.KEY_JAVA_SECURITY_KRB5_CONF, krb5ConfPath); - } - } + private HbaseOutputFormat() {} - @Override - public String toString() { - return "HbaseOutputFormat kerberos{" + - "kerberosAuthEnable=" + kerberosAuthEnable + - ", regionserverKeytabFile='" + regionserverKeytabFile + '\'' + - ", regionserverPrincipal='" + regionserverPrincipal + '\'' + - ", securityKrb5Conf='" + securityKrb5Conf + '\'' + - ", zookeeperSaslClient='" + zookeeperSaslClient + '\'' + - ", clientPrincipal='" + clientPrincipal + '\'' + - ", clientKeytabFile='" + clientKeytabFile + '\'' + - ", batchSize='" + batchSize + '\'' + - ", batchWaitInterval='" + batchWaitInterval + '\'' + - '}'; + public static HbaseOutputFormatBuilder buildHbaseOutputFormat() { + return new HbaseOutputFormatBuilder(); } public static class HbaseOutputFormatBuilder { - private final HbaseOutputFormat format; + private HbaseOutputFormat format; private HbaseOutputFormatBuilder() { format = new HbaseOutputFormat(); @@ -425,7 +170,7 @@ public HbaseOutputFormatBuilder setHost(String host) { return this; } - public HbaseOutputFormatBuilder setZkParent(String parent) { + public HbaseOutputFormatBuilder setZkParent(String parent){ format.zkParent = parent; return this; } @@ -436,7 +181,7 @@ public HbaseOutputFormatBuilder setTable(String tableName) { return this; } - public HbaseOutputFormatBuilder setRowkey(String rowkey) { + public HbaseOutputFormatBuilder setRowkey(String[] rowkey) { format.rowkey = rowkey; return this; } @@ -446,58 +191,8 @@ public HbaseOutputFormatBuilder setColumnNames(String[] columnNames) { return this; } - public HbaseOutputFormatBuilder setColumnNameFamily(Map columnNameFamily) { - format.columnNameFamily = columnNameFamily; - return this; - } - - public HbaseOutputFormatBuilder setKerberosAuthEnable(boolean kerberosAuthEnable) { - format.kerberosAuthEnable = kerberosAuthEnable; - return this; - } - - public HbaseOutputFormatBuilder setRegionserverKeytabFile(String regionserverKeytabFile) { - format.regionserverKeytabFile = regionserverKeytabFile; - return this; - } - - public HbaseOutputFormatBuilder setRegionserverPrincipal(String regionserverPrincipal) { - format.regionserverPrincipal = regionserverPrincipal; - return this; - } - - public HbaseOutputFormatBuilder setSecurityKrb5Conf(String securityKrb5Conf) { - format.securityKrb5Conf = securityKrb5Conf; - return this; - } - - public HbaseOutputFormatBuilder setZookeeperSaslClient(String zookeeperSaslClient) { - format.zookeeperSaslClient = zookeeperSaslClient; - return this; - } - - public HbaseOutputFormatBuilder setClientPrincipal(String clientPrincipal) { - format.clientPrincipal = clientPrincipal; - return this; - } - - public HbaseOutputFormatBuilder setClientKeytabFile(String clientKeytabFile) { - format.clientKeytabFile = clientKeytabFile; - return this; - } - - public HbaseOutputFormatBuilder setDirtyManager(DirtyDataManager dirtyDataManager) { - format.dirtyDataManager = dirtyDataManager; - return this; - } - - public HbaseOutputFormatBuilder setBatchSize(Integer batchSize) { - format.batchSize = batchSize; - return this; - } - - public HbaseOutputFormatBuilder setBatchWaitInterval(Long batchWaitInterval) { - format.batchWaitInterval = batchWaitInterval; + public HbaseOutputFormatBuilder setColumnTypes(String[] columnTypes) { + format.columnTypes = columnTypes; return this; } @@ -510,20 +205,20 @@ public HbaseOutputFormat finish() { String[] families = new String[format.columnNames.length]; String[] qualifiers = new String[format.columnNames.length]; - if (format.columnNameFamily != null) { - List keyList = new LinkedList<>(format.columnNameFamily.keySet()); - String[] columns = keyList.toArray(new String[0]); - for (int i = 0; i < columns.length; ++i) { - String col = columns[i]; - String[] part = col.split(":"); - families[i] = part[0]; - qualifiers[i] = part[1]; - } + for(int i = 0; i < format.columnNames.length; ++i) { + String col = format.columnNames[i]; + String[] part = col.split(":"); + families[i] = part[0]; + qualifiers[i] = part[1]; } + format.families = families; format.qualifiers = qualifiers; return format; } + } + + } diff --git a/hbase/hbase-sink/src/main/java/com/dtstack/flink/sql/sink/hbase/HbaseSink.java b/hbase/hbase-sink/src/main/java/com/dtstack/flink/sql/sink/hbase/HbaseSink.java index db390125a..03d460066 100644 --- a/hbase/hbase-sink/src/main/java/com/dtstack/flink/sql/sink/hbase/HbaseSink.java +++ b/hbase/hbase-sink/src/main/java/com/dtstack/flink/sql/sink/hbase/HbaseSink.java @@ -16,131 +16,66 @@ * limitations under the License. */ + package com.dtstack.flink.sql.sink.hbase; -import com.dtstack.flink.sql.dirtyManager.manager.DirtyDataManager; import com.dtstack.flink.sql.sink.IStreamSinkGener; import com.dtstack.flink.sql.sink.hbase.table.HbaseTableInfo; -import com.dtstack.flink.sql.table.AbstractTargetTableInfo; +import com.dtstack.flink.sql.table.TargetTableInfo; import org.apache.flink.api.common.typeinfo.TypeInformation; import org.apache.flink.api.java.tuple.Tuple2; import org.apache.flink.api.java.typeutils.RowTypeInfo; import org.apache.flink.api.java.typeutils.TupleTypeInfo; import org.apache.flink.streaming.api.datastream.DataStream; -import org.apache.flink.streaming.api.datastream.DataStreamSink; import org.apache.flink.streaming.api.functions.sink.OutputFormatSinkFunction; import org.apache.flink.streaming.api.functions.sink.RichSinkFunction; +import org.apache.flink.table.sinks.AppendStreamTableSink; import org.apache.flink.table.sinks.RetractStreamTableSink; import org.apache.flink.table.sinks.TableSink; import org.apache.flink.types.Row; -import java.util.Map; -import java.util.Properties; - /** * Date: 2018/09/14 * Company: www.dtstack.com - * * @author sishu.yss */ public class HbaseSink implements RetractStreamTableSink, IStreamSinkGener { protected String[] fieldNames; - protected Map columnNameFamily; + TypeInformation[] fieldTypes; protected String zookeeperQuorum; protected String port; protected String parent; protected String tableName; - protected String updateMode; - protected String rowkey; - protected String registerTabName; - protected boolean kerberosAuthEnable; - protected String regionserverKeytabFile; - protected String regionserverPrincipal; - protected String securityKrb5Conf; - protected String zookeeperSaslClient; - protected String batchSize; - protected String batchWaitInterval; - TypeInformation[] fieldTypes; - private String clientPrincipal; - private String clientKeytabFile; - private int parallelism = 1; - - private Map dirtyProperties; + protected String[] rowkey; public HbaseSink() { // TO DO NOTHING } @Override - public HbaseSink genStreamSink(AbstractTargetTableInfo targetTableInfo) { + public HbaseSink genStreamSink(TargetTableInfo targetTableInfo) { HbaseTableInfo hbaseTableInfo = (HbaseTableInfo) targetTableInfo; this.zookeeperQuorum = hbaseTableInfo.getHost(); this.port = hbaseTableInfo.getPort(); this.parent = hbaseTableInfo.getParent(); this.tableName = hbaseTableInfo.getTableName(); this.rowkey = hbaseTableInfo.getRowkey(); - this.columnNameFamily = hbaseTableInfo.getColumnNameFamily(); - this.registerTabName = hbaseTableInfo.getName(); - - this.kerberosAuthEnable = hbaseTableInfo.isKerberosAuthEnable(); - this.regionserverKeytabFile = hbaseTableInfo.getRegionserverKeytabFile(); - this.regionserverPrincipal = hbaseTableInfo.getRegionserverPrincipal(); - this.securityKrb5Conf = hbaseTableInfo.getSecurityKrb5Conf(); - this.zookeeperSaslClient = hbaseTableInfo.getZookeeperSaslClient(); - - this.clientKeytabFile = hbaseTableInfo.getClientKeytabFile(); - this.clientPrincipal = hbaseTableInfo.getClientPrincipal(); - - this.dirtyProperties = hbaseTableInfo.getDirtyProperties(); - - Integer tmpSinkParallelism = hbaseTableInfo.getParallelism(); - if (tmpSinkParallelism != null) { - this.parallelism = tmpSinkParallelism; - } - - this.batchSize = hbaseTableInfo.getBatchSize(); - this.batchWaitInterval = hbaseTableInfo.getBatchWaitInterval(); return this; } @Override public void emitDataStream(DataStream> dataStream) { - consumeDataStream(dataStream); - } - - @Override - public DataStreamSink> consumeDataStream(DataStream> dataStream) { HbaseOutputFormat.HbaseOutputFormatBuilder builder = HbaseOutputFormat.buildHbaseOutputFormat(); + builder.setHost(this.zookeeperQuorum).setZkParent(this.parent).setTable(this.tableName); + + builder.setRowkey(rowkey); + builder.setColumnNames(fieldNames); - HbaseOutputFormat outputFormat = builder - .setHost(this.zookeeperQuorum) - .setZkParent(this.parent) - .setTable(this.tableName) - .setRowkey(rowkey) - .setColumnNames(fieldNames) - .setColumnNameFamily(columnNameFamily) - .setKerberosAuthEnable(kerberosAuthEnable) - .setRegionserverKeytabFile(regionserverKeytabFile) - .setRegionserverPrincipal(regionserverPrincipal) - .setSecurityKrb5Conf(securityKrb5Conf) - .setZookeeperSaslClient(zookeeperSaslClient) - .setClientPrincipal(clientPrincipal) - .setClientKeytabFile(clientKeytabFile) - .setBatchSize(Integer.parseInt(batchSize)) - .setBatchWaitInterval(Long.parseLong(batchWaitInterval)) - .setDirtyManager(DirtyDataManager.newInstance(dirtyProperties)) - .finish(); - + HbaseOutputFormat outputFormat = builder.finish(); RichSinkFunction richSinkFunction = new OutputFormatSinkFunction(outputFormat); - DataStreamSink dataStreamSink = dataStream.addSink(richSinkFunction).name(registerTabName); - - if (parallelism > 0) { - dataStreamSink.setParallelism(parallelism); - } - - return dataStreamSink; + dataStream.addSink(richSinkFunction); } @Override diff --git a/hbase/hbase-sink/src/main/java/com/dtstack/flink/sql/sink/hbase/HbaseUtil.java b/hbase/hbase-sink/src/main/java/com/dtstack/flink/sql/sink/hbase/HbaseUtil.java index b5a39aeff..8f1166574 100644 --- a/hbase/hbase-sink/src/main/java/com/dtstack/flink/sql/sink/hbase/HbaseUtil.java +++ b/hbase/hbase-sink/src/main/java/com/dtstack/flink/sql/sink/hbase/HbaseUtil.java @@ -22,15 +22,9 @@ import org.apache.flink.api.common.typeinfo.BasicTypeInfo; import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.io.ByteWritable; import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io.Text; -import scala.tools.nsc.Global; - -import java.math.BigDecimal; -import java.nio.ByteBuffer; -import java.util.Objects; /** * Created by softfly on 17/6/30. @@ -70,30 +64,4 @@ public static TypeInformation columnTypeToTypeInformation(String type) { } - public static byte[] toByte(Object value) { - if (Objects.isNull(value)) { - return new byte[]{}; - } - if (value instanceof Integer) { - return Bytes.toBytes((Integer) value); - } else if (value instanceof Boolean) { - return Bytes.toBytes((Boolean) value); - } else if (value instanceof ByteBuffer) { - return Bytes.toBytes((ByteBuffer) value); - } else if (value instanceof Double) { - return Bytes.toBytes((Double) value); - } else if (value instanceof Float) { - return Bytes.toBytes((Float) value); - } else if (value instanceof Long) { - return Bytes.toBytes((Long) value); - } else if (value instanceof Short) { - return Bytes.toBytes((Short) value); - } else if (value instanceof String) { - return Bytes.toBytes(String.valueOf(value)); - } else if (value instanceof BigDecimal) { - return Bytes.toBytes((BigDecimal) value); - } - throw new RuntimeException("unkown dateType[" + value.toString() + "]"); - } - } diff --git a/hbase/hbase-sink/src/main/java/com/dtstack/flink/sql/sink/hbase/Md5ReplaceOperator.java b/hbase/hbase-sink/src/main/java/com/dtstack/flink/sql/sink/hbase/Md5ReplaceOperator.java deleted file mode 100644 index e9474220a..000000000 --- a/hbase/hbase-sink/src/main/java/com/dtstack/flink/sql/sink/hbase/Md5ReplaceOperator.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.hbase; - -import com.dtstack.flink.sql.sink.hbase.enums.EReplaceOpType; -import com.dtstack.flink.sql.util.MD5Utils; - -/** - * Reason: - * Date: 2018/8/23 - * Company: www.dtstack.com - * @author xuchao - */ - -public class Md5ReplaceOperator extends AbstractReplaceOperator { - - public Md5ReplaceOperator(EReplaceOpType opType) { - super(opType); - } - - @Override - String doFunc(String replaceStr) { - return MD5Utils.getMD5String(replaceStr); - } -} diff --git a/hbase/hbase-sink/src/main/java/com/dtstack/flink/sql/sink/hbase/ReplaceInfo.java b/hbase/hbase-sink/src/main/java/com/dtstack/flink/sql/sink/hbase/ReplaceInfo.java deleted file mode 100644 index c233bfe6b..000000000 --- a/hbase/hbase-sink/src/main/java/com/dtstack/flink/sql/sink/hbase/ReplaceInfo.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.hbase; - - -import com.dtstack.flink.sql.sink.hbase.enums.EReplaceType; - -import java.io.Serializable; -import java.util.List; - -/** - * Reason: - * Date: 2018/8/23 - * Company: www.dtstack.com - * - * @author xuchao - */ - -public class ReplaceInfo implements Serializable { - - private static final long serialVersionUID = 2058635242957737717L; - - private EReplaceType type; - - private String param; - - private List subReplaceInfos; - - public ReplaceInfo(EReplaceType type){ - this.type = type; - } - - public EReplaceType getType() { - return type; - } - - public void setType(EReplaceType type) { - this.type = type; - } - - public String getParam() { - return param; - } - - public void setParam(String param) { - this.param = param; - } - - public List getSubReplaceInfos() { - return subReplaceInfos; - } - - public void setSubReplaceInfos(List subReplaceInfos) { - this.subReplaceInfos = subReplaceInfos; - } -} diff --git a/hbase/hbase-sink/src/main/java/com/dtstack/flink/sql/sink/hbase/RowKeyBuilder.java b/hbase/hbase-sink/src/main/java/com/dtstack/flink/sql/sink/hbase/RowKeyBuilder.java deleted file mode 100644 index 13329faed..000000000 --- a/hbase/hbase-sink/src/main/java/com/dtstack/flink/sql/sink/hbase/RowKeyBuilder.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.hbase; - -import com.dtstack.flink.sql.sink.hbase.enums.EReplaceType; -import com.dtstack.flink.sql.util.MD5Utils; -import com.google.common.collect.Lists; -import org.apache.commons.collections.CollectionUtils; - -import javax.xml.crypto.Data; -import java.io.Serializable; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * rowkey rule - * Date: 2018/8/23 - * Company: www.dtstack.com - * @author xuchao - */ - -public class RowKeyBuilder implements Serializable{ - - private static final long serialVersionUID = 2058635242857937717L; - - private static Pattern Md5Operator = Pattern.compile("(?i)^md5\\(\\s*(.*)\\s*\\)$"); - - private List operatorChain = Lists.newArrayList(); - - public void init(String rowKeyTempl){ - operatorChain.addAll(makeFormula(rowKeyTempl)); - } - - /** - * - * @param refData - * @return - */ - public String getRowKey(Map refData){ - return buildStr(operatorChain, refData); - } - - - - private String buildStr(List fieldList, Map refData){ - if(CollectionUtils.isEmpty(fieldList)){ - return ""; - } - StringBuffer sb = new StringBuffer(""); - for(ReplaceInfo replaceInfo : fieldList){ - - if(replaceInfo.getType() == EReplaceType.CONSTANT){ - sb.append(replaceInfo.getParam()); - continue; - } - - if(replaceInfo.getType() == EReplaceType.FUNC){ - sb.append(MD5Utils.getMD5String(buildStr(replaceInfo.getSubReplaceInfos(), refData))); - continue; - } - String replaceName = replaceInfo.getParam(); - if(!refData.containsKey(replaceName)){ - throw new RuntimeException(String.format("build rowKey with field %s which value not found.", replaceName)); - } - Object value = refData.get(replaceName); - if(value instanceof Date){ - SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); - java.util.Date d = (java.util.Date) value; - sb.append(sdf.format(d)); - } else { - sb.append(value); - } - } - - return sb.toString(); - } - - public static String[] splitIgnoreQuotaBrackets(String str, String delimiter){ - String splitPatternStr = delimiter + "(?![^()]*+\\))(?![^{}]*+})(?![^\\[\\]]*+\\])"; - return str.split(splitPatternStr); - } - - /** - * - * @param field - * @return - */ - public ReplaceInfo getReplaceInfo(String field){ - - field = field.trim(); - - //判断是不是常量==>''包裹的标识 - if(field.startsWith("'") && field.endsWith("'")){ - ReplaceInfo replaceInfo = new ReplaceInfo(EReplaceType.CONSTANT); - field = field.substring(1, field.length() - 1); - replaceInfo.setParam(field); - return replaceInfo; - } - - ReplaceInfo replaceInfo = new ReplaceInfo(EReplaceType.PARAM); - replaceInfo.setParam(field); - return replaceInfo; - } - - private List makeFormula(String formula){ - if(formula == null || formula.length() <= 0){ - return Lists.newArrayList(); - } - List result = Lists.newArrayList(); - for(String meta: splitIgnoreQuotaBrackets(formula, "\\+")){ - Matcher matcher = Md5Operator.matcher(meta.trim()); - if(matcher.find()){ - ReplaceInfo replaceInfo = new ReplaceInfo(EReplaceType.FUNC); - replaceInfo.setSubReplaceInfos(makeFormula(matcher.group(1))); - result.add(replaceInfo); - } else { - result.add(getReplaceInfo(meta)); - } - } - return result; - } -} diff --git a/hbase/hbase-sink/src/main/java/com/dtstack/flink/sql/sink/hbase/table/HbaseSinkParser.java b/hbase/hbase-sink/src/main/java/com/dtstack/flink/sql/sink/hbase/table/HbaseSinkParser.java index 6dc85efbb..d5a3fd4b7 100644 --- a/hbase/hbase-sink/src/main/java/com/dtstack/flink/sql/sink/hbase/table/HbaseSinkParser.java +++ b/hbase/hbase-sink/src/main/java/com/dtstack/flink/sql/sink/hbase/table/HbaseSinkParser.java @@ -21,26 +21,20 @@ package com.dtstack.flink.sql.sink.hbase.table; -import com.dtstack.flink.sql.enums.EUpdateMode; -import com.dtstack.flink.sql.table.AbstractTableParser; -import com.dtstack.flink.sql.table.AbstractTableInfo; -import com.dtstack.flink.sql.util.DtStringUtil; +import com.dtstack.flink.sql.table.AbsTableParser; +import com.dtstack.flink.sql.table.TableInfo; import com.dtstack.flink.sql.util.MathUtil; -import com.google.common.collect.Maps; -import org.apache.commons.lang3.StringUtils; -import java.util.LinkedHashMap; -import java.util.List; import java.util.Map; -import static com.dtstack.flink.sql.table.AbstractTableInfo.PARALLELISM_KEY; +import static com.dtstack.flink.sql.table.TableInfo.PARALLELISM_KEY; /** * Date: 2018/09/14 * Company: www.dtstack.com * @author sishu.yss */ -public class HbaseSinkParser extends AbstractTableParser { +public class HbaseSinkParser extends AbsTableParser { public static final String HBASE_ZOOKEEPER_QUORUM = "zookeeperQuorum"; @@ -53,93 +47,22 @@ public class HbaseSinkParser extends AbstractTableParser { public static final String TABLE_NAME_KEY = "tableName"; - public static final String UPDATE_KEY = "updateMode"; - - public static final String KERBEROS_AUTH_ENABLE_KEY = "kerberosAuthEnable"; - public static final String REGIONSERVER_KEYTAB_FILE_KEY = "regionserverKeytabFile"; - public static final String REGIONSERVER_PRINCIPAL_KEY = "regionserverPrincipal"; - public static final String SECURITY_KRB5_CONF_KEY = "securityKrb5Conf"; - public static final String ZOOKEEPER_SASL_CLINT_KEY = "zookeeperSaslClient"; - - public static final String CLIENT_PRINCIPAL_KEY = "clientPrincipal"; - public static final String CLIENT_KEYTABFILE_KEY = "clientKeytabFile"; - - public static final String BATCH_SIZE = "batchSize"; - public static final String BATCH_WAIT_INTERVAL = "batchWaitInterval"; - - @Override protected boolean fieldNameNeedsUpperCase() { return false; } @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { + public TableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { HbaseTableInfo hbaseTableInfo = new HbaseTableInfo(); hbaseTableInfo.setName(tableName); parseFieldsInfo(fieldsInfo, hbaseTableInfo); - hbaseTableInfo.setTableName(MathUtil.getString(props.get(TABLE_NAME_KEY.toLowerCase()))); + hbaseTableInfo.setTableName((String) props.get(TABLE_NAME_KEY.toLowerCase())); hbaseTableInfo.setParallelism(MathUtil.getIntegerVal(props.get(PARALLELISM_KEY.toLowerCase()))); - hbaseTableInfo.setHost(MathUtil.getString(props.get(HBASE_ZOOKEEPER_QUORUM.toLowerCase()))); - hbaseTableInfo.setParent(MathUtil.getString(props.get(ZOOKEEPER_PARENT.toLowerCase()))); - String rk = MathUtil.getString(props.get(HBASE_ROWKEY.toLowerCase())); - hbaseTableInfo.setRowkey(rk); - String updateMode = MathUtil.getString(props.getOrDefault(UPDATE_KEY, EUpdateMode.APPEND.name())); - hbaseTableInfo.setUpdateMode(updateMode); - - hbaseTableInfo.setKerberosAuthEnable(MathUtil.getBoolean(props.get(KERBEROS_AUTH_ENABLE_KEY.toLowerCase()), false)); - hbaseTableInfo.setRegionserverKeytabFile(MathUtil.getString(props.get(REGIONSERVER_KEYTAB_FILE_KEY.toLowerCase()))); - hbaseTableInfo.setRegionserverPrincipal((MathUtil.getString(props.get(REGIONSERVER_PRINCIPAL_KEY.toLowerCase())))); - hbaseTableInfo.setSecurityKrb5Conf(MathUtil.getString(props.get(SECURITY_KRB5_CONF_KEY.toLowerCase()))); - hbaseTableInfo.setZookeeperSaslClient(MathUtil.getString(props.get(ZOOKEEPER_SASL_CLINT_KEY.toLowerCase()))); - - hbaseTableInfo.setClientPrincipal(MathUtil.getString(props.get(CLIENT_PRINCIPAL_KEY.toLowerCase()))); - hbaseTableInfo.setClientKeytabFile(MathUtil.getString(props.get(CLIENT_KEYTABFILE_KEY.toLowerCase()))); - - hbaseTableInfo.setBatchSize(MathUtil.getString(props.getOrDefault(BATCH_SIZE.toLowerCase(), "100"))); - hbaseTableInfo.setBatchWaitInterval(MathUtil.getString(props.getOrDefault(BATCH_WAIT_INTERVAL.toLowerCase(), "1000"))); + hbaseTableInfo.setHost((String) props.get(HBASE_ZOOKEEPER_QUORUM.toLowerCase())); + hbaseTableInfo.setParent((String)props.get(ZOOKEEPER_PARENT.toLowerCase())); + String rk = (String) props.get(HBASE_ROWKEY.toLowerCase()); + hbaseTableInfo.setRowkey(rk.split(",")); return hbaseTableInfo; } - - public void parseFieldsInfo(String fieldsInfo, HbaseTableInfo tableInfo){ - List fieldRows = DtStringUtil.splitIgnoreQuota(fieldsInfo, ','); - for(String fieldRow : fieldRows){ - fieldRow = fieldRow.trim(); - - String[] filedInfoArr = fieldRow.split("\\s+"); - if(filedInfoArr.length < 2 ){ - throw new RuntimeException(String.format("table [%s] field [%s] format error.", tableInfo.getName(), fieldRow)); - } - - boolean isMatcherKey = dealKeyPattern(fieldRow, tableInfo); - if(isMatcherKey){ - continue; - } - - //Compatible situation may arise in space in the fieldName - String[] filedNameArr = new String[filedInfoArr.length - 1]; - System.arraycopy(filedInfoArr, 0, filedNameArr, 0, filedInfoArr.length - 1); - String fieldName = String.join(" ", filedNameArr); - String fieldType = filedInfoArr[filedInfoArr.length - 1 ].trim(); - Class fieldClass = dbTypeConvertToJavaType(fieldType); - String[] columnFamily = StringUtils.split(fieldName.trim(), ":"); - tableInfo.addPhysicalMappings(filedInfoArr[0],filedInfoArr[0]); - tableInfo.addField(columnFamily[1]); - tableInfo.addFieldClass(fieldClass); - tableInfo.addFieldType(fieldType); - tableInfo.addFieldExtraInfo(null); - } - tableInfo.setColumnNameFamily(parseColumnFamily(tableInfo.getPhysicalFields())); - tableInfo.finish(); - } - - private Map parseColumnFamily(Map physicalFieldMap){ - Map columnFamiles = Maps.newLinkedHashMap(); - physicalFieldMap.values().forEach(x -> { - String[] columnFamily = StringUtils.split(x.trim(), ":"); - columnFamiles.put(x, columnFamily[1]); - }); - - return columnFamiles; - } } diff --git a/hbase/hbase-sink/src/main/java/com/dtstack/flink/sql/sink/hbase/table/HbaseTableInfo.java b/hbase/hbase-sink/src/main/java/com/dtstack/flink/sql/sink/hbase/table/HbaseTableInfo.java index 7761d0466..ed28f781d 100644 --- a/hbase/hbase-sink/src/main/java/com/dtstack/flink/sql/sink/hbase/table/HbaseTableInfo.java +++ b/hbase/hbase-sink/src/main/java/com/dtstack/flink/sql/sink/hbase/table/HbaseTableInfo.java @@ -21,11 +21,8 @@ package com.dtstack.flink.sql.sink.hbase.table; -import com.dtstack.flink.sql.table.AbstractTargetTableInfo; +import com.dtstack.flink.sql.table.TargetTableInfo; import com.google.common.base.Preconditions; -import com.google.common.collect.Maps; - -import java.util.LinkedHashMap; import java.util.Map; /** @@ -33,7 +30,7 @@ * Company: www.dtstack.com * @author sishu.yss */ -public class HbaseTableInfo extends AbstractTargetTableInfo { +public class HbaseTableInfo extends TargetTableInfo { private static final String CURR_TYPE = "hbase"; @@ -43,7 +40,7 @@ public class HbaseTableInfo extends AbstractTargetTableInfo { private String parent; - private String rowkey; + private String[] rowkey; private Map columnNameFamily; @@ -55,28 +52,6 @@ public class HbaseTableInfo extends AbstractTargetTableInfo { private String tableName; - private String updateMode; - - private boolean kerberosAuthEnable; - - private String regionserverKeytabFile; - - private String regionserverPrincipal; - - private String securityKrb5Conf; - - private String zookeeperSaslClient; - - private String clientPrincipal; - - private String clientKeytabFile; - - private String batchSize; - - private String batchWaitInterval; - - private Map hbaseConfig = Maps.newHashMap(); - public HbaseTableInfo(){ setType(CURR_TYPE); } @@ -113,11 +88,11 @@ public void setParent(String parent) { this.parent = parent; } - public String getRowkey() { + public String[] getRowkey() { return rowkey; } - public void setRowkey(String rowkey) { + public void setRowkey(String[] rowkey) { this.rowkey = rowkey; } @@ -153,14 +128,6 @@ public void setColumnTypes(String[] columnTypes) { this.columnTypes = columnTypes; } - public String getUpdateMode() { - return updateMode; - } - - public void setUpdateMode(String updateMode) { - this.updateMode = updateMode; - } - @Override public boolean check() { Preconditions.checkNotNull(host, "hbase field of zookeeperQuorum is required"); @@ -172,85 +139,4 @@ public String getType() { return super.getType().toLowerCase(); } - - public Map getHbaseConfig() { - return hbaseConfig; - } - - public void setHbaseConfig(Map hbaseConfig) { - this.hbaseConfig = hbaseConfig; - } - - public boolean isKerberosAuthEnable() { - return kerberosAuthEnable; - } - - public void setKerberosAuthEnable(boolean kerberosAuthEnable) { - this.kerberosAuthEnable = kerberosAuthEnable; - } - - public String getRegionserverKeytabFile() { - return regionserverKeytabFile; - } - - public void setRegionserverKeytabFile(String regionserverKeytabFile) { - this.regionserverKeytabFile = regionserverKeytabFile; - } - - public String getRegionserverPrincipal() { - return regionserverPrincipal; - } - - public void setRegionserverPrincipal(String regionserverPrincipal) { - this.regionserverPrincipal = regionserverPrincipal; - } - - public String getSecurityKrb5Conf() { - return securityKrb5Conf; - } - - public void setSecurityKrb5Conf(String securityKrb5Conf) { - this.securityKrb5Conf = securityKrb5Conf; - } - - public String getZookeeperSaslClient() { - return zookeeperSaslClient; - } - - public void setZookeeperSaslClient(String zookeeperSaslClient) { - this.zookeeperSaslClient = zookeeperSaslClient; - } - - public String getClientPrincipal() { - return clientPrincipal; - } - - public void setClientPrincipal(String clientPrincipal) { - this.clientPrincipal = clientPrincipal; - } - - public String getClientKeytabFile() { - return clientKeytabFile; - } - - public void setClientKeytabFile(String clientKeytabFile) { - this.clientKeytabFile = clientKeytabFile; - } - - public String getBatchSize() { - return batchSize; - } - - public void setBatchSize(String batchSize) { - this.batchSize = batchSize; - } - - public String getBatchWaitInterval() { - return batchWaitInterval; - } - - public void setBatchWaitInterval(String batchWaitInterval) { - this.batchWaitInterval = batchWaitInterval; - } - } diff --git a/hbase/hbase-sink/src/test/java/com/dtstack/flink/sql/sink/hbase/HbaseConfigUtilsTest.java b/hbase/hbase-sink/src/test/java/com/dtstack/flink/sql/sink/hbase/HbaseConfigUtilsTest.java deleted file mode 100644 index 866c10753..000000000 --- a/hbase/hbase-sink/src/test/java/com/dtstack/flink/sql/sink/hbase/HbaseConfigUtilsTest.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.hbase; - -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.security.UserGroupInformation; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -import java.io.File; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.powermock.api.mockito.PowerMockito.whenNew; -import static org.powermock.api.support.membermodification.MemberModifier.suppress; - -/** - * @author: chuixue - * @create: 2020-08-12 15:35 - * @description: - **/ -@RunWith(PowerMockRunner.class) -@PrepareForTest({ - HbaseConfigUtils.class, - UserGroupInformation.class}) -public class HbaseConfigUtilsTest { - - @Test - public void testLoginAndReturnUGI() throws Exception { - suppress(UserGroupInformation.class.getMethod("setConfiguration", Configuration.class)); - suppress(UserGroupInformation.class.getMethod("loginUserFromKeytabAndReturnUGI", String.class, String.class)); - - File myFile = mock(File.class); - whenNew(File.class).withAnyArguments().thenReturn(myFile); - when(myFile.exists()).thenReturn(true); - - HbaseConfigUtils.loginAndReturnUGI(new Configuration(), "principal", "keytab"); - } -} diff --git a/hbase/hbase-sink/src/test/java/com/dtstack/flink/sql/sink/hbase/HbaseOutputFormatTest.java b/hbase/hbase-sink/src/test/java/com/dtstack/flink/sql/sink/hbase/HbaseOutputFormatTest.java deleted file mode 100644 index d362fcd4f..000000000 --- a/hbase/hbase-sink/src/test/java/com/dtstack/flink/sql/sink/hbase/HbaseOutputFormatTest.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.hbase; - -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.configuration.Configuration; -import org.apache.flink.metrics.Counter; -import org.apache.flink.types.Row; -import org.apache.hadoop.hbase.HBaseConfiguration; -import org.apache.hadoop.hbase.TableName; -import org.apache.hadoop.hbase.client.Connection; -import org.apache.hadoop.hbase.client.ConnectionFactory; -import org.apache.hadoop.hbase.client.Table; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.InjectMocks; -import org.mockito.MockitoAnnotations; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.api.support.membermodification.MemberModifier; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -import java.io.IOException; -import java.util.Date; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.when; - -/** - * @author: chuixue - * @create: 2020-07-07 19:29 - * @description: - **/ -@RunWith(PowerMockRunner.class) -@PrepareForTest({HbaseOutputFormat.class, - HBaseConfiguration.class, - Configuration.class, - ConnectionFactory.class, - TableName.class, - Table.class, - Counter.class}) -public class HbaseOutputFormatTest { - @InjectMocks - HbaseOutputFormat hbaseOutputFormat; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - } - - @Test - public void testConfigure() throws IllegalAccessException { - MemberModifier.field(HbaseOutputFormat.class, "host").set(hbaseOutputFormat, "localhost"); - MemberModifier.field(HbaseOutputFormat.class, "zkParent").set(hbaseOutputFormat, "/hbase"); - - org.apache.hadoop.conf.Configuration conf = new org.apache.hadoop.conf.Configuration(); - PowerMockito.mockStatic(HBaseConfiguration.class); - when(HBaseConfiguration.create()).thenReturn(conf); - - Configuration configuration = new Configuration(); - hbaseOutputFormat.configure(configuration); - } - - public void testOpen() throws IOException { - PowerMockito.mockStatic(ConnectionFactory.class); - Connection conn = PowerMockito.mock(Connection.class); - PowerMockito.mockStatic(TableName.class); - TableName tableName = PowerMockito.mock(TableName.class); - Table table = PowerMockito.mock(Table.class); - - when(ConnectionFactory.createConnection(any())).thenReturn(conn); - when(conn.getTable(any())).thenReturn(table); - when(TableName.valueOf(anyString())).thenReturn(tableName); - doNothing().when(hbaseOutputFormat).initMetric(); - - hbaseOutputFormat.open(1, 2); - } - - // @Test - public void testWriteRecord() throws IllegalAccessException { - MemberModifier.field(HbaseOutputFormat.class, "columnNames").set(hbaseOutputFormat, new String[]{"f:a", "f:b", "f:c"}); - MemberModifier.field(HbaseOutputFormat.class, "rowkey").set(hbaseOutputFormat, "md5('1')"); - MemberModifier.field(HbaseOutputFormat.class, "families").set(hbaseOutputFormat, new String[]{"f", "f", "f"}); - MemberModifier.field(HbaseOutputFormat.class, "qualifiers").set(hbaseOutputFormat, new String[]{"a", "b", "c"}); - Table table = PowerMockito.mock(Table.class); - MemberModifier.field(HbaseOutputFormat.class, "table").set(hbaseOutputFormat, table); - Counter outRecords = PowerMockito.mock(Counter.class); - MemberModifier.field(HbaseOutputFormat.class, "outRecords").set(hbaseOutputFormat, outRecords); - - Row row = new Row(3); - row.setField(0, "aaaa"); - row.setField(1, "bbbb"); - row.setField(2, new Date()); - - Tuple2 tuplea = new Tuple2(true, row); - hbaseOutputFormat.writeRecord(tuplea); - - Tuple2 tupleb = new Tuple2(false, row); - hbaseOutputFormat.writeRecord(tupleb); - } -} diff --git a/hbase/hbase-sink/src/test/java/com/dtstack/flink/sql/sink/hbase/HbaseSinkTest.java b/hbase/hbase-sink/src/test/java/com/dtstack/flink/sql/sink/hbase/HbaseSinkTest.java deleted file mode 100644 index 62b101682..000000000 --- a/hbase/hbase-sink/src/test/java/com/dtstack/flink/sql/sink/hbase/HbaseSinkTest.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.hbase; - -import com.dtstack.flink.sql.sink.hbase.table.HbaseTableInfo; -import org.apache.flink.streaming.api.datastream.DataStream; -import org.apache.flink.streaming.api.datastream.DataStreamSink; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.InjectMocks; -import org.mockito.MockitoAnnotations; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.api.support.membermodification.MemberModifier; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.when; - -import java.util.HashMap; -import java.util.Map; - -/** - * @author: chuixue - * @create: 2020-07-08 09:17 - * @description: - **/ -@RunWith(PowerMockRunner.class) -@PrepareForTest({DataStream.class, - HbaseSink.class}) -public class HbaseSinkTest { - - @InjectMocks - HbaseSink hbaseSink; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - } - - // @Test - public void testEmitDataStream() throws IllegalAccessException { - MemberModifier.field(HbaseSink.class, "zookeeperQuorum").set(hbaseSink, "localhost"); - MemberModifier.field(HbaseSink.class, "parent").set(hbaseSink, "/hbase"); - MemberModifier.field(HbaseSink.class, "tableName").set(hbaseSink, "tableName"); - MemberModifier.field(HbaseSink.class, "rowkey").set(hbaseSink, "rowkey"); - MemberModifier.field(HbaseSink.class, "updateMode").set(hbaseSink, "append"); - MemberModifier.field(HbaseSink.class, "fieldNames").set(hbaseSink, new String[]{"a", "b", "c"}); - MemberModifier.field(HbaseSink.class, "registerTabName").set(hbaseSink, "registerTabName"); - Map columnNameFamily = new HashMap(); - columnNameFamily.put("f:a", "a"); - columnNameFamily.put("f:b", "b"); - columnNameFamily.put("f:c", "c"); - MemberModifier.field(HbaseSink.class, "columnNameFamily").set(hbaseSink, columnNameFamily); - - DataStream dataStream = PowerMockito.mock(DataStream.class); - DataStreamSink dataStreamSink = PowerMockito.mock(DataStreamSink.class); - when(dataStream.addSink(any())).thenReturn(dataStreamSink); - when(dataStreamSink.name(any())).thenReturn(dataStreamSink); -// hbaseSink.emitDataStream(dataStream); - } - - @Test - public void testGenStreamSink() { - HbaseTableInfo hbaseTableInfo = new HbaseTableInfo(); - hbaseTableInfo.setHost("localhost"); - hbaseTableInfo.setPort("2181"); - hbaseTableInfo.setParent("/hbase"); - hbaseTableInfo.setTableName("tablename"); - hbaseTableInfo.setRowkey("rk"); - - Map columnNameFamily = new HashMap(); - columnNameFamily.put("f:a", "a"); - columnNameFamily.put("f:b", "b"); - columnNameFamily.put("f:c", "c"); - hbaseTableInfo.setColumnNameFamily(columnNameFamily); - hbaseTableInfo.setUpdateMode("append"); -// hbaseSink.genStreamSink(hbaseTableInfo); - } -} diff --git a/hbase/hbase-sink/src/test/java/com/dtstack/flink/sql/sink/hbase/HbaseUtilTest.java b/hbase/hbase-sink/src/test/java/com/dtstack/flink/sql/sink/hbase/HbaseUtilTest.java deleted file mode 100644 index 8d0300a42..000000000 --- a/hbase/hbase-sink/src/test/java/com/dtstack/flink/sql/sink/hbase/HbaseUtilTest.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.hbase; - -import org.apache.flink.api.common.typeinfo.BasicTypeInfo; -import org.apache.flink.api.common.typeinfo.IntegerTypeInfo; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.hadoop.io.IntWritable; -import org.apache.hadoop.io.Text; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -import static org.junit.Assert.assertEquals; - -/** - * @author: chuixue - * @create: 2020-07-07 15:44 - * @description: - **/ -@RunWith(PowerMockRunner.class) -@PrepareForTest({IntegerTypeInfo.class}) -public class HbaseUtilTest { - - @Test - public void testColumnTypeToTypeInformation() { - String[] types = new String[]{"TINYINT", "SMALLINT", "INT", "BIGINT", "FLOAT", "DOUBLE", "TIMESTAMP", "DATE", "STRING", "BOOLEAN"}; - for (String type : types) { - HbaseUtil.columnTypeToTypeInformation(type); - } - } -} diff --git a/hbase/hbase-sink/src/test/java/com/dtstack/flink/sql/sink/hbase/Md5ReplaceOperatorTest.java b/hbase/hbase-sink/src/test/java/com/dtstack/flink/sql/sink/hbase/Md5ReplaceOperatorTest.java deleted file mode 100644 index 3da548ca0..000000000 --- a/hbase/hbase-sink/src/test/java/com/dtstack/flink/sql/sink/hbase/Md5ReplaceOperatorTest.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.hbase; - -import com.dtstack.flink.sql.sink.hbase.enums.EReplaceOpType; -import com.dtstack.flink.sql.util.MD5Utils; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -import static org.junit.Assert.assertEquals; - -/** - * @author: chuixue - * @create: 2020-07-07 15:31 - * @description: - **/ -public class Md5ReplaceOperatorTest { - - private Md5ReplaceOperator md5ReplaceOperator; - - @Before - public void setUp() { - md5ReplaceOperator = new Md5ReplaceOperator(EReplaceOpType.MD5_FUNC); - } - - @Test - public void testDoFun() { - String md5 = md5ReplaceOperator.doFunc("md5"); - assertEquals("1bc29b36f623ba82aaf6724fd3b16718", md5); - } -} diff --git a/hbase/hbase-sink/src/test/java/com/dtstack/flink/sql/sink/hbase/table/HbaseSinkParserTest.java b/hbase/hbase-sink/src/test/java/com/dtstack/flink/sql/sink/hbase/table/HbaseSinkParserTest.java deleted file mode 100644 index e5118f189..000000000 --- a/hbase/hbase-sink/src/test/java/com/dtstack/flink/sql/sink/hbase/table/HbaseSinkParserTest.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.hbase.table; - -import com.dtstack.flink.sql.table.AbstractTableInfo; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -import java.util.HashMap; -import java.util.Map; - -/** - * @author: chuixue - * @create: 2020-07-08 09:50 - * @description: - **/ -public class HbaseSinkParserTest { - - private HbaseSinkParser hbaseSinkParser; - - @Before - public void setUp() { - hbaseSinkParser = new HbaseSinkParser(); - } - - @Test - public void testGetTableInfo() { - String fieldsInfo = "cf:name varchar," + - " cf:info varchar as f2, " + - " cf:other varchar as f3"; - - Map prop = new HashMap(); - - prop.put("type", "hbase"); - prop.put("zookeeperQuorum", "172.16.101.247:2181"); - prop.put("zookeeperParent", "/hbase"); - prop.put("tableName", "test"); - prop.put("cache", "lru"); - - hbaseSinkParser.getTableInfo("tablename", fieldsInfo, prop); - } - -} diff --git a/hbase/pom.xml b/hbase/pom.xml index 1bc473b70..835457e29 100644 --- a/hbase/pom.xml +++ b/hbase/pom.xml @@ -17,6 +17,12 @@ + + junit + junit + 3.8.1 + test + com.dtstack.flink sql.core diff --git a/http/http-sink/pom.xml b/http/http-sink/pom.xml deleted file mode 100644 index 6a6c8408f..000000000 --- a/http/http-sink/pom.xml +++ /dev/null @@ -1,81 +0,0 @@ - - - - sql.http - com.dtstack.flink - 1.0-SNAPSHOT - - 4.0.0 - - sql.sink.http - http-sink - - - - - org.apache.maven.plugins - maven-shade-plugin - 1.4 - - - package - - shade - - - false - - - org.slf4j:* - org.apache.hadoop:hadoop-common - org.apache.hadoop:hadoop-auth - org.apache.hadoop:hadoop-mapreduce-client-core - - - - - *:* - - META-INF/*.SF - META-INF/*.DSA - META-INF/*.RSA - - - - - - - - - - maven-antrun-plugin - 1.2 - - - copy-resources - - package - - run - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/http/http-sink/src/main/java/com/dtstack/flink/sql/sink/http/DtHttpClient.java b/http/http-sink/src/main/java/com/dtstack/flink/sql/sink/http/DtHttpClient.java deleted file mode 100644 index 7b7654b02..000000000 --- a/http/http-sink/src/main/java/com/dtstack/flink/sql/sink/http/DtHttpClient.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.http; - -import com.dtstack.flink.sql.util.PluginUtil; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.config.Registry; -import org.apache.http.config.RegistryBuilder; -import org.apache.http.conn.socket.ConnectionSocketFactory; -import org.apache.http.conn.socket.PlainConnectionSocketFactory; -import org.apache.http.conn.ssl.SSLConnectionSocketFactory; -import org.apache.http.entity.StringEntity; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; -import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.util.Map; - - -/** - * @author tiezhu - * @date 2021/3/22 星期一 - * Company dtstack - */ -public class DtHttpClient { - - private static final Logger LOG = LoggerFactory.getLogger(DtHttpClient.class); - - private static final int DEFAULT_MAX_TOTAL = 20; - - private static final int DEFAULT_MAX_PER_ROUTE = 20; - - private static final int DEFAULT_SOCKET_TIMEOUT = 5000;// 5秒 - - private static final int DEFAULT_CONNECT_TIMEOUT = 5000;// 5秒 - - private static final int DEFAULT_TIME_OUT = 10000;// 10秒 - - private static final String DEFAULT_CONTENT_TYPE = "application/json"; - - private static final String DEFAULT_CONTENT_ENCODING = "UTF-8"; - - private static final CloseableHttpClient httpClient; - - private static final RequestConfig requestConfig; - - static { - httpClient = createHttpClient(); - requestConfig = RequestConfig.custom() - .setSocketTimeout(DEFAULT_TIME_OUT) - .setConnectTimeout(DEFAULT_TIME_OUT) - .setConnectionRequestTimeout(DEFAULT_TIME_OUT) - .build(); - } - - private static CloseableHttpClient createHttpClient() { - LOG.info(" init http pool ..."); - PlainConnectionSocketFactory plainConnectionSocketFactory = PlainConnectionSocketFactory.getSocketFactory(); - SSLConnectionSocketFactory sslConnectionSocketFactory = SSLConnectionSocketFactory.getSocketFactory(); - Registry registry = RegistryBuilder - .create() - .register("http", plainConnectionSocketFactory) - .register("https", sslConnectionSocketFactory) - .build(); - PoolingHttpClientConnectionManager manager = new PoolingHttpClientConnectionManager(registry); - manager.setMaxTotal(DEFAULT_MAX_TOTAL); - manager.setDefaultMaxPerRoute(DEFAULT_MAX_PER_ROUTE); - - //设置请求和传输超时时间 - RequestConfig requestConfig = RequestConfig.custom() - //设置从connect Manager获取Connection 超时时间,单位毫秒。这个属性是新加的属性,因为目前版本是可以共享连接池的。 - .setConnectionRequestTimeout(DEFAULT_CONNECT_TIMEOUT) - //请求获取数据的超时时间,单位毫秒。 如果访问一个接口,多少时间内无法返回数据,就直接放弃此次调用。 - .setSocketTimeout(DEFAULT_SOCKET_TIMEOUT) - //设置连接超时时间,单位毫秒。 - .setConnectTimeout(DEFAULT_CONNECT_TIMEOUT) - .build(); - - return HttpClients.custom() - .setDefaultRequestConfig(requestConfig) - .setConnectionManager(manager) - .setRetryHandler(new SqlHttpRequestRetryHandler()) - .build(); - } - - public static void post(String httpUrl, String message) throws IOException { - post(httpUrl, message, DEFAULT_CONTENT_TYPE, DEFAULT_CONTENT_ENCODING); - } - - public static void post(String httpUrl, Map message) throws IOException { - post(httpUrl, PluginUtil.objectToString(message), DEFAULT_CONTENT_TYPE, DEFAULT_CONTENT_ENCODING); - } - - public static void post(String httpUrl, - String message, - String contentType, - String contentEncoding) throws IOException { - HttpPost httpPost = new HttpPost(httpUrl); - httpPost.setConfig(requestConfig); - StringEntity entity = new StringEntity(message, contentEncoding); - entity.setContentType(contentType); - entity.setContentEncoding(contentEncoding); - httpPost.setEntity(entity); - try (final CloseableHttpResponse response = httpClient.execute(httpPost)) { - LOG.debug("Get response: {}", response.getStatusLine().getStatusCode()); - } - } - - public static void close() { - if (httpClient != null) { - try { - httpClient.close(); - } catch (IOException e) { - LOG.error("DtHttpClient close error!", e); - } - } - } -} diff --git a/http/http-sink/src/main/java/com/dtstack/flink/sql/sink/http/HttpOutputFormat.java b/http/http-sink/src/main/java/com/dtstack/flink/sql/sink/http/HttpOutputFormat.java deleted file mode 100644 index 8c5c26427..000000000 --- a/http/http-sink/src/main/java/com/dtstack/flink/sql/sink/http/HttpOutputFormat.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.http; - -import com.dtstack.flink.sql.outputformat.AbstractDtRichOutputFormat; -import com.dtstack.flink.sql.sink.http.table.HttpTableInfo; -import com.dtstack.flink.sql.util.PluginUtil; -import com.dtstack.flink.sql.util.ThreadUtil; -import org.apache.commons.lang.StringUtils; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.configuration.Configuration; -import org.apache.flink.types.Row; -import org.apache.flink.util.Preconditions; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.util.HashMap; - -/** - * @author: chuixue - * @create: 2021-03-03 10:41 - * @description: - **/ -public class HttpOutputFormat extends AbstractDtRichOutputFormat> { - private static final Logger LOG = LoggerFactory.getLogger(HttpOutputFormat.class); - - /** - * Default connection timeout when connecting to the server socket (infinite). - */ - private HttpTableInfo httpTableInfo; - - private HttpOutputFormat() { - } - - public static HttpOutputFormatBuilder buildHttpOutputFormat() { - return new HttpOutputFormatBuilder(); - } - - @Override - public void configure(Configuration parameters) { - - } - - @Override - public void open(int taskNumber, int numTasks) { - initMetric(); - } - - @Override - public void writeRecord(Tuple2 record) { - if (!record.f0) { - return; - } - - String value = null; - HashMap map = new HashMap<>(); - try { - // not empty ,need send flag、tablename、fieldinfo、value. - if (StringUtils.isNotEmpty(httpTableInfo.getFlag())) { - map.put("flag", httpTableInfo.getFlag()); - map.put("tableName", httpTableInfo.getName()); - } - - // add field - String[] fields = httpTableInfo.getFields(); - Row row = record.getField(1); - for (int i = 0; i < fields.length; i++) { - map.put(fields[i], row.getField(i)); - } - - // post request - value = PluginUtil.objectToString(map); - DtHttpClient.post(httpTableInfo.getUrl(), value); - - // metrics - outRecords.inc(); - if (outRecords.getCount() % ROW_PRINT_FREQUENCY == 0) { - LOG.info("row data: {}", value); - } - ThreadUtil.sleepMilliseconds(httpTableInfo.getDelay()); - } catch (IOException e) { - if (outDirtyRecords.getCount() % DIRTY_PRINT_FREQUENCY == 0 || LOG.isDebugEnabled()) { - LOG.error("record insert failed ..{}", value); - LOG.error("", e); - } - outDirtyRecords.inc(); - } - } - - @Override - public void close() { - DtHttpClient.close(); - } - - public static class HttpOutputFormatBuilder { - private final HttpOutputFormat httpOutputFormat; - - protected HttpOutputFormatBuilder() { - this.httpOutputFormat = new HttpOutputFormat(); - } - - public HttpOutputFormatBuilder setHttpTableInfo(HttpTableInfo httpTableInfo) { - httpOutputFormat.httpTableInfo = httpTableInfo; - return this; - } - - public HttpOutputFormat finish() { - Preconditions.checkNotNull(httpOutputFormat.httpTableInfo.getUrl(), "No url supplied."); - return httpOutputFormat; - } - } -} diff --git a/http/http-sink/src/main/java/com/dtstack/flink/sql/sink/http/HttpSink.java b/http/http-sink/src/main/java/com/dtstack/flink/sql/sink/http/HttpSink.java deleted file mode 100644 index 28dc9a0e4..000000000 --- a/http/http-sink/src/main/java/com/dtstack/flink/sql/sink/http/HttpSink.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.http; - -import com.dtstack.flink.sql.sink.IStreamSinkGener; -import com.dtstack.flink.sql.sink.http.table.HttpTableInfo; -import com.dtstack.flink.sql.table.AbstractTargetTableInfo; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.api.java.typeutils.TupleTypeInfo; -import org.apache.flink.streaming.api.datastream.DataStream; -import org.apache.flink.streaming.api.datastream.DataStreamSink; -import org.apache.flink.streaming.api.functions.sink.OutputFormatSinkFunction; -import org.apache.flink.streaming.api.functions.sink.RichSinkFunction; -import org.apache.flink.table.sinks.RetractStreamTableSink; -import org.apache.flink.table.sinks.TableSink; -import org.apache.flink.types.Row; - -/** - * @author: chuixue - * @create: 2021-03-03 10:40 - * @description: - **/ -public class HttpSink implements RetractStreamTableSink, IStreamSinkGener { - protected String[] fieldNames; - - protected TypeInformation[] fieldTypes; - - protected HttpTableInfo httpTableInfo; - - public HttpSink() { - } - - @Override - public HttpSink genStreamSink(AbstractTargetTableInfo targetTableInfo) { - this.httpTableInfo = (HttpTableInfo) targetTableInfo; - return this; - } - - @Override - public TypeInformation getRecordType() { - return new RowTypeInfo(fieldTypes, fieldNames); - } - - @Override - public void emitDataStream(DataStream> dataStream) { - consumeDataStream(dataStream); - } - - @Override - public DataStreamSink consumeDataStream(DataStream> dataStream) { - HttpOutputFormat.HttpOutputFormatBuilder builder = HttpOutputFormat.buildHttpOutputFormat(); - HttpOutputFormat httpOutputFormat = builder.setHttpTableInfo(this.httpTableInfo) - .finish(); - RichSinkFunction richSinkFunction = new OutputFormatSinkFunction(httpOutputFormat); - DataStreamSink dataStreamSink = dataStream.addSink(richSinkFunction) - .setParallelism(this.httpTableInfo.getParallelism()) - .name(this.httpTableInfo.getName()); - return dataStreamSink; - } - - @Override - public TupleTypeInfo> getOutputType() { - return new TupleTypeInfo(org.apache.flink.table.api.Types.BOOLEAN(), getRecordType()); - } - - @Override - public String[] getFieldNames() { - return fieldNames; - } - - @Override - public TypeInformation[] getFieldTypes() { - return fieldTypes; - } - - @Override - public TableSink> configure(String[] fieldNames, TypeInformation[] fieldTypes) { - this.fieldNames = fieldNames; - this.fieldTypes = fieldTypes; - return this; - } -} diff --git a/http/http-sink/src/main/java/com/dtstack/flink/sql/sink/http/SqlHttpRequestRetryHandler.java b/http/http-sink/src/main/java/com/dtstack/flink/sql/sink/http/SqlHttpRequestRetryHandler.java deleted file mode 100644 index 48206c42b..000000000 --- a/http/http-sink/src/main/java/com/dtstack/flink/sql/sink/http/SqlHttpRequestRetryHandler.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.http; - -import org.apache.http.HttpEntityEnclosingRequest; -import org.apache.http.HttpRequest; -import org.apache.http.NoHttpResponseException; -import org.apache.http.client.HttpRequestRetryHandler; -import org.apache.http.client.protocol.HttpClientContext; -import org.apache.http.protocol.HttpContext; - -import javax.net.ssl.SSLException; -import javax.net.ssl.SSLHandshakeException; -import java.io.IOException; -import java.io.InterruptedIOException; -import java.net.UnknownHostException; - -/** - * @author tiezhu - * @date 2021/3/22 星期一 - * Company dtstack - */ -public class SqlHttpRequestRetryHandler implements HttpRequestRetryHandler { - private static final Integer DEFAULT_MAX_RETRY_NUMBER = 5; - - @Override - public boolean retryRequest(IOException exception, int retryNumber, HttpContext httpContext) { - if (retryNumber >= DEFAULT_MAX_RETRY_NUMBER) {// 如果已经重试了5次,就放弃 - return false; - } - if (exception instanceof NoHttpResponseException) {// 如果服务器丢掉了连接,那么就重试 - return true; - } - if (exception instanceof SSLHandshakeException) {// 不要重试SSL握手异常 - return false; - } - if (exception instanceof InterruptedIOException) {// 超时 - return false; - } - if (exception instanceof UnknownHostException) {// 目标服务器不可达 - return false; - } - if (exception instanceof SSLException) {// SSL握手异常 - return false; - } - - HttpClientContext clientContext = HttpClientContext.adapt(httpContext); - HttpRequest request = clientContext.getRequest(); - // 如果请求是幂等的,就再次尝试 - return !(request instanceof HttpEntityEnclosingRequest); - } -} diff --git a/http/http-sink/src/main/java/com/dtstack/flink/sql/sink/http/table/HttpSinkParser.java b/http/http-sink/src/main/java/com/dtstack/flink/sql/sink/http/table/HttpSinkParser.java deleted file mode 100644 index a5ef3ed2b..000000000 --- a/http/http-sink/src/main/java/com/dtstack/flink/sql/sink/http/table/HttpSinkParser.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.http.table; - -import com.dtstack.flink.sql.table.AbstractTableInfo; -import com.dtstack.flink.sql.table.AbstractTableParser; -import com.dtstack.flink.sql.util.MathUtil; - -import java.util.Map; - -/** - * @author: chuixue - * @create: 2021-03-03 10:40 - * @description: - **/ -public class HttpSinkParser extends AbstractTableParser { - @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) throws Exception { - HttpTableInfo httpTableInfo = new HttpTableInfo(); - httpTableInfo.setName(tableName); - parseFieldsInfo(fieldsInfo, httpTableInfo); - httpTableInfo.setUrl(MathUtil.getString(props.get(HttpTableInfo.URL_KEY))); - httpTableInfo.setDelay(MathUtil.getIntegerVal(props.getOrDefault(HttpTableInfo.DELAY_KEY, 50))); - httpTableInfo.setFlag(MathUtil.getString(props.getOrDefault(HttpTableInfo.FLAG_KEY, ""))); - httpTableInfo.setMaxNumRetries(MathUtil.getIntegerVal(props.getOrDefault(HttpTableInfo.MAXNUMRETRIES_KEY, 3))); - - httpTableInfo.check(); - return httpTableInfo; - } - -} diff --git a/http/http-sink/src/main/java/com/dtstack/flink/sql/sink/http/table/HttpTableInfo.java b/http/http-sink/src/main/java/com/dtstack/flink/sql/sink/http/table/HttpTableInfo.java deleted file mode 100644 index 64d080f39..000000000 --- a/http/http-sink/src/main/java/com/dtstack/flink/sql/sink/http/table/HttpTableInfo.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.http.table; - -import avro.shaded.com.google.common.base.Preconditions; -import com.dtstack.flink.sql.table.AbstractTargetTableInfo; - -/** - * @author: chuixue - * @create: 2021-03-03 10:41 - * @description: - **/ -public class HttpTableInfo extends AbstractTargetTableInfo { - - private static final String CURR_TYPE = "http"; - - public static final String URL_KEY = "url"; - - public static final String DELAY_KEY = "delay"; - - public static final String FLAG_KEY = "flag"; - - public static final String MAXNUMRETRIES_KEY = "maxNumRetries"; - - public HttpTableInfo() { - super.setType(CURR_TYPE); - } - - private String url; - - private int delay; - - private String flag; - - private long maxNumRetries; - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - public int getDelay() { - return delay; - } - - public void setDelay(int delay) { - this.delay = delay; - } - - public String getFlag() { - return flag; - } - - public void setFlag(String flag) { - this.flag = flag; - } - - public long getMaxNumRetries() { - return maxNumRetries; - } - - public void setMaxNumRetries(long maxNumRetries) { - this.maxNumRetries = maxNumRetries; - } - - @Override - public boolean check() { - Preconditions.checkNotNull(url, "url not null"); - Preconditions.checkNotNull(maxNumRetries, "maxNumRetries name not null"); - - Preconditions.checkArgument(maxNumRetries >= -1, "maxNumRetries must be zero or larger (num retries), or -1 (infinite retries)"); - return false; - } -} diff --git a/http/http-sink/src/test/java/com/dtstack/flink/sql/flink/http/HttpSinkTest.java b/http/http-sink/src/test/java/com/dtstack/flink/sql/flink/http/HttpSinkTest.java deleted file mode 100644 index 9f55f8f8b..000000000 --- a/http/http-sink/src/test/java/com/dtstack/flink/sql/flink/http/HttpSinkTest.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.dtstack.flink.sql.flink.http; - -/** - * @author tiezhu - * @date 2021/3/18 星期四 - * Company dtstack - */ -public class HttpSinkTest { -} diff --git a/http/http-sink/src/test/java/com/dtstack/flink/sql/flink/http/table/HttpTableInfoTest.java b/http/http-sink/src/test/java/com/dtstack/flink/sql/flink/http/table/HttpTableInfoTest.java deleted file mode 100644 index b1fd8b131..000000000 --- a/http/http-sink/src/test/java/com/dtstack/flink/sql/flink/http/table/HttpTableInfoTest.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.flink.http.table; - -import com.dtstack.flink.sql.sink.http.table.HttpSinkParser; -import com.dtstack.flink.sql.sink.http.table.HttpTableInfo; -import com.dtstack.flink.sql.table.AbstractTableInfo; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import java.util.HashMap; - -/** - * @author tiezhu - * @date 2021/3/18 星期四 - * Company dtstack - */ -public class HttpTableInfoTest { - private static final HttpSinkParser parser = new HttpSinkParser(); - private HashMap map; - - @Before - public void setUp() { - map = new HashMap<>(); - map.put("type", "http"); - map.put("url", "localhost:9999"); - map.put("delay", "20"); - map.put("flag", "7f8717b2-110c-4012-8e3c-c1965e84ee75"); - } - - @Test - public void parsePropertiesAndGetTableInfo() throws Exception { - AbstractTableInfo tableInfo = parser.getTableInfo( - "Test", - "id int, name string", - map - ); - HttpTableInfo httpTableInfo = (HttpTableInfo) tableInfo; - Assert.assertEquals("http", httpTableInfo.getType()); - Assert.assertEquals(20, httpTableInfo.getDelay()); - } -} diff --git a/http/pom.xml b/http/pom.xml deleted file mode 100644 index 911b353b9..000000000 --- a/http/pom.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - flink.sql - com.dtstack.flink - 1.0-SNAPSHOT - - 4.0.0 - - sql.http - pom - - http-sink - - - - - com.dtstack.flink - sql.core - 1.0-SNAPSHOT - provided - - - - org.apache.httpcomponents - httpclient - 4.5.13 - - - - \ No newline at end of file diff --git a/impala/impala-side/impala-all-side/pom.xml b/impala/impala-side/impala-all-side/pom.xml deleted file mode 100644 index c62af7607..000000000 --- a/impala/impala-side/impala-all-side/pom.xml +++ /dev/null @@ -1,92 +0,0 @@ - - - - sql.side.impala - com.dtstack.flink - 1.0-SNAPSHOT - ../pom.xml - - 4.0.0 - - sql.side.all.impala - impala-all-side - jar - - - 1.0-SNAPSHOT - - - - - com.dtstack.flink - sql.side.impala.core - ${sql.side.impala.core.version} - - - - - - - org.apache.maven.plugins - maven-shade-plugin - 1.4 - - - package - - shade - - - - - com.fasterxml.jackson.* - org.slf4j - - - - - *:* - - META-INF/*.SF - META-INF/*.DSA - META-INF/*.RSA - - - - - - - - - - maven-antrun-plugin - 1.2 - - - copy-resources - - package - - run - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/impala/impala-side/impala-all-side/src/main/java/com/dtstack/flink/sql/side/impala/ImpalaAllReqRow.java b/impala/impala-side/impala-all-side/src/main/java/com/dtstack/flink/sql/side/impala/ImpalaAllReqRow.java deleted file mode 100644 index 2a99eef99..000000000 --- a/impala/impala-side/impala-all-side/src/main/java/com/dtstack/flink/sql/side/impala/ImpalaAllReqRow.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.impala; - -import com.dtstack.flink.sql.classloader.ClassLoaderManager; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.impala.table.ImpalaSideTableInfo; -import com.dtstack.flink.sql.side.rdb.all.AbstractRdbAllReqRow; -import com.dtstack.flink.sql.util.KrbUtils; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.hadoop.security.UserGroupInformation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.security.PrivilegedExceptionAction; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.SQLException; -import java.util.List; - -/** - * side operator with cache for all(period reload) - * Date: 2019/11/12 - * Company: www.dtstack.com - * - * @author xiuzhu - */ - -public class ImpalaAllReqRow extends AbstractRdbAllReqRow { - - private static final long serialVersionUID = 2098635140857937717L; - - private static final Logger LOG = LoggerFactory.getLogger(ImpalaAllReqRow.class); - - private static final String IMPALA_DRIVER = "com.cloudera.impala.jdbc41.Driver"; - - private ImpalaSideTableInfo impalaSideTableInfo; - - public ImpalaAllReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { - super(new ImpalaAllSideInfo(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo)); - this.impalaSideTableInfo = (ImpalaSideTableInfo) sideTableInfo; - } - - @Override - public Connection getConn(String dbUrl, String userName, String password) { - try { - Connection connection; - String url = getUrl(); - ClassLoaderManager.forName(IMPALA_DRIVER, getClass().getClassLoader()); - // Kerberos - if (impalaSideTableInfo.getAuthMech() == 1) { - String keyTabFilePath = impalaSideTableInfo.getKeyTabFilePath(); - String krb5FilePath = impalaSideTableInfo.getKrb5FilePath(); - String principal = impalaSideTableInfo.getPrincipal(); - UserGroupInformation ugi = KrbUtils.loginAndReturnUgi(principal, keyTabFilePath, krb5FilePath); - connection = ugi.doAs(new PrivilegedExceptionAction() { - @Override - public Connection run() throws SQLException { - return DriverManager.getConnection(url); - } - }); - } else { - connection = DriverManager.getConnection(url); - } - connection.setAutoCommit(false); - return connection; - } catch (Exception e) { - LOG.error("", e); - throw new RuntimeException("", e); - } - } - - public String getUrl() throws IOException { - - String newUrl = ""; - Integer authMech = impalaSideTableInfo.getAuthMech(); - - StringBuffer urlBuffer = new StringBuffer(impalaSideTableInfo.getUrl()); - if (authMech == 0) { - newUrl = urlBuffer.toString(); - - } else if (authMech == 1) { - String krbRealm = impalaSideTableInfo.getKrbRealm(); - String krbHostFQDN = impalaSideTableInfo.getKrbHostFQDN(); - String krbServiceName = impalaSideTableInfo.getKrbServiceName(); - urlBuffer.append(";" - .concat("AuthMech=1;") - .concat("KrbRealm=").concat(krbRealm).concat(";") - .concat("KrbHostFQDN=").concat(krbHostFQDN).concat(";") - .concat("KrbServiceName=").concat(krbServiceName).concat(";") - ); - newUrl = urlBuffer.toString(); - - - } else if (authMech == 2) { - String uName = impalaSideTableInfo.getUserName(); - urlBuffer.append(";" - .concat("AuthMech=3;") - .concat("UID=").concat(uName).concat(";") - .concat("PWD=;") - .concat("UseSasl=0") - ); - newUrl = urlBuffer.toString(); - - } else if (authMech == 3) { - String uName = impalaSideTableInfo.getUserName(); - String pwd = impalaSideTableInfo.getPassword(); - urlBuffer.append(";" - .concat("AuthMech=3;") - .concat("UID=").concat(uName).concat(";") - .concat("PWD=").concat(pwd) - ); - newUrl = urlBuffer.toString(); - - } else { - throw new IllegalArgumentException("The value of authMech is illegal, Please select 0, 1, 2, 3"); - } - - return newUrl; - } -} diff --git a/impala/impala-side/impala-all-side/src/main/java/com/dtstack/flink/sql/side/impala/ImpalaAllSideInfo.java b/impala/impala-side/impala-all-side/src/main/java/com/dtstack/flink/sql/side/impala/ImpalaAllSideInfo.java deleted file mode 100644 index a5e643967..000000000 --- a/impala/impala-side/impala-all-side/src/main/java/com/dtstack/flink/sql/side/impala/ImpalaAllSideInfo.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.impala; - -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.impala.table.ImpalaSideTableInfo; -import com.dtstack.flink.sql.side.rdb.all.RdbAllSideInfo; -import org.apache.flink.api.java.typeutils.RowTypeInfo; - -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -public class ImpalaAllSideInfo extends RdbAllSideInfo { - - public ImpalaAllSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { - super(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); - } - - @Override - public String getAdditionalWhereClause() { - ImpalaSideTableInfo impalaSideTableInfo = (ImpalaSideTableInfo) sideTableInfo; - return impalaSideTableInfo.isEnablePartition() ? buildPartitionCondition(impalaSideTableInfo) : ""; - } - - private String buildPartitionCondition(ImpalaSideTableInfo impalaSideTableInfo) { - String partitionCondtion = " "; - String[] partitionfields = impalaSideTableInfo.getPartitionfields(); - String[] partitionFieldTypes = impalaSideTableInfo.getPartitionFieldTypes(); - Map partitionVaules = impalaSideTableInfo.getPartitionValues(); - - int fieldsSize = partitionfields.length; - for (int i = 0; i < fieldsSize; i++) { - String fieldName = partitionfields[i]; - String fieldType = partitionFieldTypes[i]; - List values = partitionVaules.get(fieldName); - String partitionVaule = getPartitionVaule(fieldType, values); - partitionCondtion += String.format("AND %s IN (%s) ", fieldName, partitionVaule); - } - return partitionCondtion; - } - - private String getPartitionVaule(String fieldType, List values) { - String partitionVaule = values.stream().map(val -> { - return ("string".equals(fieldType.toLowerCase()) || "varchar".equals(fieldType.toLowerCase())) ? "'" + val + "'" : val.toString(); - }).collect(Collectors.joining(" , ")).toString(); - - return partitionVaule; - } - -} diff --git a/impala/impala-side/impala-all-side/src/test/java/com/dtstack/flink/sql/side/impala/ImpalaAllReqRowTest.java b/impala/impala-side/impala-all-side/src/test/java/com/dtstack/flink/sql/side/impala/ImpalaAllReqRowTest.java deleted file mode 100644 index 909388a9e..000000000 --- a/impala/impala-side/impala-all-side/src/test/java/com/dtstack/flink/sql/side/impala/ImpalaAllReqRowTest.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.dtstack.flink.sql.side.impala; - -import com.dtstack.flink.sql.side.impala.table.ImpalaSideParser; -import com.dtstack.flink.sql.side.rdb.all.RdbAllReqRowTestBase; -import com.dtstack.flink.sql.table.AbstractTableInfo; -import org.junit.Before; -import org.junit.Test; -import org.powermock.reflect.Whitebox; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -public class ImpalaAllReqRowTest extends RdbAllReqRowTestBase { - - @Override - protected void init() { - clazz = ImpalaAllReqRow.class; - } - -// @Test - public void testGetUrl() throws IOException { - final String tableName = "table_foo"; - final String fieldsInfo = "id INT, name VARCHAR, PRIMARY KEY (id)"; - - Map props = new HashMap(); - props.put("authmech", 3); - - props.put("enablepartition", "true"); - props.put("partitionvalues", "{\"name\":[\"tom\",\"jeck\"]}"); - props.put("partitionfields", "name"); - props.put("partitionfieldtypes", "varchar"); - - props.put("url", "jdbc:hive2://myhost.example.com:21050/;principal=impala/myhost.example.com@H2.EXAMPLE.COM"); - props.put("tablename", "table_foo"); - props.put("username", "foo"); - props.put("password", "foo"); - - ImpalaAllReqRow rq = (ImpalaAllReqRow) reqRow; - ImpalaSideParser sinkParser = new ImpalaSideParser(); - AbstractTableInfo tableInfo = sinkParser.getTableInfo(tableName, fieldsInfo, props); - Whitebox.setInternalState(reqRow, "impalaSideTableInfo", tableInfo); - rq.getUrl(); - - props.put("authmech", 2); - tableInfo = sinkParser.getTableInfo(tableName, fieldsInfo, props); - Whitebox.setInternalState(reqRow, "impalaSideTableInfo", tableInfo); - rq.getUrl(); - - props.put("authmech", 1); - props.put("principal", ""); - props.put("keytabfilepath", "/foo/bar.keytab"); - props.put("krb5filepath", "krb5.conf"); - props.put("krbhostfqdn", ""); - props.put("krbservicename", ""); - tableInfo = sinkParser.getTableInfo(tableName, fieldsInfo, props); - Whitebox.setInternalState(reqRow, "impalaSideTableInfo", tableInfo); - rq.getUrl(); - } - -} \ No newline at end of file diff --git a/impala/impala-side/impala-all-side/src/test/java/com/dtstack/flink/sql/side/impala/ImpalaAllSideInfoTest.java b/impala/impala-side/impala-all-side/src/test/java/com/dtstack/flink/sql/side/impala/ImpalaAllSideInfoTest.java deleted file mode 100644 index 2da045646..000000000 --- a/impala/impala-side/impala-all-side/src/test/java/com/dtstack/flink/sql/side/impala/ImpalaAllSideInfoTest.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.dtstack.flink.sql.side.impala; - -import com.dtstack.flink.sql.side.impala.table.ImpalaSideParser; -import com.dtstack.flink.sql.table.AbstractTableInfo; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.powermock.reflect.Whitebox; - -import java.util.HashMap; -import java.util.Map; - -import static org.junit.Assert.*; - -public class ImpalaAllSideInfoTest { - - ImpalaAllSideInfo sideInfo; - AbstractTableInfo tableInfo; - - @Before - public void setUp() { - sideInfo = Whitebox.newInstance(ImpalaAllSideInfo.class); - final String tableName = "table_foo"; - final String fieldsInfo = "id INT, name VARCHAR, PRIMARY KEY (id)"; - - Map props = new HashMap(); - props.put("authmech", 3); - props.put("enablepartition", "true"); - props.put("partitionvalues", "{\"name\":[\"tom\",\"jeck\"]}"); - props.put("partitionfields", "name"); - props.put("partitionfieldtypes", "varchar"); - props.put("url", "jdbc:hive2://myhost.example.com:21050/;principal=impala/myhost.example.com@H2.EXAMPLE.COM"); - props.put("tablename", "table_foo"); - props.put("username", "foo"); - props.put("password", "foo"); - - ImpalaSideParser sinkParser = new ImpalaSideParser(); - tableInfo = sinkParser.getTableInfo(tableName, fieldsInfo, props); - Whitebox.setInternalState(sideInfo, "sideTableInfo", tableInfo); - - } - - @Test - public void testGetAdditionalWhereClause() { - String condition = sideInfo.getAdditionalWhereClause(); - String normal = " AND name IN ('tom' , 'jeck') "; - Assert.assertTrue(normal.equals(condition)); - } -} \ No newline at end of file diff --git a/impala/impala-side/impala-async-side/pom.xml b/impala/impala-side/impala-async-side/pom.xml deleted file mode 100644 index b7841b1da..000000000 --- a/impala/impala-side/impala-async-side/pom.xml +++ /dev/null @@ -1,94 +0,0 @@ - - - - sql.side.impala - com.dtstack.flink - 1.0-SNAPSHOT - ../pom.xml - - 4.0.0 - - sql.side.async.impala - impala-async-side - - jar - - - 1.0-SNAPSHOT - - - - - com.dtstack.flink - sql.side.impala.core - ${sql.side.impala.core.version} - - - - - - - org.apache.maven.plugins - maven-shade-plugin - 1.4 - - - package - - shade - - - - - com.fasterxml.jackson.* - org.slf4j - - - - - *:* - - META-INF/*.SF - META-INF/*.DSA - META-INF/*.RSA - - - - - - - - - - maven-antrun-plugin - 1.2 - - - copy-resources - - package - - run - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/impala/impala-side/impala-async-side/src/main/java/com/dtstack/flink/sql/side/impala/ImpalaAsyncReqRow.java b/impala/impala-side/impala-async-side/src/main/java/com/dtstack/flink/sql/side/impala/ImpalaAsyncReqRow.java deleted file mode 100644 index 7eee84332..000000000 --- a/impala/impala-side/impala-async-side/src/main/java/com/dtstack/flink/sql/side/impala/ImpalaAsyncReqRow.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.impala; - -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.impala.table.ImpalaSideTableInfo; -import com.dtstack.flink.sql.side.rdb.async.RdbAsyncReqRow; -import com.dtstack.flink.sql.util.KrbUtils; -import io.vertx.core.json.JsonObject; -import io.vertx.ext.sql.SQLClient; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.configuration.Configuration; -import org.apache.flink.runtime.execution.SuppressRestartsException; -import org.apache.flink.streaming.api.functions.async.ResultFuture; -import org.apache.flink.table.dataformat.BaseRow; -import org.apache.hadoop.security.UserGroupInformation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.security.PrivilegedAction; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicLong; - -/** - * Date: 2019/11/12 - * Company: www.dtstack.com - * - * @author xiuzhu - */ - -public class ImpalaAsyncReqRow extends RdbAsyncReqRow { - - private static final Logger LOG = LoggerFactory.getLogger(ImpalaAsyncReqRow.class); - - private final static String IMPALA_DRIVER = "com.cloudera.impala.jdbc41.Driver"; - - protected UserGroupInformation ugi = null; - - public ImpalaAsyncReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { - super(new ImpalaAsyncSideInfo(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo)); - } - - @Override - public void open(Configuration parameters) throws Exception { - super.open(parameters); - } - - @Override - public JsonObject buildJdbcConfig() { - ImpalaSideTableInfo impalaSideTableInfo = (ImpalaSideTableInfo) sideInfo.getSideTableInfo(); - - try { - if (impalaSideTableInfo.getAuthMech() == 1) { - String keyTabFilePath = impalaSideTableInfo.getKeyTabFilePath(); - String krb5FilePath = impalaSideTableInfo.getKrb5FilePath(); - String principal = impalaSideTableInfo.getPrincipal(); - ugi = KrbUtils.loginAndReturnUgi(principal, keyTabFilePath, krb5FilePath); - } - } catch (Exception e) { - throw new SuppressRestartsException( - new Throwable("impala login with kerberos error. cause by: " + e.getMessage())); - } - - JsonObject impalaClientConfig = new JsonObject(); - impalaClientConfig.put("url", getUrl()) - .put("driver_class", IMPALA_DRIVER) - .put("max_pool_size", impalaSideTableInfo.getAsyncPoolSize()) - .put("provider_class", DT_PROVIDER_CLASS) - .put("idle_connection_test_period", 300) - .put("test_connection_on_checkin", DEFAULT_TEST_CONNECTION_ON_CHECKIN) - .put("max_idle_time", 600) - .put("preferred_test_query", PREFERRED_TEST_QUERY_SQL) - .put("idle_connection_test_period", DEFAULT_IDLE_CONNECTION_TEST_PEROID) - .put("test_connection_on_checkin", DEFAULT_TEST_CONNECTION_ON_CHECKIN); - - return impalaClientConfig; - } - - public String getUrl() { - ImpalaSideTableInfo impalaSideTableInfo = (ImpalaSideTableInfo) sideInfo.getSideTableInfo(); - - String newUrl = ""; - Integer authMech = impalaSideTableInfo.getAuthMech(); - - StringBuffer urlBuffer = new StringBuffer(impalaSideTableInfo.getUrl()); - if (authMech == 0) { - newUrl = urlBuffer.toString(); - } else if (authMech == 1) { - String krbRealm = impalaSideTableInfo.getKrbRealm(); - String krbHostFQDN = impalaSideTableInfo.getKrbHostFQDN(); - String krbServiceName = impalaSideTableInfo.getKrbServiceName(); - urlBuffer.append(";" - .concat("AuthMech=1;") - .concat("KrbRealm=").concat(krbRealm).concat(";") - .concat("KrbHostFQDN=").concat(krbHostFQDN).concat(";") - .concat("KrbServiceName=").concat(krbServiceName).concat(";") - ); - newUrl = urlBuffer.toString(); - } else if (authMech == 2) { - String uName = impalaSideTableInfo.getUserName(); - urlBuffer.append(";" - .concat("AuthMech=3;") - .concat("UID=").concat(uName).concat(";") - .concat("PWD=;") - .concat("UseSasl=0") - ); - newUrl = urlBuffer.toString(); - } else if (authMech == 3) { - String uName = impalaSideTableInfo.getUserName(); - String pwd = impalaSideTableInfo.getPassword(); - urlBuffer.append(";" - .concat("AuthMech=3;") - .concat("UID=").concat(uName).concat(";") - .concat("PWD=").concat(pwd) - ); - newUrl = urlBuffer.toString(); - } else { - throw new IllegalArgumentException("The value of authMech is illegal, Please select 0, 1, 2, 3"); - } - return newUrl; - } - - @Override - protected void asyncQueryData(Map inputParams, - BaseRow input, - ResultFuture resultFuture, - SQLClient rdbSqlClient, - AtomicLong failCounter, - AtomicBoolean finishFlag, - CountDownLatch latch) { - if (ugi == null) { - doAsyncQueryData(inputParams, - input, resultFuture, - rdbSqlClient, - failCounter, - finishFlag, - latch); - } else { - // Kerberos - ugi.doAs(new PrivilegedAction() { - @Override - public Object run() { - doAsyncQueryData(inputParams, - input, resultFuture, - rdbSqlClient, - failCounter, - finishFlag, - latch); - return null; - } - }); - } - } -} diff --git a/impala/impala-side/impala-async-side/src/main/java/com/dtstack/flink/sql/side/impala/ImpalaAsyncSideInfo.java b/impala/impala-side/impala-async-side/src/main/java/com/dtstack/flink/sql/side/impala/ImpalaAsyncSideInfo.java deleted file mode 100644 index 14fbf0ed3..000000000 --- a/impala/impala-side/impala-async-side/src/main/java/com/dtstack/flink/sql/side/impala/ImpalaAsyncSideInfo.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.impala; - -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.impala.table.ImpalaSideTableInfo; -import com.dtstack.flink.sql.side.rdb.async.RdbAsyncSideInfo; -import org.apache.flink.api.java.typeutils.RowTypeInfo; - -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -/** - * Date: 2019/11/12 - * Company: www.dtstack.com - * - * @author xiuzhu - */ - -public class ImpalaAsyncSideInfo extends RdbAsyncSideInfo { - - public ImpalaAsyncSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { - super(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); - } - - @Override - public String getAdditionalWhereClause() { - ImpalaSideTableInfo impalaSideTableInfo = (ImpalaSideTableInfo) sideTableInfo; - return impalaSideTableInfo.isEnablePartition() ? buildPartitionCondition(impalaSideTableInfo) : ""; - } - - - private String buildPartitionCondition(ImpalaSideTableInfo impalaSideTableInfo) { - String partitionCondtion = " "; - String[] partitionfields = impalaSideTableInfo.getPartitionfields(); - String[] partitionFieldTypes = impalaSideTableInfo.getPartitionFieldTypes(); - Map partitionVaules = impalaSideTableInfo.getPartitionValues(); - - int fieldsSize = partitionfields.length; - for (int i = 0; i < fieldsSize; i++) { - String fieldName = partitionfields[i]; - String fieldType = partitionFieldTypes[i]; - List values = partitionVaules.get(fieldName); - String partitionVaule = getPartitionVaule(fieldType, values); - partitionCondtion += String.format("AND %s IN (%s) ", fieldName, partitionVaule); - } - return partitionCondtion; - } - - - private String getPartitionVaule(String fieldType, List values) { - String partitionVaule = values.stream().map(val -> { - return ("string".equals(fieldType.toLowerCase()) || "varchar".equals(fieldType.toLowerCase())) ? "'" + val + "'" : val.toString(); - }).collect(Collectors.joining(" , ")).toString(); - - return partitionVaule; - } - -} diff --git a/impala/impala-side/impala-async-side/src/test/java/com/dtstack/flink/sql/side/impala/ImpalaAsyncReqRowTest.java b/impala/impala-side/impala-async-side/src/test/java/com/dtstack/flink/sql/side/impala/ImpalaAsyncReqRowTest.java deleted file mode 100644 index ec1464843..000000000 --- a/impala/impala-side/impala-async-side/src/test/java/com/dtstack/flink/sql/side/impala/ImpalaAsyncReqRowTest.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.dtstack.flink.sql.side.impala; - -import com.dtstack.flink.sql.side.BaseSideInfo; -import com.dtstack.flink.sql.side.impala.table.ImpalaSideParser; -import com.dtstack.flink.sql.side.rdb.async.RdbAsyncReqRowTestBase; -import com.dtstack.flink.sql.table.AbstractTableInfo; -import org.junit.Before; -import org.junit.Test; -import org.powermock.reflect.Whitebox; - -import java.util.HashMap; -import java.util.Map; - -public class ImpalaAsyncReqRowTest { -// -// @Override -// protected void init() { -// clazz = ImpalaAsyncReqRow.class; -// } -// -// @Test -// public void testGetUrl() { -// final String tableName = "table_foo"; -// final String fieldsInfo = "id INT, name VARCHAR"; -// -// Map props = new HashMap(); -// props.put("authmech", 3); -// props.put("enablepartition", "true"); -// props.put("partitionvalues", "{\"name\":[\"tom\",\"jeck\"]}"); -// props.put("partitionfields", "name"); -// props.put("partitionfieldtypes", "varchar"); -// props.put("url", "jdbc:hive2://myhost.example.com:21050/;principal=impala/myhost.example.com@H2.EXAMPLE.COM"); -// props.put("tablename", "table_foo"); -// props.put("username", "foo"); -// props.put("password", "foo"); -// -// ImpalaAsyncReqRow rq = (ImpalaAsyncReqRow) reqRow; -// -// ImpalaSideParser sinkParser = new ImpalaSideParser(); -// AbstractTableInfo tableInfo = sinkParser.getTableInfo(tableName, fieldsInfo, props); -// -// BaseSideInfo sideInfo = Whitebox.newInstance(ImpalaAsyncSideInfo.class); -// Whitebox.setInternalState(sideInfo, "sideTableInfo", tableInfo); -// Whitebox.setInternalState(reqRow, "sideInfo", sideInfo); -// rq.getUrl(); -// -// props.put("authmech", 2); -// tableInfo = sinkParser.getTableInfo(tableName, fieldsInfo, props); -// sideInfo = Whitebox.newInstance(ImpalaAsyncSideInfo.class); -// Whitebox.setInternalState(sideInfo, "sideTableInfo", tableInfo); -// Whitebox.setInternalState(reqRow, "sideInfo", sideInfo); -// rq.getUrl(); -// -// props.put("authmech", 1); -// props.put("principal", ""); -// props.put("keytabfilepath", "/foo/bar.keytab"); -// props.put("krb5filepath", "krb5.conf"); -// props.put("krbhostfqdn", ""); -// props.put("krbservicename", ""); -// tableInfo = sinkParser.getTableInfo(tableName, fieldsInfo, props); -// sideInfo = Whitebox.newInstance(ImpalaAsyncSideInfo.class); -// Whitebox.setInternalState(sideInfo, "sideTableInfo", tableInfo); -// Whitebox.setInternalState(reqRow, "sideInfo", sideInfo); -// rq.getUrl(); -// } - -} \ No newline at end of file diff --git a/impala/impala-side/impala-async-side/src/test/java/com/dtstack/flink/sql/side/impala/ImpalaAsyncSideInfoTest.java b/impala/impala-side/impala-async-side/src/test/java/com/dtstack/flink/sql/side/impala/ImpalaAsyncSideInfoTest.java deleted file mode 100644 index b911fafd7..000000000 --- a/impala/impala-side/impala-async-side/src/test/java/com/dtstack/flink/sql/side/impala/ImpalaAsyncSideInfoTest.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.dtstack.flink.sql.side.impala; - -import com.dtstack.flink.sql.side.impala.table.ImpalaSideParser; -import com.dtstack.flink.sql.table.AbstractTableInfo; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.powermock.reflect.Whitebox; - -import java.util.HashMap; -import java.util.Map; - -public class ImpalaAsyncSideInfoTest { - - ImpalaAsyncSideInfo sideInfo; - AbstractTableInfo tableInfo; - - @Before - public void setUp() { - sideInfo = Whitebox.newInstance(ImpalaAsyncSideInfo.class); - final String tableName = "table_foo"; - final String fieldsInfo = "id INT, name VARCHAR, PRIMARY KEY (id)"; - - Map props = new HashMap(); - props.put("authmech", 3); - props.put("enablepartition", "true"); - props.put("partitionvalues", "{\"name\":[\"tom\",\"jeck\"]}"); - props.put("partitionfields", "name"); - props.put("partitionfieldtypes", "varchar"); - props.put("url", "jdbc:hive2://myhost.example.com:21050/;principal=impala/myhost.example.com@H2.EXAMPLE.COM"); - props.put("tablename", "table_foo"); - props.put("username", "foo"); - props.put("password", "foo"); - - ImpalaSideParser sinkParser = new ImpalaSideParser(); - tableInfo = sinkParser.getTableInfo(tableName, fieldsInfo, props); - Whitebox.setInternalState(sideInfo, "sideTableInfo", tableInfo); - - } - - @Test - public void testGetAdditionalWhereClause() { - String condition = sideInfo.getAdditionalWhereClause(); - String normal = " AND name IN ('tom' , 'jeck') "; - Assert.assertTrue(normal.equals(condition)); - } - -} \ No newline at end of file diff --git a/impala/impala-side/impala-side-core/pom.xml b/impala/impala-side/impala-side-core/pom.xml deleted file mode 100644 index 90eb29f03..000000000 --- a/impala/impala-side/impala-side-core/pom.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - sql.side.impala - com.dtstack.flink - 1.0-SNAPSHOT - ../pom.xml - - 4.0.0 - - sql.side.impala.core - 1.0-SNAPSHOT - jar - impala-side-core - - - \ No newline at end of file diff --git a/impala/impala-side/impala-side-core/src/main/java/com/dtstack/flink/sql/side/impala/table/ImpalaSideParser.java b/impala/impala-side/impala-side-core/src/main/java/com/dtstack/flink/sql/side/impala/table/ImpalaSideParser.java deleted file mode 100644 index 497359932..000000000 --- a/impala/impala-side/impala-side-core/src/main/java/com/dtstack/flink/sql/side/impala/table/ImpalaSideParser.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.impala.table; - -import com.dtstack.flink.sql.side.rdb.table.RdbSideParser; -import com.dtstack.flink.sql.side.rdb.table.RdbSideTableInfo; -import com.dtstack.flink.sql.table.AbstractTableInfo; -import com.dtstack.flink.sql.util.MathUtil; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.math.BigDecimal; -import java.sql.Timestamp; -import java.util.Arrays; -import java.util.List; -import java.util.Map; - - -/** - * Reason: - * Date: 2019/11/12 - * Company: www.dtstack.com - * - * @author xiuzhu - */ - -public class ImpalaSideParser extends RdbSideParser { - private static final Logger LOG = LoggerFactory.getLogger(ImpalaSideParser.class); - - private static final String CURR_TYPE = "impala"; - - @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { - ImpalaSideTableInfo impalaSideTableInfo = new ImpalaSideTableInfo(); - impalaSideTableInfo.setType(CURR_TYPE); - impalaSideTableInfo.setName(tableName); - parseFieldsInfo(fieldsInfo, impalaSideTableInfo); - - parseCacheProp(impalaSideTableInfo, props); - impalaSideTableInfo.setParallelism(MathUtil.getIntegerVal(props.get(ImpalaSideTableInfo.PARALLELISM_KEY.toLowerCase()))); - impalaSideTableInfo.setUrl(MathUtil.getString(props.get(ImpalaSideTableInfo.URL_KEY.toLowerCase()))); - impalaSideTableInfo.setTableName(MathUtil.getString(props.get(ImpalaSideTableInfo.TABLE_NAME_KEY.toLowerCase()))); - impalaSideTableInfo.setUserName(MathUtil.getString(props.get(ImpalaSideTableInfo.USER_NAME_KEY.toLowerCase()))); - impalaSideTableInfo.setPassword(MathUtil.getString(props.get(ImpalaSideTableInfo.PASSWORD_KEY.toLowerCase()))); - impalaSideTableInfo.setSchema(MathUtil.getString(props.get(ImpalaSideTableInfo.SCHEMA_KEY.toLowerCase()))); - impalaSideTableInfo.setDriverName("com.cloudera.impala.jdbc41.Driver"); - impalaSideTableInfo.setFastCheck(MathUtil.getBoolean(props.getOrDefault(RdbSideTableInfo.FAST_CHECK.toLowerCase(), true))); - impalaSideTableInfo.setCheckProperties(); - - if (MathUtil.getLongVal(props.get(impalaSideTableInfo.ERROR_LIMIT.toLowerCase())) != null) { - impalaSideTableInfo.setErrorLimit(MathUtil.getLongVal(props.get(impalaSideTableInfo.ERROR_LIMIT.toLowerCase()))); - } - - //set authmech params - Integer authMech = MathUtil.getIntegerVal(props.get(ImpalaSideTableInfo.AUTHMECH_KEY.toLowerCase())); - - authMech = authMech == null? 0 : authMech; - impalaSideTableInfo.setAuthMech(authMech); - List authMechs = Arrays.asList(0, 1, 2, 3); - - if (!authMechs.contains(authMech)){ - throw new IllegalArgumentException("The value of authMech is illegal, Please select 0, 1, 2, 3"); - } else if (authMech == 1) { - impalaSideTableInfo.setPrincipal(MathUtil.getString(props.get(ImpalaSideTableInfo.PRINCIPAL_KEY.toLowerCase()))); - impalaSideTableInfo.setKeyTabFilePath(MathUtil.getString(props.get(ImpalaSideTableInfo.KEYTABFILEPATH_KEY.toLowerCase()))); - impalaSideTableInfo.setKrb5FilePath(MathUtil.getString(props.get(ImpalaSideTableInfo.KRB5FILEPATH_KEY.toLowerCase()))); - String krbRealm = MathUtil.getString(props.get(ImpalaSideTableInfo.KRBREALM_KEY.toLowerCase())); - krbRealm = krbRealm == null? "HADOOP.COM" : krbRealm; - impalaSideTableInfo.setKrbRealm(krbRealm); - impalaSideTableInfo.setKrbHostFQDN(MathUtil.getString(props.get(ImpalaSideTableInfo.KRBHOSTFQDN_KEY.toLowerCase()))); - impalaSideTableInfo.setKrbServiceName(MathUtil.getString(props.get(ImpalaSideTableInfo.KRBSERVICENAME_KEY.toLowerCase()))); - } else if (authMech == 2 ) { - impalaSideTableInfo.setUserName(MathUtil.getString(props.get(ImpalaSideTableInfo.USER_NAME_KEY.toLowerCase()))); - } else if (authMech == 3) { - impalaSideTableInfo.setUserName(MathUtil.getString(props.get(ImpalaSideTableInfo.USER_NAME_KEY.toLowerCase()))); - impalaSideTableInfo.setPassword(MathUtil.getString(props.get(ImpalaSideTableInfo.PASSWORD_KEY.toLowerCase()))); - } - - //set partition params - String enablePartitionStr = (String) props.get(ImpalaSideTableInfo.ENABLEPARTITION_KEY.toLowerCase()); - boolean enablePartition = MathUtil.getBoolean(enablePartitionStr == null? "false":enablePartitionStr); - impalaSideTableInfo.setEnablePartition(enablePartition); - if (enablePartition) { - String partitionfieldsStr = MathUtil.getString(props.get(ImpalaSideTableInfo.PARTITIONFIELDS_KEY.toLowerCase())); - impalaSideTableInfo.setPartitionfields(StringUtils.split(partitionfieldsStr, ",")); - String partitionfieldTypesStr = MathUtil.getString(props.get(ImpalaSideTableInfo.PARTITIONFIELDTYPES_KEY.toLowerCase())); - impalaSideTableInfo.setPartitionFieldTypes(StringUtils.split(partitionfieldTypesStr, ",")); - String partitionfieldValuesStr = MathUtil.getString(props.get(ImpalaSideTableInfo.PARTITIONVALUES_KEY.toLowerCase())); - impalaSideTableInfo.setPartitionValues(setPartitionFieldValues(partitionfieldValuesStr)); - } - - impalaSideTableInfo.check(); - return impalaSideTableInfo; - } - - public Map setPartitionFieldValues(String partitionfieldValuesStr){ - Map fieldValues; - try { - ObjectMapper objectMapper = new ObjectMapper(); - fieldValues = objectMapper.readValue(partitionfieldValuesStr, Map.class); - for (String key : fieldValues.keySet()) { - List value = (List)fieldValues.get(key); - fieldValues.put(key, value); - } - return fieldValues; - } catch (Exception e) { - LOG.error("",e); - throw new RuntimeException(e); - } - } - - @Override - public Class dbTypeConvertToJavaType(String fieldType) { - switch (fieldType.toLowerCase()) { - case "boolean": - return Boolean.class; - case "char": - return Character.class; - case "double": - return Double.class; - case "float": - return Float.class; - case "tinyint": - return Byte.class; - case "smallint": - return Short.class; - case "int": - return Integer.class; - case "bigint": - return Long.class; - case "decimal": - return BigDecimal.class; - case "string": - case "varchar": - return String.class; - case "timestamp": - return Timestamp.class; - default: - break; - } - - throw new RuntimeException("不支持 " + fieldType + " 类型"); - } -} diff --git a/impala/impala-side/impala-side-core/src/main/java/com/dtstack/flink/sql/side/impala/table/ImpalaSideTableInfo.java b/impala/impala-side/impala-side-core/src/main/java/com/dtstack/flink/sql/side/impala/table/ImpalaSideTableInfo.java deleted file mode 100644 index 504ab520e..000000000 --- a/impala/impala-side/impala-side-core/src/main/java/com/dtstack/flink/sql/side/impala/table/ImpalaSideTableInfo.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.impala.table; - -import com.dtstack.flink.sql.core.rdb.JdbcResourceCheck; -import com.dtstack.flink.sql.side.rdb.table.RdbSideTableInfo; -import com.google.common.base.Preconditions; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Date: 2019/11/13 - * Company: www.dtstack.com - * @author xiuzhu - */ - -public class ImpalaSideTableInfo extends RdbSideTableInfo { - - public static final String AUTHMECH_KEY = "authMech"; - - public static final String KRB5FILEPATH_KEY = "krb5FilePath"; - - public static final String PRINCIPAL_KEY = "principal"; - - public static final String KEYTABFILEPATH_KEY = "keyTabFilePath"; - - public static final String KRBREALM_KEY = "krbRealm"; - - public static final String KRBHOSTFQDN_KEY = "krbHostFQDN"; - - public static final String KRBSERVICENAME_KEY = "krbServiceName"; - - public static final String ENABLEPARTITION_KEY = "enablePartition"; - - public static final String PARTITIONFIELDS_KEY = "partitionfields"; - - public static final String PARTITIONFIELDTYPES_KEY = "partitionFieldTypes"; - - public static final String PARTITIONVALUES_KEY = "partitionValues"; - - - private Integer authMech; - - private String krb5FilePath; - - private String principal; - - private String keyTabFilePath; - - private String krbRealm; - - private String krbHostFQDN; - - private String krbServiceName; - - private boolean enablePartition; - - private String[] partitionfields; - - private String[] partitionFieldTypes; - - private Map partitionValues = new HashMap<>(); - - - public ImpalaSideTableInfo() { - } - - public Integer getAuthMech() { - return authMech; - } - - public void setAuthMech(Integer authMech) { - this.authMech = authMech; - } - - public String getKrb5FilePath() { - return krb5FilePath; - } - - public void setKrb5FilePath(String krb5FilePath) { - this.krb5FilePath = krb5FilePath; - } - - public String getPrincipal() { - return principal; - } - - public void setPrincipal(String principal) { - this.principal = principal; - } - - public String getKeyTabFilePath() { - return keyTabFilePath; - } - - public void setKeyTabFilePath(String keyTabFilePath) { - this.keyTabFilePath = keyTabFilePath; - } - - public String getKrbRealm() { - return krbRealm; - } - - public void setKrbRealm(String krbRealm) { - this.krbRealm = krbRealm; - } - - public String getKrbHostFQDN() { - return krbHostFQDN; - } - - public void setKrbHostFQDN(String krbHostFQDN) { - this.krbHostFQDN = krbHostFQDN; - } - - public String getKrbServiceName() { - return krbServiceName; - } - - public void setKrbServiceName(String krbServiceName) { - this.krbServiceName = krbServiceName; - } - - public boolean isEnablePartition() { - return enablePartition; - } - - public void setEnablePartition(boolean enablePartition) { - this.enablePartition = enablePartition; - } - - public String[] getPartitionfields() { - return partitionfields; - } - - public void setPartitionfields(String[] partitionfields) { - this.partitionfields = partitionfields; - } - - public String[] getPartitionFieldTypes() { - return partitionFieldTypes; - } - - public void setPartitionFieldTypes(String[] partitionFieldTypes) { - this.partitionFieldTypes = partitionFieldTypes; - } - - public Map getPartitionValues() { - return partitionValues; - } - - public void setPartitionValues(Map partitionValues) { - this.partitionValues = partitionValues; - } - - @Override - public boolean check() { - Preconditions.checkNotNull(this.getUrl(), "impala of URL is required"); - Preconditions.checkNotNull(this.getTableName(), "impala of tableName is required"); - if (this.authMech == 1) { - Preconditions.checkNotNull(this.getKrb5FilePath(), "impala field of krb5FilePath is required"); - Preconditions.checkNotNull(this.getPrincipal(), "impala field of principal is required"); - Preconditions.checkNotNull(this.getKeyTabFilePath(), "impala field of keyTabFilePath is required"); - Preconditions.checkNotNull(this.getKrbHostFQDN(), "impala field of krbHostFQDN is required"); - Preconditions.checkNotNull(this.getKrbServiceName(), "impala field of krbServiceName is required"); - } else if (this.authMech == 2) { - Preconditions.checkNotNull(this.getUserName(), "impala field of userName is required"); - }else if (this.authMech == 3) { - Preconditions.checkNotNull(this.getUserName(), "impala field of userName is required"); - Preconditions.checkNotNull(this.getPassword(), "impala field of password is required"); - } - - if (enablePartition){ - Preconditions.checkNotNull(this.getPartitionfields(), "impala field of partitionfields is required"); - Preconditions.checkNotNull(this.getPartitionfields(), "impala field of partitionfields is required"); - Preconditions.checkNotNull(this.getPartitionfields(), "impala field of partitionfields is required"); - } - - if (getFastCheck()) { - JdbcResourceCheck.getInstance().checkResourceStatus(this.getCheckProperties()); - } - - return true; - } -} diff --git a/impala/impala-side/impala-side-core/src/test/java/com/dtstack/flink/sql/side/impala/table/ImpalaSideParserTest.java b/impala/impala-side/impala-side-core/src/test/java/com/dtstack/flink/sql/side/impala/table/ImpalaSideParserTest.java deleted file mode 100644 index aeae0f8e5..000000000 --- a/impala/impala-side/impala-side-core/src/test/java/com/dtstack/flink/sql/side/impala/table/ImpalaSideParserTest.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.dtstack.flink.sql.side.impala.table; - -import com.dtstack.flink.sql.table.AbstractTableInfo; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import java.sql.Timestamp; -import java.util.HashMap; -import java.util.Map; - -public class ImpalaSideParserTest { - - ImpalaSideParser sinkParser; - - @Before - public void setUp() { - sinkParser = new ImpalaSideParser(); - } - -// @Test - public void testGetTableInfo() { - - final String tableName = "table_foo"; - final String fieldsInfo = "id INT, name VARCHAR, PRIMARY KEY (id)"; - - Map props = new HashMap(); - props.put("authmech", 3); - - props.put("enablepartition", "true"); - props.put("partitionvalues", "{\"name\":[\"tom\",\"jeck\"]}"); - props.put("partitionfields", "name"); - props.put("partitionfieldtypes", "varchar"); - - props.put("url", "jdbc:hive2://myhost.example.com:21050/;principal=impala/myhost.example.com@H2.EXAMPLE.COM"); - props.put("tablename", "table_foo"); - props.put("username", "foo"); - props.put("password", "foo"); - - AbstractTableInfo tableInfo= sinkParser.getTableInfo(tableName, fieldsInfo, props); - props.put("authmech", 2); - sinkParser.getTableInfo(tableName, fieldsInfo, props); - props.put("authmech", 1); - props.put("principal", ""); - props.put("keytabfilepath", "/foo/bar.keytab"); - props.put("krb5filepath", "krb5.conf"); - props.put("krbhostfqdn", ""); - props.put("krbservicename", ""); - sinkParser.getTableInfo(tableName, fieldsInfo, props); - props.put("authmech", -1); - try { - sinkParser.getTableInfo(tableName, fieldsInfo, props); - } catch (IllegalArgumentException e) { } - - -// final String NORMAL_TYPE = "mysql"; -// final String table_type = tableInfo.getType(); -// Assert.assertTrue(NORMAL_TYPE.equals(table_type)); - } - - @Test - public void testSetPartitionFieldValues() { - try { - sinkParser.setPartitionFieldValues("TEST"); - } catch (Exception e) { } - Map map = sinkParser.setPartitionFieldValues("{\"id\": [1, 2]}"); - Map normalMap = Maps.newHashMap(); - - normalMap.put("id", Lists.newArrayList(1, 2)); - Assert.assertTrue(normalMap.equals(map)); - } - - @Test - public void testDbTypeConvertToJavaType() { - String ERR_TYPE = "TEST_foo"; - try { - sinkParser.dbTypeConvertToJavaType(ERR_TYPE); - } catch (Exception e) { - String normal = "不支持 " + ERR_TYPE +" 类型"; - Assert.assertTrue(e.getMessage().equals(normal)); - } - Class clazz = sinkParser.dbTypeConvertToJavaType("timestamp"); - Assert.assertTrue(Timestamp.class.equals(clazz)); - } - -} \ No newline at end of file diff --git a/impala/impala-side/pom.xml b/impala/impala-side/pom.xml deleted file mode 100644 index 461539844..000000000 --- a/impala/impala-side/pom.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - sql.impala - com.dtstack.flink - 1.0-SNAPSHOT - ../pom.xml - - 4.0.0 - - sql.side.impala - pom - impala-side - - impala-side-core - impala-all-side - impala-async-side - - - - 1.0-SNAPSHOT - - - - - com.dtstack.flink - sql.side.rdb - ${rdb.side.version} - - - - - - com.dtstack.flink - sql.side.rdb - ${rdb.side.version} - test-jar - test - - - - - - \ No newline at end of file diff --git a/impala/impala-sink/pom.xml b/impala/impala-sink/pom.xml deleted file mode 100644 index 3e376b078..000000000 --- a/impala/impala-sink/pom.xml +++ /dev/null @@ -1,92 +0,0 @@ - - - - sql.impala - com.dtstack.flink - 1.0-SNAPSHOT - ../pom.xml - - 4.0.0 - - sql.sink.impala - jar - impala-sink - http://maven.apache.org - - - 1.0-SNAPSHOT - - - - - com.dtstack.flink - sql.sink.rdb - ${sql.sink.rdb.version} - - - - - - - org.apache.maven.plugins - maven-shade-plugin - 1.4 - - - package - - shade - - - - - - - - - - *:* - - META-INF/*.SF - META-INF/*.DSA - META-INF/*.RSA - - - - - - - - - - maven-antrun-plugin - 1.2 - - - copy-resources - - package - - run - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/impala/impala-sink/src/main/java/com/dtstack/flink/sql/sink/impala/EAuthMech.java b/impala/impala-sink/src/main/java/com/dtstack/flink/sql/sink/impala/EAuthMech.java deleted file mode 100644 index 3753a54bd..000000000 --- a/impala/impala-sink/src/main/java/com/dtstack/flink/sql/sink/impala/EAuthMech.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.impala; - -/** - * impala kdnc AuthMech params - * Date: 2020/2/18 - * Company: www.dtstack.com - * @author maqi - */ -public enum EAuthMech { - // 0 for No Authentication - NoAuthentication(0), - // 1 for Kerberos - Kerberos(1), - // 2 for User Name - UserName(2), - // 3 for User Name and Password - NameANDPassword(3); - - private int type; - - EAuthMech(int type) { - this.type = type; - } - - public int getType() { - return this.type; - } -} diff --git a/impala/impala-sink/src/main/java/com/dtstack/flink/sql/sink/impala/ImpalaOutputFormat.java b/impala/impala-sink/src/main/java/com/dtstack/flink/sql/sink/impala/ImpalaOutputFormat.java deleted file mode 100644 index 12960e404..000000000 --- a/impala/impala-sink/src/main/java/com/dtstack/flink/sql/sink/impala/ImpalaOutputFormat.java +++ /dev/null @@ -1,752 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.impala; - -import com.dtstack.flink.sql.classloader.ClassLoaderManager; -import com.dtstack.flink.sql.core.rdb.util.JdbcConnectionUtil; -import com.dtstack.flink.sql.exception.ExceptionTrace; -import com.dtstack.flink.sql.factory.DTThreadFactory; -import com.dtstack.flink.sql.outputformat.AbstractDtRichOutputFormat; -import com.dtstack.flink.sql.sink.rdb.JDBCTypeConvertUtils; -import com.dtstack.flink.sql.table.AbstractTableInfo; -import com.dtstack.flink.sql.util.DtStringUtil; -import com.dtstack.flink.sql.util.KrbUtils; -import com.google.common.collect.Maps; -import org.apache.commons.collections.CollectionUtils; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.configuration.Configuration; -import org.apache.flink.types.Row; -import org.apache.hadoop.security.UserGroupInformation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.security.PrivilegedExceptionAction; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.PreparedStatement; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; - -import static com.dtstack.flink.sql.sink.rdb.JDBCTypeConvertUtils.setRecordToStatement; -import static org.apache.flink.util.Preconditions.checkNotNull; - -/** - * Date: 2020/10/14 - * Company: www.dtstack.com - * - * @author tiezhu - */ -public class ImpalaOutputFormat extends AbstractDtRichOutputFormat> { - - private static final Logger LOG = LoggerFactory.getLogger(ImpalaOutputFormat.class); - - private static final long serialVersionUID = 1L; - - // ${field} - private static final Pattern STATIC_PARTITION_PATTERN = Pattern.compile("\\$\\{([^}]*)}"); - //specific type which values need to be quoted - private static final String[] NEED_QUOTE_TYPE = {"string", "timestamp", "varchar"}; - - private static final Integer DEFAULT_CONN_TIME_OUT = 60; - private static final int RECEIVE_DATA_PRINT_FREQUENCY = 1000; - private static final int DIRTY_DATA_PRINT_FREQUENCY = 1000; - - private static final String KUDU_TYPE = "kudu"; - private static final String UPDATE_MODE = "update"; - private static final String PARTITION_CONSTANT = "PARTITION"; - private static final String DRIVER_NAME = "com.cloudera.impala.jdbc41.Driver"; - - private static final String VALUES_CONDITION = "${valuesCondition}"; - private static final String PARTITION_CONDITION = "${partitionCondition}"; - private static final String TABLE_FIELDS_CONDITION = "${tableFieldsCondition}"; - private static final String NO_PARTITION = "noPartition"; - // partition field of static partition which matched by ${field} - private final List staticPartitionFields = new ArrayList<>(); - public List fieldNames; - public List fieldTypes; - public List fieldExtraInfoList; - protected transient Connection connection; - protected transient Statement statement; - protected transient PreparedStatement updateStatement; - protected String keytabPath; - protected String krb5confPath; - protected String principal; - protected Integer authMech; - protected String dbUrl; - protected String userName; - protected String password; - protected int batchSize = 100; - protected long batchWaitInterval = 60 * 1000L; - protected String tableName; - protected List primaryKeys; - protected String partitionFields; - protected Boolean enablePartition; - protected String schema; - protected String storeType; - protected String updateMode; - private transient volatile boolean closed = false; - private int batchCount = 0; - // |------------------------------------------------| - // | partitionCondition |Array of valueCondition| - // |------------------------------------------------| - // | ptOne, ptTwo, ptThree | [(v1, v2, v3, v4, v5)]| DP - // |------------------------------------------------| - // | ptOne = v1, ptTwo = v2 | [(v3, v4, v5)] | SP - // |------------------------------------------------| - // | ptOne, ptTwo = v2 | [(v1, v3, v4, v5)] | DP and SP - // |------------------------------------------------| - // | noPartition | [(v1, v2, v3, v4, v5)]| kudu or disablePartition - // |------------------------------------------------| - private transient Map> rowDataMap; - // valueFieldsName -> 重组之后的fieldNames,为了重组row data字段值对应 - // 需要对partition字段做特殊处理,比如原来的字段顺序为(age, name, id),但是因为partition,写入的SQL为 - // INSERT INTO tableName(name, id) PARTITION(age) VALUES(?, ?, ?) - // 那么实际executeSql设置字段的顺序应该为(name, id, age),同时,字段对应的type顺序也需要重组 - private List valueFieldNames; - private transient AbstractDtRichOutputFormat metricOutputFormat; - private List rows; - - private transient ScheduledExecutorService scheduler; - private transient ScheduledFuture scheduledFuture; - - public static Builder getImpalaBuilder() { - return new Builder(); - } - - @Override - public void configure(Configuration parameters) { - } - - @Override - public void open(int taskNumber, int numTasks) throws IOException { - try { - rowDataMap = new HashMap<>(); - rows = new ArrayList<>(); - metricOutputFormat = this; - openConnect(); - initScheduledTask(batchWaitInterval); - init(); - initMetric(); - } catch (Exception e) { - throw new RuntimeException("impala output format open error!", e); - } - } - - private void init() throws SQLException { - if (Objects.nonNull(partitionFields)) { - // match ${field} from partitionFields - Matcher matcher = STATIC_PARTITION_PATTERN.matcher(partitionFields); - while (matcher.find()) { - LOG.info("find static partition field: {}", matcher.group(1)); - staticPartitionFields.add(matcher.group(1)); - } - } - - if (updateMode.equalsIgnoreCase(UPDATE_MODE)) { - if (!storeType.equalsIgnoreCase(KUDU_TYPE)) { - throw new IllegalArgumentException("update mode not support for non-kudu table!"); - } - updateStatement = connection.prepareStatement(buildUpdateSql(schema, tableName, fieldNames, primaryKeys)); - } else { - valueFieldNames = rebuildFieldNameListAndTypeList(fieldNames, staticPartitionFields, fieldTypes, partitionFields); - } - - } - - private void initScheduledTask(Long batchWaitInterval) { - try { - if (batchWaitInterval != 0) { - this.scheduler = new ScheduledThreadPoolExecutor(1, - new DTThreadFactory("impala-upsert-output-format")); - this.scheduledFuture = this.scheduler.scheduleWithFixedDelay(() -> { - synchronized (ImpalaOutputFormat.this) { - flush(); - } - }, batchWaitInterval, batchWaitInterval, TimeUnit.MILLISECONDS); - } - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - private void openConnect() throws IOException { - if (authMech == 1) { - UserGroupInformation ugi = KrbUtils.loginAndReturnUgi(principal, keytabPath, krb5confPath); - try { - ugi.doAs((PrivilegedExceptionAction) () -> { - openJdbc(); - return null; - }); - } catch (InterruptedException | IOException e) { - throw new IllegalArgumentException("connect impala error!", e); - } - } else { - openJdbc(); - } - } - - /** - * get jdbc connection - */ - private void openJdbc() { - ClassLoaderManager.forName(DRIVER_NAME, getClass().getClassLoader()); - try { - connection = DriverManager.getConnection(dbUrl, userName, password); - statement = connection.createStatement(); - connection.setAutoCommit(false); - } catch (SQLException sqlException) { - throw new RuntimeException("get impala jdbc connection failed!", sqlException); - } - } - - private synchronized void flush() { - try { - if (batchCount > 0) { - if (updateMode.equalsIgnoreCase(UPDATE_MODE)) { - executeUpdateBatch(); - } - if (!rowDataMap.isEmpty()) { - String templateSql = - "INSERT INTO tableName ${tableFieldsCondition} PARTITION ${partitionCondition} VALUES ${valuesCondition}"; - executeBatchSql( - templateSql, - schema, - tableName, - storeType, - enablePartition, - valueFieldNames, - partitionFields, - rowDataMap - ); - rowDataMap.clear(); - } - } - batchCount = 0; - } catch (Exception e) { - LOG.error("Writing records to impala jdbc failed.", e); - throw new RuntimeException("Writing records to impala jdbc failed.", e); - } - } - - /** - * execute batch update statement - * - * @throws SQLException throw sql exception - */ - private void executeUpdateBatch() throws SQLException { - try { - rows.forEach(row -> { - try { - JDBCTypeConvertUtils.setRecordToStatement( - updateStatement, - JDBCTypeConvertUtils.getSqlTypeFromFieldType(fieldTypes), - row, - primaryKeys.stream().mapToInt(fieldNames::indexOf).toArray() - ); - updateStatement.addBatch(); - } catch (Exception e) { - throw new RuntimeException("impala jdbc execute batch error!", e); - } - }); - updateStatement.executeBatch(); - connection.commit(); - rows.clear(); - } catch (Exception e) { - LOG.debug("impala jdbc execute batch error ", e); - JdbcConnectionUtil.rollBack(connection); - JdbcConnectionUtil.commit(connection); - updateStatement.clearBatch(); - executeUpdate(connection); - } - } - - public void executeUpdate(Connection connection) { - rows.forEach(row -> { - try { - setRecordToStatement(updateStatement, JDBCTypeConvertUtils.getSqlTypeFromFieldType(fieldTypes), row); - updateStatement.executeUpdate(); - JdbcConnectionUtil.commit(connection); - } catch (Exception e) { - JdbcConnectionUtil.rollBack(connection); - JdbcConnectionUtil.commit(connection); - if (metricOutputFormat.outDirtyRecords.getCount() % DIRTY_DATA_PRINT_FREQUENCY == 0 || LOG.isDebugEnabled()) { - LOG.error("record insert failed ,this row is {}", row.toString()); - LOG.error("", e); - } - metricOutputFormat.outDirtyRecords.inc(); - } - }); - rows.clear(); - } - - private void putRowIntoMap(Map> rowDataMap, Tuple2 rowData) { - Set keySet = rowDataMap.keySet(); - ArrayList tempRowArray; - if (keySet.contains(rowData.f0)) { - tempRowArray = rowDataMap.get(rowData.f0); - } else { - tempRowArray = new ArrayList<>(); - } - tempRowArray.add(rowData.f1); - rowDataMap.put(rowData.f0, tempRowArray); - } - - private List rebuildFieldNameListAndTypeList(List fieldNames, List staticPartitionFields, List fieldTypes, String partitionFields) { - if (partitionFields == null || partitionFields.isEmpty()) { - return fieldNames; - } - - List valueFields = new ArrayList<>(fieldNames); - - for (int i = valueFields.size() - 1; i >= 0; i--) { - if (staticPartitionFields.contains(fieldNames.get(i))) { - valueFields.remove(i); - fieldTypes.remove(i); - } - } - - for (int i = 0; i < valueFields.size(); i++) { - if (partitionFields.contains(fieldNames.get(i))) { - valueFields.add(valueFields.remove(i)); - fieldTypes.add(fieldTypes.remove(i)); - } - } - - return valueFields; - } - - @Override - public void writeRecord(Tuple2 record) throws IOException { - try { - if (!record.f0) { - return; - } - - if (outRecords.getCount() % RECEIVE_DATA_PRINT_FREQUENCY == 0 || LOG.isDebugEnabled()) { - LOG.info("Receive data : {}", record); - } - - if (updateMode.equalsIgnoreCase(UPDATE_MODE)) { - rows.add(Row.copy(record.f1)); - } else { - Map valueMap = Maps.newHashMap(); - Row row = Row.copy(record.f1); - - for (int i = 0; i < row.getArity(); i++) { - valueMap.put(fieldNames.get(i), row.getField(i)); - } - - Tuple2 rowTuple2 = new Tuple2<>(); - if (storeType.equalsIgnoreCase(KUDU_TYPE) || !enablePartition) { - rowTuple2.f0 = NO_PARTITION; - } else { - rowTuple2.f0 = buildPartitionCondition(valueMap, partitionFields, staticPartitionFields); - } - - // 根据字段名对 row data 重组, 比如,原始 row data : (1, xxx, 20) -> (id, name, age) - // 但是由于 partition,写入的field 顺序变成了 (name, id, age),则需要对 row data 重组变成 (xxx, 1, 20) - Row rowValue = new Row(fieldTypes.size()); - for (int i = 0; i < fieldTypes.size(); i++) { - rowValue.setField(i, valueMap.get(valueFieldNames.get(i))); - } - rowTuple2.f1 = buildValuesCondition(fieldTypes, rowValue); - putRowIntoMap(rowDataMap, rowTuple2); - } - - batchCount++; - - if (batchCount >= batchSize) { - flush(); - } - - // Receive data - outRecords.inc(); - } catch (Exception e) { - throw new IOException("Writing records to impala failed.", e); - } - } - - @Override - public void close() throws IOException { - if (closed) { - return; - } - // 将还未执行的SQL flush - if (batchCount > 0) { - flush(); - } - // cancel scheduled task - if (this.scheduledFuture != null) { - scheduledFuture.cancel(false); - this.scheduler.shutdown(); - } - // close connection - try { - if (connection != null && connection.isValid(DEFAULT_CONN_TIME_OUT)) { - connection.close(); - } - - if (statement != null && !statement.isClosed()) { - statement.close(); - } - - if (updateStatement != null && !updateStatement.isClosed()) { - updateStatement.close(); - } - } catch (SQLException e) { - throw new RuntimeException("impala connection close failed!", e); - } finally { - connection = null; - statement = null; - updateStatement = null; - } - closed = true; - } - - /** - * execute batch sql from row data map - * sql like 'insert into tableName(f1, f2, f3) ${partitionCondition} values(v1, v2, v3), (v4, v5, v6).... - * - * @param tempSql template sql - * @param storeType the store type of data - * @param enablePartition enable partition or not - * @param fieldNames field name list - * @param partitionFields partition fields - * @param rowDataMap row data map - */ - private void executeBatchSql(String tempSql, - String schema, - String tableName, - String storeType, - Boolean enablePartition, - List fieldNames, - String partitionFields, - Map> rowDataMap) { - StringBuilder partitionCondition = new StringBuilder(); - String tableFieldsCondition = buildTableFieldsCondition(fieldNames, partitionFields); - ArrayList rowData = new ArrayList<>(); - String tableNameInfo = Objects.isNull(schema) ? - tableName : quoteIdentifier(schema) + "." + tableName; - tempSql = tempSql.replace("tableName", tableNameInfo); - boolean isPartitioned = storeType.equalsIgnoreCase(KUDU_TYPE) || !enablePartition; - - try { - // kudu ${partitionCondition} is null - if (isPartitioned) { - tempSql = tempSql - .replace(PARTITION_CONDITION, partitionCondition.toString()) - .replace(PARTITION_CONSTANT, "") - .replace(TABLE_FIELDS_CONDITION, tableFieldsCondition); - rowData.addAll(rowDataMap.get(NO_PARTITION)); - String executeSql = tempSql.replace(VALUES_CONDITION, String.join(", ", rowData)); - statement.execute(executeSql); - rowData.clear(); - } else { - // partition sql - Set keySet = rowDataMap.keySet(); - for (String key : keySet) { - rowData.addAll(rowDataMap.get(key)); - partitionCondition.append(key); - tempSql = tempSql - .replace(PARTITION_CONDITION, partitionCondition.toString()) - .replace(TABLE_FIELDS_CONDITION, tableFieldsCondition); - String executeSql = tempSql - .replace(VALUES_CONDITION, String.join(", ", rowData)); - statement.execute(executeSql); - partitionCondition.delete(0, partitionCondition.length()); - } - } - } catch (Exception e) { - if (e instanceof SQLException) { - dealBatchSqlError(rowData, connection, statement, tempSql); - } else { - throw new RuntimeException("Insert into impala error!", e); - } - } finally { - rowData.clear(); - } - } - - /** - * 当批量写入失败时,把批量的sql拆解为单条sql提交,对于单条写入的sql记做脏数据 - * - * @param rowData 批量的values - * @param connection 当前数据库connect - * @param statement 当前statement - * @param templateSql 模版sql,例如insert into tableName(f1, f2, f3) [partition] values $valueCondition - */ - private void dealBatchSqlError(List rowData, - Connection connection, - Statement statement, - String templateSql) { - String errorMsg = "Insert into impala error. \nCause: [%s]\nRow: [%s]"; - JdbcConnectionUtil.rollBack(connection); - JdbcConnectionUtil.commit(connection); - for (String rowDatum : rowData) { - String executeSql = templateSql.replace(VALUES_CONDITION, rowDatum); - try { - statement.execute(executeSql); - JdbcConnectionUtil.commit(connection); - } catch (SQLException e) { - JdbcConnectionUtil.rollBack(connection); - JdbcConnectionUtil.commit(connection); - if (metricOutputFormat.outDirtyRecords.getCount() % DIRTY_DATA_PRINT_FREQUENCY == 0 || LOG.isDebugEnabled()) { - LOG.error( - String.format( - errorMsg, - ExceptionTrace.traceOriginalCause(e), - rowDatum) - ); - } - metricOutputFormat.outDirtyRecords.inc(); - } - } - } - - /** - * build partition condition with row data - * - * @param rowData row data - * @param partitionFields partition fields - * @param staticPartitionField static partition fields - * @return condition like '(ptOne, ptTwo=v2)' - */ - private String buildPartitionCondition(Map rowData, String partitionFields, List staticPartitionField) { - for (String key : staticPartitionField) { - StringBuilder sb = new StringBuilder(); - Object value = rowData.get(key); - sb.append(key).append("=").append(value); - partitionFields = partitionFields.replace("${" + key + "}", sb.toString()); - } - return "(" + partitionFields + ")"; - } - - /** - * build field condition according to field names - * replace ${tableFieldCondition} - * - * @param fieldNames the selected field names - * @param partitionFields the partition fields - * @return condition like '(id, name, age)' - */ - private String buildTableFieldsCondition(List fieldNames, String partitionFields) { - return "(" + fieldNames.stream() - .filter(f -> !partitionFields.contains(f)) - .map(this::quoteIdentifier) - .collect(Collectors.joining(", ")) + ")"; - } - - /** - * according to field types, build the values condition - * replace ${valuesCondition} - * - * @param fieldTypes field types - * @return condition like '(?, ?, cast('?' as string))' and '?' will be replaced with row data - */ - private String buildValuesCondition(List fieldTypes, Row row) { - String valuesCondition = fieldTypes.stream().map( - f -> { - for (String item : NEED_QUOTE_TYPE) { - if (f.toLowerCase().contains(item)) { - return String.format("cast('?' as %s)", f.toLowerCase()); - } - } - return "?"; - }).collect(Collectors.joining(", ")); - for (int i = 0; i < row.getArity(); i++) { - Object rowField = row.getField(i); - if (DtStringUtil.isEmptyOrNull(rowField)) { - valuesCondition = valuesCondition.replaceFirst("'\\?'", "null"); - } else { - valuesCondition = valuesCondition.replaceFirst("\\?", Matcher.quoteReplacement(rowField.toString())); - } - } - return "(" + valuesCondition + ")"; - } - - /** - * impala update mode SQL - * - * @return UPDATE tableName SET setCondition WHERE whereCondition - */ - private String buildUpdateSql(String schema, String tableName, List fieldNames, List primaryKeys) { - //跳过primary key字段 - String setClause = fieldNames.stream() - .filter(f -> !CollectionUtils.isNotEmpty(primaryKeys) || !primaryKeys.contains(f)) - .map(f -> quoteIdentifier(f) + "=?") - .collect(Collectors.joining(", ")); - - String conditionClause = primaryKeys.stream() - .map(f -> quoteIdentifier(f) + "=?") - .collect(Collectors.joining(" AND ")); - - return "UPDATE " + (Objects.isNull(schema) ? "" : quoteIdentifier(schema) + ".") - + quoteIdentifier(tableName) + " SET " + setClause + " WHERE " + conditionClause; - } - - private String quoteIdentifier(String identifier) { - return "`" + identifier + "`"; - } - - public static class Builder { - private final ImpalaOutputFormat format = new ImpalaOutputFormat(); - - public Builder setDbUrl(String dbUrl) { - format.dbUrl = dbUrl; - return this; - } - - public Builder setUserName(String userName) { - format.userName = userName; - return this; - } - - public Builder setPassword(String password) { - format.password = password; - return this; - } - - public Builder setBatchSize(Integer batchSize) { - format.batchSize = batchSize; - return this; - } - - public Builder setBatchWaitInterval(Long batchWaitInterval) { - format.batchWaitInterval = batchWaitInterval; - return this; - } - - public Builder setTableName(String tableName) { - format.tableName = tableName; - return this; - } - - public Builder setPartitionFields(String partitionFields) { - format.partitionFields = Objects.isNull(partitionFields) ? - "" : partitionFields; - return this; - } - - public Builder setPrimaryKeys(List primaryKeys) { - format.primaryKeys = primaryKeys; - return this; - } - - public Builder setSchema(String schema) { - format.schema = schema; - return this; - } - - public Builder setEnablePartition(Boolean enablePartition) { - format.enablePartition = enablePartition; - return this; - } - - public Builder setUpdateMode(String updateMode) { - format.updateMode = updateMode; - return this; - } - - public Builder setFieldList(List fieldList) { - format.fieldNames = fieldList; - return this; - } - - public Builder setFieldTypeList(List fieldTypeList) { - format.fieldTypes = fieldTypeList; - return this; - } - - public Builder setStoreType(String storeType) { - format.storeType = storeType; - return this; - } - - public Builder setFieldExtraInfoList(List fieldExtraInfoList) { - format.fieldExtraInfoList = fieldExtraInfoList; - return this; - } - - public Builder setKeyTabPath(String keyTabPath) { - format.keytabPath = keyTabPath; - return this; - } - - public Builder setKrb5ConfPath(String krb5ConfPath) { - format.krb5confPath = krb5ConfPath; - return this; - } - - public Builder setPrincipal(String principal) { - format.principal = principal; - return this; - } - - public Builder setAuthMech(Integer authMech) { - format.authMech = authMech; - return this; - } - - private boolean canHandle(String url) { - return url.startsWith("jdbc:impala:"); - } - - public ImpalaOutputFormat build() { - if (!canHandle(format.dbUrl)) { - throw new IllegalArgumentException("impala dbUrl is illegal, check url: " + format.dbUrl); - } - - if (format.authMech == EAuthMech.Kerberos.getType()) { - checkNotNull(format.krb5confPath, - "When kerberos authentication is enabled, krb5confPath is required!"); - checkNotNull(format.principal, - "When kerberos authentication is enabled, principal is required!"); - checkNotNull(format.keytabPath, - "When kerberos authentication is enabled, keytabPath is required!"); - } - - if (format.authMech == EAuthMech.UserName.getType()) { - checkNotNull(format.userName, "userName is required!"); - } - - if (format.authMech == EAuthMech.NameANDPassword.getType()) { - checkNotNull(format.userName, "userName is required!"); - checkNotNull(format.password, "password is required!"); - } - - checkNotNull(format.storeType, "storeType is required!"); - - return format; - } - } -} diff --git a/impala/impala-sink/src/main/java/com/dtstack/flink/sql/sink/impala/ImpalaSink.java b/impala/impala-sink/src/main/java/com/dtstack/flink/sql/sink/impala/ImpalaSink.java deleted file mode 100644 index 049fed887..000000000 --- a/impala/impala-sink/src/main/java/com/dtstack/flink/sql/sink/impala/ImpalaSink.java +++ /dev/null @@ -1,230 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.impala; - -import com.dtstack.flink.sql.sink.IStreamSinkGener; -import com.dtstack.flink.sql.sink.impala.table.ImpalaTableInfo; -import com.dtstack.flink.sql.table.AbstractTableInfo; -import com.dtstack.flink.sql.table.AbstractTargetTableInfo; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.api.java.typeutils.TupleTypeInfo; -import org.apache.flink.streaming.api.datastream.DataStream; -import org.apache.flink.streaming.api.datastream.DataStreamSink; -import org.apache.flink.streaming.api.functions.sink.OutputFormatSinkFunction; -import org.apache.flink.streaming.api.functions.sink.RichSinkFunction; -import org.apache.flink.table.sinks.RetractStreamTableSink; -import org.apache.flink.table.sinks.TableSink; -import org.apache.flink.types.Row; - -import java.util.List; -import java.util.Objects; - -/** - * Date: 2020/10/14 - * Company: www.dtstack.com - * - * @author tiezhu - */ -public class ImpalaSink implements RetractStreamTableSink, IStreamSinkGener { - - private static final String DEFAULT_STORE_TYPE = "kudu"; - - protected String[] fieldNames; - TypeInformation[] fieldTypes; - protected String dbUrl; - protected String userName; - protected String password; - protected Integer authMech; - - protected String keytabPath; - protected String krb5confPath; - protected String principal; - - protected int batchSize = 100; - protected long batchWaitInterval = 60 * 1000L; - protected String tableName; - protected String registerTabName; - protected String storeType; - - protected List primaryKeys; - private int parallelism = 1; - protected String schema; - protected String updateMode; - protected Boolean enablePartition; - public List fieldList; - public List fieldTypeList; - public List fieldExtraInfoList; - protected String partitionFields; - - public ImpalaSink() { - // do Nothing - } - - @Override - public ImpalaSink genStreamSink(AbstractTargetTableInfo targetTableInfo) { - ImpalaTableInfo impalaTableInfo = (ImpalaTableInfo) targetTableInfo; - this.dbUrl = getImpalaJdbcUrl(impalaTableInfo); - this.password = impalaTableInfo.getPassword(); - this.userName = impalaTableInfo.getUserName(); - this.authMech = impalaTableInfo.getAuthMech(); - - this.principal = impalaTableInfo.getPrincipal(); - this.keytabPath = impalaTableInfo.getKeyTabFilePath(); - this.krb5confPath = impalaTableInfo.getKrb5FilePath(); - - this.updateMode = Objects.isNull(impalaTableInfo.getUpdateMode()) ? - "append" : impalaTableInfo.getUpdateMode(); - - this.batchSize = Objects.isNull(impalaTableInfo.getBatchSize()) ? - batchSize : impalaTableInfo.getBatchSize(); - this.batchWaitInterval = Objects.isNull(impalaTableInfo.getBatchWaitInterval()) ? - batchWaitInterval : impalaTableInfo.getBatchWaitInterval(); - this.parallelism = Objects.isNull(impalaTableInfo.getParallelism()) ? - parallelism : impalaTableInfo.getParallelism(); - this.registerTabName = impalaTableInfo.getTableName(); - - this.fieldList = impalaTableInfo.getFieldList(); - this.fieldTypeList = impalaTableInfo.getFieldTypeList(); - this.fieldExtraInfoList = impalaTableInfo.getFieldExtraInfoList(); - this.tableName = impalaTableInfo.getTableName(); - this.schema = impalaTableInfo.getSchema(); - this.primaryKeys = impalaTableInfo.getPrimaryKeys(); - this.partitionFields = impalaTableInfo.getPartitionFields(); - - this.storeType = Objects.isNull(impalaTableInfo.getStoreType()) ? - DEFAULT_STORE_TYPE : impalaTableInfo.getStoreType(); - this.enablePartition = impalaTableInfo.isEnablePartition(); - - return this; - } - - /** - * build Impala Jdbc Url according to authMech - * - * @param impalaTableInfo impala table info - * @return jdbc url with auth mech info - */ - public String getImpalaJdbcUrl(ImpalaTableInfo impalaTableInfo) { - Integer authMech = impalaTableInfo.getAuthMech(); - String newUrl = impalaTableInfo.getUrl(); - StringBuilder urlBuffer = new StringBuilder(impalaTableInfo.getUrl()); - if (authMech == EAuthMech.NoAuthentication.getType()) { - return newUrl; - } else if (authMech == EAuthMech.Kerberos.getType()) { - String krbRealm = impalaTableInfo.getKrbRealm(); - String krbHostFqdn = impalaTableInfo.getKrbHostFQDN(); - String krbServiceName = impalaTableInfo.getKrbServiceName(); - urlBuffer.append(";" - .concat("AuthMech=1;") - .concat("KrbRealm=").concat(krbRealm).concat(";") - .concat("KrbHostFQDN=").concat(krbHostFqdn).concat(";") - .concat("KrbServiceName=").concat(krbServiceName).concat(";") - ); - newUrl = urlBuffer.toString(); - } else if (authMech == EAuthMech.UserName.getType()) { - urlBuffer.append(";" - .concat("AuthMech=3;") - .concat("UID=").concat(impalaTableInfo.getUserName()).concat(";") - .concat("PWD=;") - .concat("UseSasl=0") - ); - newUrl = urlBuffer.toString(); - } else if (authMech == EAuthMech.NameANDPassword.getType()) { - urlBuffer.append(";" - .concat("AuthMech=3;") - .concat("UID=").concat(impalaTableInfo.getUserName()).concat(";") - .concat("PWD=").concat(impalaTableInfo.getPassword()) - ); - newUrl = urlBuffer.toString(); - } else { - throw new IllegalArgumentException("The value of authMech is illegal, Please select 0, 1, 2, 3"); - } - return newUrl; - } - - private ImpalaOutputFormat buildImpalaOutputFormat() { - - return ImpalaOutputFormat.getImpalaBuilder() - .setDbUrl(dbUrl) - .setPassword(password) - .setUserName(userName) - .setSchema(schema) - .setTableName(tableName) - .setUpdateMode(updateMode) - .setBatchSize(batchSize) - .setBatchWaitInterval(batchWaitInterval) - .setPrimaryKeys(primaryKeys) - .setPartitionFields(partitionFields) - .setFieldList(fieldList) - .setFieldTypeList(fieldTypeList) - .setFieldExtraInfoList(fieldExtraInfoList) - .setStoreType(storeType) - .setEnablePartition(enablePartition) - .setUpdateMode(updateMode) - .setAuthMech(authMech) - .setKeyTabPath(keytabPath) - .setKrb5ConfPath(krb5confPath) - .setPrincipal(principal) - .build(); - } - - @Override - public void emitDataStream(DataStream> dataStream) { - consumeDataStream(dataStream); - } - - @Override - public DataStreamSink consumeDataStream(DataStream> dataStream) { - ImpalaOutputFormat outputFormat = buildImpalaOutputFormat(); - RichSinkFunction richSinkFunction = new OutputFormatSinkFunction(outputFormat); - DataStreamSink dataStreamSink = dataStream.addSink(richSinkFunction) - .setParallelism(parallelism) - .name(tableName); - return dataStreamSink; - } - - @Override - public TableSink> configure(String[] fieldNames, TypeInformation[] fieldTypes) { - this.fieldNames = fieldNames; - this.fieldTypes = fieldTypes; - return this; - } - - @Override - public TupleTypeInfo> getOutputType() { - return new TupleTypeInfo<>(org.apache.flink.table.api.Types.BOOLEAN(), getRecordType()); - } - - @Override - public TypeInformation getRecordType() { - return new RowTypeInfo(fieldTypes, fieldNames); - } - - @Override - public String[] getFieldNames() { - return fieldNames; - } - - @Override - public TypeInformation[] getFieldTypes() { - return fieldTypes; - } -} diff --git a/impala/impala-sink/src/main/java/com/dtstack/flink/sql/sink/impala/table/ImpalaSinkParser.java b/impala/impala-sink/src/main/java/com/dtstack/flink/sql/sink/impala/table/ImpalaSinkParser.java deleted file mode 100644 index e7e28d1bd..000000000 --- a/impala/impala-sink/src/main/java/com/dtstack/flink/sql/sink/impala/table/ImpalaSinkParser.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.impala.table; - -import com.dtstack.flink.sql.table.AbstractTableInfo; -import com.dtstack.flink.sql.table.AbstractTableParser; -import com.dtstack.flink.sql.util.MathUtil; - -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -/** - * Date: 2020/10/14 - * Company: www.dtstack.com - * - * @author tiezhu - */ -public class ImpalaSinkParser extends AbstractTableParser { - - private static final String PARALLELISM_KEY = "parallelism"; - - private static final String AUTH_MECH_KEY = "authMech"; - - private static final String KRB5FILEPATH_KEY = "krb5FilePath"; - - private static final String PRINCIPAL_KEY = "principal"; - - private static final String KEY_TAB_FILE_PATH_KEY = "keyTabFilePath"; - - private static final String KRB_REALM_KEY = "krbRealm"; - - private static final String KRB_HOST_FQDN_KEY = "krbHostFQDN"; - - private static final String KRB_SERVICE_NAME_KEY = "krbServiceName"; - - private static final String ENABLE_PARTITION_KEY = "enablePartition"; - - private static final String PARTITION_FIELDS_KEY = "partitionFields"; - - private static final String URL_KEY = "url"; - - private static final String TABLE_NAME_KEY = "tableName"; - - private static final String USER_NAME_KEY = "userName"; - - private static final String PASSWORD_KEY = "password"; - - private static final String BATCH_SIZE_KEY = "batchSize"; - - private static final String BATCH_WAIT_INTERVAL_KEY = "batchWaitInterval"; - - private static final String BUFFER_SIZE_KEY = "bufferSize"; - - private static final String FLUSH_INTERVAL_MS_KEY = "flushIntervalMs"; - - private static final String SCHEMA_KEY = "schema"; - - private static final String UPDATE_KEY = "updateMode"; - - private static final String KUDU_TYPE = "kudu"; - - private static final String DEFAULT_STORE_TYPE = "kudu"; - - private static final String STORE_TYPE_KEY = "storeType"; - - private static final String KRB_DEFAULT_REALM = "HADOOP.COM"; - - private static final String CURRENT_TYPE = "impala"; - - - @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) throws Exception { - ImpalaTableInfo impalaTableInfo = new ImpalaTableInfo(); - impalaTableInfo.setName(tableName); - parseFieldsInfo(fieldsInfo, impalaTableInfo); - - impalaTableInfo.setParallelism(MathUtil.getIntegerVal(props.get(PARALLELISM_KEY.toLowerCase()))); - impalaTableInfo.setUrl(MathUtil.getString(props.get(URL_KEY.toLowerCase()))); - impalaTableInfo.setTableName(MathUtil.getString(props.get(TABLE_NAME_KEY.toLowerCase()))); - impalaTableInfo.setBatchSize(MathUtil.getIntegerVal(props.get(BATCH_SIZE_KEY.toLowerCase()))); - impalaTableInfo.setBatchWaitInterval(MathUtil.getLongVal(props.get(BATCH_WAIT_INTERVAL_KEY.toLowerCase()))); - impalaTableInfo.setBufferSize(MathUtil.getString(props.get(BUFFER_SIZE_KEY.toLowerCase()))); - impalaTableInfo.setFlushIntervalMs(MathUtil.getString(props.get(FLUSH_INTERVAL_MS_KEY.toLowerCase()))); - impalaTableInfo.setSchema(MathUtil.getString(props.get(SCHEMA_KEY.toLowerCase()))); - impalaTableInfo.setUpdateMode(MathUtil.getString(props.get(UPDATE_KEY.toLowerCase()))); - impalaTableInfo.setDriverName("com.cloudera.impala.jdbc41.Driver"); - - Integer authMech = MathUtil.getIntegerVal(props.get(AUTH_MECH_KEY.toLowerCase())); - authMech = authMech == null ? 0 : authMech; - impalaTableInfo.setAuthMech(authMech); - List authMechs = Arrays.asList(0, 1, 2, 3); - - if (!authMechs.contains(authMech)) { - throw new IllegalArgumentException("The value of authMech is illegal, Please select 0, 1, 2, 3"); - } else if (authMech == 1) { - impalaTableInfo.setPrincipal(MathUtil.getString(props.get(PRINCIPAL_KEY.toLowerCase()))); - impalaTableInfo.setKeyTabFilePath(MathUtil.getString(props.get(KEY_TAB_FILE_PATH_KEY.toLowerCase()))); - impalaTableInfo.setKrb5FilePath(MathUtil.getString(props.get(KRB5FILEPATH_KEY.toLowerCase()))); - String krbRealm = MathUtil.getString(props.get(KRB_REALM_KEY.toLowerCase())); - krbRealm = krbRealm == null ? KRB_DEFAULT_REALM : krbRealm; - impalaTableInfo.setKrbRealm(krbRealm); - impalaTableInfo.setKrbHostFQDN(MathUtil.getString(props.get(KRB_HOST_FQDN_KEY.toLowerCase()))); - impalaTableInfo.setKrbServiceName(MathUtil.getString(props.get(KRB_SERVICE_NAME_KEY.toLowerCase()))); - } else if (authMech == 2) { - impalaTableInfo.setUserName(MathUtil.getString(props.get(USER_NAME_KEY.toLowerCase()))); - } else if (authMech == 3) { - impalaTableInfo.setUserName(MathUtil.getString(props.get(USER_NAME_KEY.toLowerCase()))); - impalaTableInfo.setPassword(MathUtil.getString(props.get(PASSWORD_KEY.toLowerCase()))); - } - - String storeType = MathUtil.getString(props.get(STORE_TYPE_KEY.toLowerCase())); - impalaTableInfo.setStoreType(Objects.isNull(storeType) ? DEFAULT_STORE_TYPE : storeType); - - String enablePartitionStr = (String) props.get(ENABLE_PARTITION_KEY.toLowerCase()); - boolean enablePartition = MathUtil.getBoolean(enablePartitionStr == null ? "false" : enablePartitionStr); - impalaTableInfo.setEnablePartition(enablePartition); - - if (!impalaTableInfo.getStoreType().equalsIgnoreCase(KUDU_TYPE) && enablePartition) { - String partitionFields = MathUtil.getString(props.get(PARTITION_FIELDS_KEY.toLowerCase())); - impalaTableInfo.setPartitionFields(partitionFields); - } - - impalaTableInfo.setType(CURRENT_TYPE); - - impalaTableInfo.check(); - return impalaTableInfo; - } -} diff --git a/impala/impala-sink/src/main/java/com/dtstack/flink/sql/sink/impala/table/ImpalaTableInfo.java b/impala/impala-sink/src/main/java/com/dtstack/flink/sql/sink/impala/table/ImpalaTableInfo.java deleted file mode 100644 index 75dfd1722..000000000 --- a/impala/impala-sink/src/main/java/com/dtstack/flink/sql/sink/impala/table/ImpalaTableInfo.java +++ /dev/null @@ -1,279 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.impala.table; - -import com.dtstack.flink.sql.enums.EUpdateMode; -import com.dtstack.flink.sql.table.AbstractTargetTableInfo; -import com.google.common.base.Preconditions; -import org.apache.commons.lang3.StringUtils; - -import java.util.Objects; - -/** - * Date: 2020/10/14 - * Company: www.dtstack.com - * - * @author tiezhu - */ -public class ImpalaTableInfo extends AbstractTargetTableInfo { - - private static final int MAX_BATCH_SIZE = 10000; - - private String url; - - private String tableName; - - private String userName; - - private String password; - - private Integer batchSize; - - private Long batchWaitInterval; - - private String bufferSize; - - private String flushIntervalMs; - - private String schema; - - private boolean allReplace; - - private String updateMode; - - private Integer authMech; - - private String krb5FilePath; - - private String principal; - - private String keyTabFilePath; - - private String krbRealm; - - private String krbHostFQDN; - - private String krbServiceName; - - private boolean enablePartition = false; - - private String partitionFields; - - private String storeType; - - private String driverName; - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - public String getTableName() { - return tableName; - } - - public void setTableName(String tableName) { - this.tableName = tableName; - } - - public String getUserName() { - return userName; - } - - public void setUserName(String userName) { - this.userName = userName; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public Integer getBatchSize() { - return batchSize; - } - - public void setBatchSize(Integer batchSize) { - this.batchSize = batchSize; - } - - public Long getBatchWaitInterval() { - return batchWaitInterval; - } - - public void setBatchWaitInterval(Long batchWaitInterval) { - this.batchWaitInterval = batchWaitInterval; - } - - public String getBufferSize() { - return bufferSize; - } - - public void setBufferSize(String bufferSize) { - this.bufferSize = bufferSize; - } - - public String getFlushIntervalMs() { - return flushIntervalMs; - } - - public void setFlushIntervalMs(String flushIntervalMs) { - this.flushIntervalMs = flushIntervalMs; - } - - public String getSchema() { - return schema; - } - - public void setSchema(String schema) { - this.schema = schema; - } - - public String getUpdateMode() { - return updateMode; - } - - public void setUpdateMode(String updateMode) { - this.updateMode = updateMode; - } - - public Integer getAuthMech() { - return authMech; - } - - public void setAuthMech(Integer authMech) { - this.authMech = authMech; - } - - public String getKrb5FilePath() { - return krb5FilePath; - } - - public void setKrb5FilePath(String krb5FilePath) { - this.krb5FilePath = krb5FilePath; - } - - public String getPrincipal() { - return principal; - } - - public void setPrincipal(String principal) { - this.principal = principal; - } - - public String getKeyTabFilePath() { - return keyTabFilePath; - } - - public void setKeyTabFilePath(String keyTabFilePath) { - this.keyTabFilePath = keyTabFilePath; - } - - public String getKrbRealm() { - return krbRealm; - } - - public void setKrbRealm(String krbRealm) { - this.krbRealm = krbRealm; - } - - public String getKrbHostFQDN() { - return krbHostFQDN; - } - - public void setKrbHostFQDN(String krbHostFQDN) { - this.krbHostFQDN = krbHostFQDN; - } - - public String getKrbServiceName() { - return krbServiceName; - } - - public void setKrbServiceName(String krbServiceName) { - this.krbServiceName = krbServiceName; - } - - public boolean isEnablePartition() { - return enablePartition; - } - - public void setEnablePartition(boolean enablePartition) { - this.enablePartition = enablePartition; - } - - public String getPartitionFields() { - return partitionFields; - } - - public void setPartitionFields(String partitionFields) { - this.partitionFields = partitionFields; - } - - public String getStoreType() { - return storeType; - } - - public void setStoreType(String storeType) { - this.storeType = storeType; - } - - public String getDriverName() { - return driverName; - } - - public void setDriverName(String driverName) { - this.driverName = driverName; - } - - @Override - public String getType() { - return super.getType().toLowerCase(); - } - - @Override - public boolean check() { - Preconditions.checkNotNull(url, "impala field of URL is required"); - Preconditions.checkNotNull(tableName, "impala field of tableName is required"); - - if (Objects.nonNull(batchSize)) { - Preconditions.checkArgument(batchSize <= MAX_BATCH_SIZE, "batchSize must be less than " + MAX_BATCH_SIZE); - } - - if (StringUtils.equalsIgnoreCase(updateMode, EUpdateMode.UPSERT.name())) { - Preconditions.checkArgument(Objects.nonNull(getPrimaryKeys()) && getPrimaryKeys().size() > 0, "updateMode mode primary is required"); - } - - if (Objects.nonNull(getPrimaryKeys())) { - getPrimaryKeys().forEach(pk -> { - Preconditions.checkArgument(getFieldList().contains(pk), "primary key " + pk + " not found in sink table field"); - }); - } - - - Preconditions.checkArgument(getFieldList().size() == getFieldExtraInfoList().size(), - "fields and fieldExtraInfoList attributes must be the same length"); - return true; - } -} diff --git a/impala/impala-sink/src/test/java/com/dtstack/flink/sql/sink/impala/ImpalaSinkTest.java b/impala/impala-sink/src/test/java/com/dtstack/flink/sql/sink/impala/ImpalaSinkTest.java deleted file mode 100644 index ec082bc71..000000000 --- a/impala/impala-sink/src/test/java/com/dtstack/flink/sql/sink/impala/ImpalaSinkTest.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.dtstack.flink.sql.sink.impala; - -import com.dtstack.flink.sql.sink.impala.table.ImpalaTableInfo; -import com.dtstack.flink.sql.sink.rdb.dialect.JDBCDialect; -import com.dtstack.flink.sql.sink.rdb.format.JDBCUpsertOutputFormat; -import org.junit.Before; -import org.junit.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.powermock.api.support.membermodification.MemberModifier; -import org.powermock.reflect.Whitebox; - -import java.util.Optional; - -import static org.mockito.Mockito.when; - -public class ImpalaSinkTest { - - @Mock - JDBCDialect jdbcDialect; - - @InjectMocks - ImpalaSink sink = new ImpalaSink();; - - ImpalaTableInfo tableInfo = new ImpalaTableInfo(); - @Before - public void setUp () { - MockitoAnnotations.initMocks(this); - tableInfo.setAuthMech(EAuthMech.NoAuthentication.ordinal()); - Whitebox.setInternalState(sink, "impalaTableInfo", tableInfo); - } - -} \ No newline at end of file diff --git a/impala/impala-sink/src/test/java/com/dtstack/flink/sql/sink/impala/table/ImpalaSinkParserTest.java b/impala/impala-sink/src/test/java/com/dtstack/flink/sql/sink/impala/table/ImpalaSinkParserTest.java deleted file mode 100644 index 100380ac1..000000000 --- a/impala/impala-sink/src/test/java/com/dtstack/flink/sql/sink/impala/table/ImpalaSinkParserTest.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.dtstack.flink.sql.sink.impala.table; - -import com.dtstack.flink.sql.table.AbstractTableInfo; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import java.sql.Timestamp; -import java.util.HashMap; -import java.util.Map; - -public class ImpalaSinkParserTest { - - ImpalaSinkParser sinkParser; - - @Before - public void setUp() { - sinkParser = new ImpalaSinkParser(); - } - -// @Test - public void testGetTableInfo() throws Exception { - - final String tableName = "table_foo"; - final String fieldsInfo = "id INT, name VARCHAR"; - - Map props = new HashMap(); - props.put("authmech", 3); - - props.put("enablepartition", "true"); - props.put("partitionvalues", "{\"name\":[\"tom\",\"jeck\"]}"); - props.put("partitionfields", "name"); - props.put("partitionfieldtypes", "varchar"); - - props.put("url", "jdbc:hive2://myhost.example.com:21050/;principal=impala/myhost.example.com@H2.EXAMPLE.COM"); - props.put("tablename", "table_foo"); - props.put("username", "foo"); - props.put("password", "foo"); - - AbstractTableInfo tableInfo= sinkParser.getTableInfo(tableName, fieldsInfo, props); - props.put("authmech", 2); - sinkParser.getTableInfo(tableName, fieldsInfo, props); - props.put("authmech", 1); - props.put("principal", ""); - props.put("keytabfilepath", "/foo/bar.keytab"); - props.put("krb5filepath", "krb5.conf"); - props.put("krbhostfqdn", ""); - props.put("krbservicename", ""); - sinkParser.getTableInfo(tableName, fieldsInfo, props); - props.put("authmech", -1); - try { - sinkParser.getTableInfo(tableName, fieldsInfo, props); - } catch (IllegalArgumentException e) { } - - -// final String NORMAL_TYPE = "mysql"; -// final String table_type = tableInfo.getType(); -// Assert.assertTrue(NORMAL_TYPE.equals(table_type)); - } - -// @Test - public void testDbTypeConvertToJavaType() { - String ERR_TYPE = "TEST_foo"; - try { - sinkParser.dbTypeConvertToJavaType(ERR_TYPE); - } catch (Exception e) { - String normal = "不支持 " + ERR_TYPE +" 类型"; - Assert.assertTrue(e.getMessage().equals(normal)); - } - Class clazz = sinkParser.dbTypeConvertToJavaType("timestamp"); - Assert.assertTrue(Timestamp.class.equals(clazz)); - } - -} \ No newline at end of file diff --git a/impala/pom.xml b/impala/pom.xml deleted file mode 100644 index 08bb09090..000000000 --- a/impala/pom.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - flink.sql - com.dtstack.flink - 1.0-SNAPSHOT - ../pom.xml - - 4.0.0 - - sql.impala - pom - - impala-sink - impala-side - - - - 1.0-SNAPSHOT - - - - - - com.dtstack.flink - sql.core - ${sql.core.version} - provided - - - - com.cloudera.impala.jdbc - ImpalaJDBC41 - 2.6.12 - - - - org.apache.hadoop - hadoop-common - 2.7.3 - - - - - - \ No newline at end of file diff --git a/kafka-base/kafka-base-sink/pom.xml b/kafka-base/kafka-base-sink/pom.xml deleted file mode 100644 index 679ba0d51..000000000 --- a/kafka-base/kafka-base-sink/pom.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - 4.0.0 - - sql.kafka-base - com.dtstack.flink - 1.0-SNAPSHOT - ../pom.xml - - - sql.sink.kafka-base - kafka-base-sink - - jar - - \ No newline at end of file diff --git a/kafka-base/kafka-base-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/AbstractKafkaProducerFactory.java b/kafka-base/kafka-base-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/AbstractKafkaProducerFactory.java deleted file mode 100644 index ad9d77730..000000000 --- a/kafka-base/kafka-base-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/AbstractKafkaProducerFactory.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.kafka; - -import com.dtstack.flink.sql.format.FormatType; -import com.dtstack.flink.sql.format.SerializationMetricWrapper; -import com.dtstack.flink.sql.sink.kafka.serialization.AvroTuple2SerializationSchema; -import com.dtstack.flink.sql.sink.kafka.serialization.CsvTupleSerializationSchema; -import com.dtstack.flink.sql.sink.kafka.serialization.JsonTupleSerializationSchema; -import com.dtstack.flink.sql.sink.kafka.table.KafkaSinkTableInfo; -import org.apache.commons.lang3.StringUtils; -import org.apache.flink.api.common.serialization.SerializationSchema; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.streaming.api.functions.sink.RichSinkFunction; -import org.apache.flink.streaming.connectors.kafka.partitioner.FlinkKafkaPartitioner; -import org.apache.flink.types.Row; - -import java.util.Optional; -import java.util.Properties; - -/** - * 抽象的kafka producer 的工厂类 - * 包括序统一的序列化工具的构造 - * company: www.dtstack.com - * @author: toutian - * create: 2019/12/26 - */ -public abstract class AbstractKafkaProducerFactory { - - /** - * 获取具体的KafkaProducer - * eg create KafkaProducer010 - * @param kafkaSinkTableInfo - * @param typeInformation - * @param properties - * @param partitioner - * @return - */ - public abstract RichSinkFunction> createKafkaProducer(KafkaSinkTableInfo kafkaSinkTableInfo, TypeInformation> typeInformation, - Properties properties, Optional>> partitioner, String[] partitionKeys); - - protected SerializationMetricWrapper createSerializationMetricWrapper(KafkaSinkTableInfo kafkaSinkTableInfo, TypeInformation> typeInformation) { - SerializationSchema> serializationSchema = createSerializationSchema(kafkaSinkTableInfo, typeInformation); - return new SerializationMetricWrapper(serializationSchema); - } - - private SerializationSchema> createSerializationSchema(KafkaSinkTableInfo kafkaSinkTableInfo, TypeInformation> typeInformation) { - SerializationSchema> serializationSchema = null; - if (FormatType.JSON.name().equalsIgnoreCase(kafkaSinkTableInfo.getSinkDataType())) { - if (StringUtils.isNotBlank(kafkaSinkTableInfo.getSchemaString())) { - serializationSchema = new JsonTupleSerializationSchema(kafkaSinkTableInfo.getSchemaString(), kafkaSinkTableInfo.getUpdateMode()); - } else if (typeInformation != null && typeInformation.getArity() != 0) { - serializationSchema = new JsonTupleSerializationSchema(typeInformation, kafkaSinkTableInfo.getUpdateMode()); - } else { - throw new IllegalArgumentException("sinkDataType:" + FormatType.JSON.name() + " must set schemaString(JSON Schema)or TypeInformation"); - } - } else if (FormatType.CSV.name().equalsIgnoreCase(kafkaSinkTableInfo.getSinkDataType())) { - if (StringUtils.isBlank(kafkaSinkTableInfo.getFieldDelimiter())) { - throw new IllegalArgumentException("sinkDataType:" + FormatType.CSV.name() + " must set fieldDelimiter"); - } - final CsvTupleSerializationSchema.Builder serSchemaBuilder = new CsvTupleSerializationSchema.Builder(typeInformation); - serSchemaBuilder.setFieldDelimiter(kafkaSinkTableInfo.getFieldDelimiter().toCharArray()[0]); - serSchemaBuilder.setUpdateMode(kafkaSinkTableInfo.getUpdateMode()); - - serializationSchema = serSchemaBuilder.build(); - } else if (FormatType.AVRO.name().equalsIgnoreCase(kafkaSinkTableInfo.getSinkDataType())) { - if (StringUtils.isBlank(kafkaSinkTableInfo.getSchemaString())) { - throw new IllegalArgumentException("sinkDataType:" + FormatType.AVRO.name() + " must set schemaString"); - } - serializationSchema = new AvroTuple2SerializationSchema(kafkaSinkTableInfo.getSchemaString(), kafkaSinkTableInfo.getUpdateMode()); - } - - if (null == serializationSchema) { - throw new UnsupportedOperationException("FormatType:" + kafkaSinkTableInfo.getSinkDataType()); - } - - return serializationSchema; - } - -} diff --git a/kafka-base/kafka-base-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/AbstractKafkaSink.java b/kafka-base/kafka-base-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/AbstractKafkaSink.java deleted file mode 100644 index f0f215c27..000000000 --- a/kafka-base/kafka-base-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/AbstractKafkaSink.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.kafka; - -import com.dtstack.flink.sql.enums.EUpdateMode; -import com.dtstack.flink.sql.sink.IStreamSinkGener; -import com.dtstack.flink.sql.sink.kafka.table.KafkaSinkTableInfo; -import com.dtstack.flink.sql.util.DataTypeUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.api.java.typeutils.TupleTypeInfo; -import org.apache.flink.streaming.api.datastream.DataStream; -import org.apache.flink.streaming.api.datastream.DataStreamSink; -import org.apache.flink.streaming.api.functions.sink.SinkFunction; -import org.apache.flink.streaming.connectors.kafka.partitioner.FlinkKafkaPartitioner; -import org.apache.flink.table.api.TableSchema; -import org.apache.flink.table.sinks.RetractStreamTableSink; -import org.apache.flink.table.sinks.TableSink; -import org.apache.flink.table.types.DataType; -import org.apache.flink.types.Row; -import org.apache.flink.util.Preconditions; -import org.apache.kafka.clients.consumer.ConsumerConfig; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.Optional; -import java.util.Properties; -import java.util.stream.IntStream; - -import static org.apache.flink.table.types.utils.TypeConversions.fromLegacyInfoToDataType; - -/** - * Date: 2020/3/30 - * Company: www.dtstack.com - * @author maqi - */ -public abstract class AbstractKafkaSink implements RetractStreamTableSink, IStreamSinkGener { - public static final String SINK_OPERATOR_NAME_TPL = "${topic}_${table}"; - - protected String[] fieldNames; - protected TypeInformation[] fieldTypes; - - protected String[] partitionKeys; - protected String sinkOperatorName; - protected Properties properties; - protected int parallelism = -1; - protected String topic; - protected String tableName; - protected String updateMode; - - protected TableSchema schema; - protected SinkFunction> kafkaProducer011; - - protected Optional>> partitioner; - - protected Properties getKafkaProperties(KafkaSinkTableInfo KafkaSinkTableInfo) { - Properties props = new Properties(); - props.setProperty(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, KafkaSinkTableInfo.getBootstrapServers()); - - for (String key : KafkaSinkTableInfo.getKafkaParamKeys()) { - props.setProperty(key, KafkaSinkTableInfo.getKafkaParam(key)); - } - return props; - } - // TODO Source有相同的方法日后可以合并 - protected TypeInformation[] getTypeInformations(KafkaSinkTableInfo kafka11SinkTableInfo) { - String[] fieldTypes = kafka11SinkTableInfo.getFieldTypes(); - Class[] fieldClasses = kafka11SinkTableInfo.getFieldClasses(); - TypeInformation[] types = IntStream.range(0, fieldClasses.length) - .mapToObj( - i -> { - if (fieldClasses[i].isArray()) { - return DataTypeUtils.convertToArray(fieldTypes[i]); - } - if (fieldClasses[i] == new HashMap().getClass()) { - return DataTypeUtils.convertToMap(fieldTypes[i]); - } - return TypeInformation.of(fieldClasses[i]); - }) - .toArray(TypeInformation[]::new); - return types; - } - - - protected TableSchema buildTableSchema(String[] fieldNames, TypeInformation[] fieldTypes) { - Preconditions.checkArgument(fieldNames.length == fieldTypes.length, "fieldNames length must equals fieldTypes length !"); - - DataType[] dataTypes = IntStream.range(0, fieldTypes.length) - .mapToObj(i -> fromLegacyInfoToDataType(fieldTypes[i])) - .toArray(DataType[]::new); - - TableSchema tableSchema = TableSchema.builder() - .fields(fieldNames, dataTypes) - .build(); - return tableSchema; - } - - protected String[] getPartitionKeys(KafkaSinkTableInfo kafkaSinkTableInfo) { - String keysStr = kafkaSinkTableInfo.getPartitionKeys(); - if (StringUtils.isNotBlank(keysStr)) { - String[] keys = StringUtils.split(keysStr, ","); - String[] cleanedKeys = Arrays.stream(keys) - .map(x -> x.trim()) - .toArray(String[]::new); - return cleanedKeys; - } - return null; - } - - @Override - public DataStreamSink> consumeDataStream(DataStream> dataStream) { - if (updateMode.equalsIgnoreCase(EUpdateMode.APPEND.name())) { - dataStream = dataStream.filter((Tuple2 record) -> record.f0); - } - DataStreamSink> dataStreamSink = dataStream.addSink(kafkaProducer011).name(sinkOperatorName); - if (parallelism > 0) { - dataStreamSink.setParallelism(parallelism); - } - return dataStreamSink; - } - - @Override - public void emitDataStream(DataStream> dataStream) { - consumeDataStream(dataStream); - } - - @Override - public TableSink> configure(String[] fieldNames, TypeInformation[] fieldTypes) { - this.fieldNames = fieldNames; - this.fieldTypes = fieldTypes; - return this; - } - - @Override - public TupleTypeInfo> getOutputType() { - return new TupleTypeInfo(org.apache.flink.table.api.Types.BOOLEAN(), new RowTypeInfo(fieldTypes, fieldNames)); - } - - @Override - public TableSchema getTableSchema() { - return schema; - } - - @Override - public TypeInformation getRecordType() { - return new RowTypeInfo(fieldTypes, fieldNames); - } -} diff --git a/kafka-base/kafka-base-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerFlinkPartition.java b/kafka-base/kafka-base-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerFlinkPartition.java deleted file mode 100644 index 479c490a5..000000000 --- a/kafka-base/kafka-base-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerFlinkPartition.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.dtstack.flink.sql.sink.kafka; - - -import org.apache.flink.streaming.connectors.kafka.partitioner.FlinkKafkaPartitioner; -import org.apache.flink.util.Preconditions; - -public class CustomerFlinkPartition extends FlinkKafkaPartitioner { - private static final long serialVersionUID = 1L; - private int parallelInstanceId; - - public CustomerFlinkPartition() { - - } - - @Override - public void open(int parallelInstanceId, int parallelInstances) { - Preconditions.checkArgument(parallelInstanceId >= 0, "Id of this subtask cannot be negative."); - Preconditions.checkArgument(parallelInstances > 0, "Number of subtasks must be larger than 0."); - this.parallelInstanceId = parallelInstanceId; - } - - @Override - public int partition(T record, byte[] key, byte[] value, String targetTopic, int[] partitions) { - Preconditions.checkArgument(partitions != null && partitions.length > 0, "Partitions of the target topic is empty."); - if (key == null) { - return partitions[this.parallelInstanceId % partitions.length]; - } - return partitions[Math.abs(new String(key).hashCode()) % partitions.length]; - } - - @Override - public boolean equals(Object o) { - return this == o || o instanceof CustomerFlinkPartition; - } - - @Override - public int hashCode() { - return CustomerFlinkPartition.class.hashCode(); - } -} diff --git a/kafka-base/kafka-base-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/serialization/AvroTuple2SerializationSchema.java b/kafka-base/kafka-base-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/serialization/AvroTuple2SerializationSchema.java deleted file mode 100644 index fd019291b..000000000 --- a/kafka-base/kafka-base-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/serialization/AvroTuple2SerializationSchema.java +++ /dev/null @@ -1,366 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.kafka.serialization; - -import com.dtstack.flink.sql.enums.EUpdateMode; -import org.apache.avro.LogicalType; -import org.apache.avro.LogicalTypes; -import org.apache.avro.Schema; -import org.apache.avro.SchemaParseException; -import org.apache.avro.generic.GenericData; -import org.apache.avro.generic.GenericDatumWriter; -import org.apache.avro.generic.GenericRecord; -import org.apache.avro.generic.IndexedRecord; -import org.apache.avro.io.DatumWriter; -import org.apache.avro.io.Encoder; -import org.apache.avro.io.EncoderFactory; -import org.apache.avro.specific.SpecificData; -import org.apache.avro.specific.SpecificDatumWriter; -import org.apache.avro.specific.SpecificRecord; -import org.apache.avro.util.Utf8; -import org.apache.commons.lang3.StringUtils; -import org.apache.flink.api.common.serialization.SerializationSchema; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.types.Row; -import org.apache.flink.util.Preconditions; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.math.BigDecimal; -import java.nio.ByteBuffer; -import java.sql.Date; -import java.sql.Time; -import java.sql.Timestamp; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.TimeZone; -import java.util.stream.Collectors; - -/** - * Serialization schema that serializes CROW into Avro bytes. - * - *

Serializes objects that are represented in (nested) Flink rows. It support types that - * are compatible with Flink's Table & SQL API. - ** - * @author maqi - */ -public class AvroTuple2SerializationSchema implements SerializationSchema> { - - /** - * Used for time conversions from SQL types. - */ - private static final TimeZone LOCAL_TZ = TimeZone.getDefault(); - - /** - * Avro record class for serialization. Might be null if record class is not available. - */ - private Class recordClazz; - - /** - * Schema string for deserialization. - */ - private String schemaString; - - /** - * Avro serialization schema. - */ - private transient Schema schema; - - /** - * Writer to serialize Avro record into a byte array. - */ - private transient DatumWriter datumWriter; - - /** - * Output stream to serialize records into byte array. - */ - private transient ByteArrayOutputStream arrayOutputStream; - - /** - * Low-level class for serialization of Avro values. - */ - private transient Encoder encoder; - - private String updateMode; - - private String retractKey = "retract"; - - /** - * Creates an Avro serialization schema for the given specific record class. - * - * @param recordClazz Avro record class used to serialize Flink's row to Avro's record - */ - public AvroTuple2SerializationSchema(Class recordClazz, String updateMode) { - Preconditions.checkNotNull(recordClazz, "Avro record class must not be null."); - this.recordClazz = recordClazz; - this.schema = SpecificData.get().getSchema(recordClazz); - this.schemaString = schema.toString(); - this.datumWriter = new SpecificDatumWriter<>(schema); - this.arrayOutputStream = new ByteArrayOutputStream(); - this.encoder = EncoderFactory.get().binaryEncoder(arrayOutputStream, null); - this.updateMode = updateMode; - } - - /** - * Creates an Avro serialization schema for the given Avro schema string. - * - * @param avroSchemaString Avro schema string used to serialize Flink's row to Avro's record - */ - public AvroTuple2SerializationSchema(String avroSchemaString, String updateMode) { - Preconditions.checkNotNull(avroSchemaString, "Avro schema must not be null."); - this.recordClazz = null; - this.schemaString = avroSchemaString; - try { - this.schema = new Schema.Parser().parse(avroSchemaString); - } catch (SchemaParseException e) { - throw new IllegalArgumentException("Could not parse Avro schema string.", e); - } - this.datumWriter = new GenericDatumWriter<>(schema); - this.arrayOutputStream = new ByteArrayOutputStream(); - this.encoder = EncoderFactory.get().binaryEncoder(arrayOutputStream, null); - this.updateMode = updateMode; - } - - @Override - public byte[] serialize(Tuple2 tuple2) { - try { - Row row = tuple2.f1; - boolean change = tuple2.f0; - - // convert to record - final GenericRecord record = convertRowToAvroRecord(schema, row); - - dealRetractField(change, record); - - arrayOutputStream.reset(); - datumWriter.write(record, encoder); - encoder.flush(); - return arrayOutputStream.toByteArray(); - } catch (Exception e) { - throw new RuntimeException("Failed to serialize row.", e); - } - } - - protected void dealRetractField(boolean change, GenericRecord record) { - schema.getFields() - .stream() - .filter(field -> StringUtils.equalsIgnoreCase(field.name(), retractKey)) - .findFirst() - .ifPresent(field -> { - if (StringUtils.equalsIgnoreCase(updateMode, EUpdateMode.UPSERT.name())) { - record.put(retractKey, convertFlinkType(field.schema(), change)); - } - }); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - final AvroTuple2SerializationSchema that = (AvroTuple2SerializationSchema) o; - return Objects.equals(recordClazz, that.recordClazz) && Objects.equals(schemaString, that.schemaString); - } - - @Override - public int hashCode() { - return Objects.hash(recordClazz, schemaString); - } - - // -------------------------------------------------------------------------------------------- - - private GenericRecord convertRowToAvroRecord(Schema schema, Row row) { - - final List fields = schema.getFields() - .stream() - .filter(field -> !StringUtils.equalsIgnoreCase(field.name(), retractKey)) - .collect(Collectors.toList()); - - final int length = fields.size(); - final GenericRecord record = new GenericData.Record(schema); - for (int i = 0; i < length; i++) { - final Schema.Field field = fields.get(i); - record.put(i, convertFlinkType(field.schema(), row.getField(i))); - } - return record; - } - - private Object convertFlinkType(Schema schema, Object object) { - if (object == null) { - return null; - } - switch (schema.getType()) { - case RECORD: - if (object instanceof Row) { - return convertRowToAvroRecord(schema, (Row) object); - } - throw new IllegalStateException("Row expected but was: " + object.getClass()); - case ENUM: - return new GenericData.EnumSymbol(schema, object.toString()); - case ARRAY: - final Schema elementSchema = schema.getElementType(); - final Object[] array = (Object[]) object; - final GenericData.Array convertedArray = new GenericData.Array<>(array.length, schema); - for (Object element : array) { - convertedArray.add(convertFlinkType(elementSchema, element)); - } - return convertedArray; - case MAP: - final Map map = (Map) object; - final Map convertedMap = new HashMap<>(); - for (Map.Entry entry : map.entrySet()) { - convertedMap.put( - new Utf8(entry.getKey().toString()), - convertFlinkType(schema.getValueType(), entry.getValue())); - } - return convertedMap; - case UNION: - final List types = schema.getTypes(); - final int size = types.size(); - final Schema actualSchema; - if (size == 2 && types.get(0).getType() == Schema.Type.NULL) { - actualSchema = types.get(1); - } else if (size == 2 && types.get(1).getType() == Schema.Type.NULL) { - actualSchema = types.get(0); - } else if (size == 1) { - actualSchema = types.get(0); - } else { - // generic type - return object; - } - return convertFlinkType(actualSchema, object); - case FIXED: - // check for logical type - if (object instanceof BigDecimal) { - return new GenericData.Fixed( - schema, - convertFromDecimal(schema, (BigDecimal) object)); - } - return new GenericData.Fixed(schema, (byte[]) object); - case STRING: - return new Utf8(object.toString()); - case BYTES: - // check for logical type - if (object instanceof BigDecimal) { - return ByteBuffer.wrap(convertFromDecimal(schema, (BigDecimal) object)); - } - return ByteBuffer.wrap((byte[]) object); - case INT: - // check for logical types - if (object instanceof Date) { - return convertFromDate(schema, (Date) object); - } else if (object instanceof Time) { - return convertFromTime(schema, (Time) object); - } - return object; - case LONG: - // check for logical type - if (object instanceof Timestamp) { - return convertFromTimestamp(schema, (Timestamp) object); - } - return object; - case FLOAT: - case DOUBLE: - case BOOLEAN: - return object; - default: - } - throw new RuntimeException("Unsupported Avro type:" + schema); - } - - private byte[] convertFromDecimal(Schema schema, BigDecimal decimal) { - final LogicalType logicalType = schema.getLogicalType(); - if (logicalType instanceof LogicalTypes.Decimal) { - final LogicalTypes.Decimal decimalType = (LogicalTypes.Decimal) logicalType; - // rescale to target type - final BigDecimal rescaled = decimal.setScale(decimalType.getScale(), BigDecimal.ROUND_UNNECESSARY); - // byte array must contain the two's-complement representation of the - // unscaled integer value in big-endian byte order - return decimal.unscaledValue().toByteArray(); - } else { - throw new RuntimeException("Unsupported decimal type."); - } - } - - private int convertFromDate(Schema schema, Date date) { - final LogicalType logicalType = schema.getLogicalType(); - if (logicalType == LogicalTypes.date()) { - // adopted from Apache Calcite - final long time = date.getTime(); - final long converted = time + (long) LOCAL_TZ.getOffset(time); - return (int) (converted / 86400000L); - } else { - throw new RuntimeException("Unsupported date type."); - } - } - - private int convertFromTime(Schema schema, Time date) { - final LogicalType logicalType = schema.getLogicalType(); - if (logicalType == LogicalTypes.timeMillis()) { - // adopted from Apache Calcite - final long time = date.getTime(); - final long converted = time + (long) LOCAL_TZ.getOffset(time); - return (int) (converted % 86400000L); - } else { - throw new RuntimeException("Unsupported time type."); - } - } - - private long convertFromTimestamp(Schema schema, Timestamp date) { - final LogicalType logicalType = schema.getLogicalType(); - if (logicalType == LogicalTypes.timestampMillis()) { - // adopted from Apache Calcite - final long time = date.getTime(); - return time + (long) LOCAL_TZ.getOffset(time); - } else { - throw new RuntimeException("Unsupported timestamp type."); - } - } - - private void writeObject(ObjectOutputStream outputStream) throws IOException { - outputStream.writeObject(recordClazz); - outputStream.writeObject(schemaString); // support for null - outputStream.writeObject(retractKey); - outputStream.writeObject(updateMode); - } - - @SuppressWarnings("unchecked") - private void readObject(ObjectInputStream inputStream) throws ClassNotFoundException, IOException { - recordClazz = (Class) inputStream.readObject(); - schemaString = (String) inputStream.readObject(); - if (recordClazz != null) { - schema = SpecificData.get().getSchema(recordClazz); - } else { - schema = new Schema.Parser().parse(schemaString); - } - retractKey = (String) inputStream.readObject(); - updateMode = (String) inputStream.readObject(); - - datumWriter = new SpecificDatumWriter<>(schema); - arrayOutputStream = new ByteArrayOutputStream(); - encoder = EncoderFactory.get().binaryEncoder(arrayOutputStream, null); - } -} diff --git a/kafka-base/kafka-base-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/serialization/CsvTupleSerializationSchema.java b/kafka-base/kafka-base-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/serialization/CsvTupleSerializationSchema.java deleted file mode 100644 index 32c00018b..000000000 --- a/kafka-base/kafka-base-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/serialization/CsvTupleSerializationSchema.java +++ /dev/null @@ -1,372 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.kafka.serialization; - -import com.dtstack.flink.sql.enums.EUpdateMode; -import org.apache.commons.lang3.StringUtils; -import org.apache.flink.annotation.PublicEvolving; -import org.apache.flink.api.common.serialization.SerializationSchema; -import org.apache.flink.api.common.typeinfo.BasicArrayTypeInfo; -import org.apache.flink.api.common.typeinfo.PrimitiveArrayTypeInfo; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.common.typeinfo.Types; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.api.java.typeutils.ObjectArrayTypeInfo; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.api.java.typeutils.TupleTypeInfo; -import org.apache.flink.formats.csv.CsvRowDeserializationSchema; -import org.apache.flink.formats.csv.CsvRowSchemaConverter; -import org.apache.flink.formats.csv.CsvRowSerializationSchema; -import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.JsonNode; -import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.ObjectWriter; -import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.node.ArrayNode; -import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.node.ContainerNode; -import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.node.ObjectNode; -import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.dataformat.csv.CsvMapper; -import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.dataformat.csv.CsvSchema; -import org.apache.flink.types.Row; -import org.apache.flink.util.Preconditions; - -import java.io.Serializable; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.util.Arrays; -import java.util.Objects; - -/** - * Serialization schema that serializes an object of Flink types into a CSV bytes. - * - *

Serializes the input row into a {@link ObjectNode} and - * converts it into byte[]. - * - *

Result byte[] messages can be deserialized using {@link CsvRowDeserializationSchema}. - */ -@PublicEvolving -public final class CsvTupleSerializationSchema implements SerializationSchema> { - - private static final long serialVersionUID = 2098447220136965L; - - /** Type information describing the input CSV data. */ - private final RowTypeInfo typeInfo; - - /** Runtime instance that performs the actual work. */ - private final RuntimeConverter runtimeConverter; - - /** CsvMapper used to write {@link JsonNode} into bytes. */ - private final CsvMapper csvMapper; - - /** Schema describing the input CSV data. */ - private CsvSchema csvSchema; - - /** Object writer used to write rows. It is configured by {@link CsvSchema}. */ - private ObjectWriter objectWriter; - - /** Reusable object node. */ - private transient ObjectNode root; - - private String updateMode; - - private String retractKey = "retract"; - - private CsvTupleSerializationSchema( - RowTypeInfo typeInfo, - CsvSchema csvSchema, - String updateMode) { - this.typeInfo = typeInfo; - this.runtimeConverter = createRowRuntimeConverter(typeInfo, true); - this.csvMapper = new CsvMapper(); - this.csvSchema = csvSchema; - this.updateMode = updateMode; - this.objectWriter = csvMapper.writer(csvSchema); - } - - /** - * A builder for creating a {@link CsvRowSerializationSchema}. - */ - @PublicEvolving - public static class Builder { - - private final RowTypeInfo typeInfo; - private CsvSchema csvSchema; - private String updateMode; - - /** - * Creates a {@link CsvRowSerializationSchema} expecting the given {@link TypeInformation}. - * - * @param typeInfo type information used to create schema. - */ - public Builder(TypeInformation> typeInfo) { - Preconditions.checkNotNull(typeInfo, "Type information must not be null."); - - if (!(typeInfo instanceof TupleTypeInfo)) { - throw new IllegalArgumentException("Row type information expected."); - } - RowTypeInfo rowTypeInfo = (RowTypeInfo) ((TupleTypeInfo) typeInfo).getTypeAt(1); - - this.typeInfo = rowTypeInfo; - this.csvSchema = CsvRowSchemaConverter.convert(rowTypeInfo); - } - - public Builder setFieldDelimiter(char c) { - this.csvSchema = this.csvSchema.rebuild().setColumnSeparator(c).build(); - return this; - } - - public Builder setLineDelimiter(String delimiter) { - Preconditions.checkNotNull(delimiter, "Delimiter must not be null."); - if (!("\n".equals(delimiter)) && !("\r".equals(delimiter)) && !("\r\n".equals(delimiter))) { - throw new IllegalArgumentException( - "Unsupported new line delimiter. Only \\n, \\r, or \\r\\n are supported."); - } - this.csvSchema = this.csvSchema.rebuild().setLineSeparator(delimiter).build(); - return this; - } - - public Builder setArrayElementDelimiter(String delimiter) { - Preconditions.checkNotNull(delimiter, "Delimiter must not be null."); - this.csvSchema = this.csvSchema.rebuild().setArrayElementSeparator(delimiter).build(); - return this; - } - - public Builder setQuoteCharacter(char c) { - this.csvSchema = this.csvSchema.rebuild().setQuoteChar(c).build(); - return this; - } - - public Builder setEscapeCharacter(char c) { - this.csvSchema = this.csvSchema.rebuild().setEscapeChar(c).build(); - return this; - } - - public Builder setNullLiteral(String s) { - this.csvSchema = this.csvSchema.rebuild().setNullValue(s).build(); - return this; - } - - public Builder setUpdateMode(String updateMode) { - this.updateMode = updateMode; - return this; - } - - public CsvTupleSerializationSchema build() { - return new CsvTupleSerializationSchema( - typeInfo, - csvSchema, - updateMode); - } - } - - @Override - public byte[] serialize(Tuple2 tuple2) { - Row row = tuple2.f1; - boolean change = tuple2.f0; - if (root == null) { - root = csvMapper.createObjectNode(); - } - try { - runtimeConverter.convert(csvMapper, root, row); - if (StringUtils.equalsIgnoreCase(updateMode, EUpdateMode.UPSERT.name())) { - fillRetractField(row, change); - } - - return objectWriter.writeValueAsBytes(root); - } catch (Throwable t) { - throw new RuntimeException("Could not serialize row '" + row + "'.", t); - } - } - - protected void fillRetractField(Row row, boolean change) { - root.put(retractKey, change); - CsvSchema.Builder newBuilder = new CsvSchema.Builder(csvSchema); - - CsvSchema.Column retractColumn = new CsvSchema.Column(row.getArity(), retractKey, CsvSchema.ColumnType.BOOLEAN); - newBuilder.addColumn(retractColumn); - csvSchema = newBuilder.build(); - - this.objectWriter = csvMapper.writer(csvSchema); - - } - - @Override - public boolean equals(Object o) { - if (o == null || o.getClass() != this.getClass()) { - return false; - } - if (this == o) { - return true; - } - final CsvTupleSerializationSchema that = (CsvTupleSerializationSchema) o; - final CsvSchema otherSchema = that.csvSchema; - - return typeInfo.equals(that.typeInfo) && - csvSchema.getColumnSeparator() == otherSchema.getColumnSeparator() && - Arrays.equals(csvSchema.getLineSeparator(), otherSchema.getLineSeparator()) && - csvSchema.getArrayElementSeparator().equals(otherSchema.getArrayElementSeparator()) && - csvSchema.getQuoteChar() == otherSchema.getQuoteChar() && - csvSchema.getEscapeChar() == otherSchema.getEscapeChar() && - Arrays.equals(csvSchema.getNullValue(), otherSchema.getNullValue()); - } - - @Override - public int hashCode() { - return Objects.hash( - typeInfo, - csvSchema.getColumnSeparator(), - csvSchema.getLineSeparator(), - csvSchema.getArrayElementSeparator(), - csvSchema.getQuoteChar(), - csvSchema.getEscapeChar(), - csvSchema.getNullValue()); - } - - // -------------------------------------------------------------------------------------------- - - private interface RuntimeConverter extends Serializable { - JsonNode convert(CsvMapper csvMapper, ContainerNode container, Object obj); - } - - private static RuntimeConverter createRowRuntimeConverter(RowTypeInfo rowTypeInfo, boolean isTopLevel) { - final TypeInformation[] fieldTypes = rowTypeInfo.getFieldTypes(); - final String[] fieldNames = rowTypeInfo.getFieldNames(); - - final RuntimeConverter[] fieldConverters = createFieldRuntimeConverters(fieldTypes); - - return assembleRowRuntimeConverter(isTopLevel, fieldNames, fieldConverters); - } - - private static RuntimeConverter[] createFieldRuntimeConverters(TypeInformation[] fieldTypes) { - final RuntimeConverter[] fieldConverters = new RuntimeConverter[fieldTypes.length]; - for (int i = 0; i < fieldTypes.length; i++) { - fieldConverters[i] = createNullableRuntimeConverter(fieldTypes[i]); - } - return fieldConverters; - } - - private static RuntimeConverter assembleRowRuntimeConverter( - boolean isTopLevel, - String[] fieldNames, - RuntimeConverter[] fieldConverters) { - final int rowArity = fieldNames.length; - // top level reuses the object node container - if (isTopLevel) { - return (csvMapper, container, obj) -> { - final Row row = (Row) obj; - - validateArity(rowArity, row.getArity()); - - final ObjectNode objectNode = (ObjectNode) container; - for (int i = 0; i < rowArity; i++) { - objectNode.set( - fieldNames[i], - fieldConverters[i].convert(csvMapper, container, row.getField(i))); - } - return objectNode; - }; - } else { - return (csvMapper, container, obj) -> { - final Row row = (Row) obj; - - validateArity(rowArity, row.getArity()); - - final ArrayNode arrayNode = csvMapper.createArrayNode(); - for (int i = 0; i < rowArity; i++) { - arrayNode.add(fieldConverters[i].convert(csvMapper, arrayNode, row.getField(i))); - } - return arrayNode; - }; - } - } - - private static RuntimeConverter createNullableRuntimeConverter(TypeInformation info) { - final RuntimeConverter valueConverter = createRuntimeConverter(info); - return (csvMapper, container, obj) -> { - if (obj == null) { - return container.nullNode(); - } - return valueConverter.convert(csvMapper, container, obj); - }; - } - - private static RuntimeConverter createRuntimeConverter(TypeInformation info) { - if (info.equals(Types.VOID)) { - return (csvMapper, container, obj) -> container.nullNode(); - } else if (info.equals(Types.STRING)) { - return (csvMapper, container, obj) -> container.textNode((String) obj); - } else if (info.equals(Types.BOOLEAN)) { - return (csvMapper, container, obj) -> container.booleanNode((Boolean) obj); - } else if (info.equals(Types.BYTE)) { - return (csvMapper, container, obj) -> container.numberNode((Byte) obj); - } else if (info.equals(Types.SHORT)) { - return (csvMapper, container, obj) -> container.numberNode((Short) obj); - } else if (info.equals(Types.INT)) { - return (csvMapper, container, obj) -> container.numberNode((Integer) obj); - } else if (info.equals(Types.LONG)) { - return (csvMapper, container, obj) -> container.numberNode((Long) obj); - } else if (info.equals(Types.FLOAT)) { - return (csvMapper, container, obj) -> container.numberNode((Float) obj); - } else if (info.equals(Types.DOUBLE)) { - return (csvMapper, container, obj) -> container.numberNode((Double) obj); - } else if (info.equals(Types.BIG_DEC)) { - return (csvMapper, container, obj) -> container.numberNode((BigDecimal) obj); - } else if (info.equals(Types.BIG_INT)) { - return (csvMapper, container, obj) -> container.numberNode((BigInteger) obj); - } else if (info.equals(Types.SQL_DATE)) { - return (csvMapper, container, obj) -> container.textNode(obj.toString()); - } else if (info.equals(Types.SQL_TIME)) { - return (csvMapper, container, obj) -> container.textNode(obj.toString()); - } else if (info.equals(Types.SQL_TIMESTAMP)) { - return (csvMapper, container, obj) -> container.textNode(obj.toString()); - } else if (info instanceof RowTypeInfo){ - return createRowRuntimeConverter((RowTypeInfo) info, false); - } else if (info instanceof BasicArrayTypeInfo) { - return createObjectArrayRuntimeConverter(((BasicArrayTypeInfo) info).getComponentInfo()); - } else if (info instanceof ObjectArrayTypeInfo) { - return createObjectArrayRuntimeConverter(((ObjectArrayTypeInfo) info).getComponentInfo()); - } else if (info instanceof PrimitiveArrayTypeInfo && - ((PrimitiveArrayTypeInfo) info).getComponentType() == Types.BYTE) { - return createByteArrayRuntimeConverter(); - } - else { - throw new RuntimeException("Unsupported type information '" + info + "'."); - } - } - - private static RuntimeConverter createObjectArrayRuntimeConverter(TypeInformation elementType) { - final RuntimeConverter elementConverter = createNullableRuntimeConverter(elementType); - return (csvMapper, container, obj) -> { - final Object[] array = (Object[]) obj; - final ArrayNode arrayNode = csvMapper.createArrayNode(); - for (Object element : array) { - arrayNode.add(elementConverter.convert(csvMapper, arrayNode, element)); - } - return arrayNode; - }; - } - - private static RuntimeConverter createByteArrayRuntimeConverter() { - return (csvMapper, container, obj) -> container.binaryNode((byte[]) obj); - } - - private static void validateArity(int expected, int actual) { - if (expected != actual) { - throw new RuntimeException("Row length mismatch. " + expected + - " fields expected but was " + actual + "."); - } - } -} diff --git a/kafka-base/kafka-base-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/serialization/CustomerKeyedSerializationSchema.java b/kafka-base/kafka-base-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/serialization/CustomerKeyedSerializationSchema.java deleted file mode 100644 index 662b6c230..000000000 --- a/kafka-base/kafka-base-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/serialization/CustomerKeyedSerializationSchema.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.dtstack.flink.sql.sink.kafka.serialization; - - -import com.dtstack.flink.sql.format.SerializationMetricWrapper; -import org.apache.flink.api.common.serialization.SerializationSchema; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.ObjectMapper; -import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.node.ObjectNode; -import org.apache.flink.streaming.util.serialization.KeyedSerializationSchema; -import org.apache.flink.types.Row; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.concurrent.atomic.AtomicLong; - -public class CustomerKeyedSerializationSchema implements KeyedSerializationSchema> { - - private static final Logger LOG = LoggerFactory.getLogger(CustomerKeyedSerializationSchema.class); - - private static final AtomicLong COUNTER = new AtomicLong(0L); - - private static final long serialVersionUID = 1L; - private final SerializationMetricWrapper serializationMetricWrapper; - private String[] partitionKeys; - private ObjectMapper mapper = null; - - public CustomerKeyedSerializationSchema(SerializationMetricWrapper serializationMetricWrapper, String[] partitionKeys) { - this.serializationMetricWrapper = serializationMetricWrapper; - this.partitionKeys = partitionKeys; - this.mapper = new ObjectMapper(); - } - - @Override - public byte[] serializeKey(Tuple2 element) { - if (partitionKeys == null || partitionKeys.length <= 0) { - return null; - } - SerializationSchema> serializationSchema = serializationMetricWrapper.getSerializationSchema(); - if (serializationSchema instanceof JsonTupleSerializationSchema) { - return serializeJsonKey((JsonTupleSerializationSchema) serializationSchema, element); - } - return null; - } - - @Override - public byte[] serializeValue(Tuple2 element) { - return this.serializationMetricWrapper.serialize(element); - } - - @Override - public String getTargetTopic(Tuple2 element) { - return null; - } - - private byte[] serializeJsonKey(JsonTupleSerializationSchema jsonTupleSerializationSchema, Tuple2 element) { - try { - byte[] data = jsonTupleSerializationSchema.serialize(element); - ObjectNode objectNode = mapper.readValue(data, ObjectNode.class); - StringBuilder sb = new StringBuilder(); - for (String key : partitionKeys) { - if (objectNode.has(key)) { - sb.append(objectNode.get(key.trim())); - } - } - return sb.toString().getBytes(); - } catch (Exception e) { - if (COUNTER.getAndIncrement() % 1000 == 0) { - LOG.error("serializeJsonKey error", e); - } - } - return null; - } -} diff --git a/kafka-base/kafka-base-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/table/KafkaSinkTableInfo.java b/kafka-base/kafka-base-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/table/KafkaSinkTableInfo.java deleted file mode 100644 index 2804c71de..000000000 --- a/kafka-base/kafka-base-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/table/KafkaSinkTableInfo.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.kafka.table; - -import com.dtstack.flink.sql.enums.EUpdateMode; -import com.dtstack.flink.sql.format.FormatType; -import com.dtstack.flink.sql.table.AbstractTargetTableInfo; -import com.google.common.base.Preconditions; -import org.apache.avro.Schema; -import org.apache.commons.lang3.StringUtils; - -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -/** - * Date: 2018/12/18 - * Company: www.dtstack.com - * - * @author DocLi - * @modifyer maqi - */ -public class KafkaSinkTableInfo extends AbstractTargetTableInfo { - - public static final String BOOTSTRAPSERVERS_KEY = "bootstrapServers"; - - public static final String TOPIC_KEY = "topic"; - - public static final String TYPE_KEY = "type"; - - public static final String ENABLE_KEY_PARTITION_KEY = "enableKeyPartitions"; - - public static final String PARTITION_KEY = "partitionKeys"; - - public static final String UPDATE_KEY = "updateMode"; - - public static final String SCHEMA_STRING_KEY = "schemaInfo"; - - public static final String RETRACT_FIELD_KEY = "retract"; - - public static final String CSV_FIELD_DELIMITER_KEY = "fieldDelimiter"; - - private String bootstrapServers; - - public Map kafkaParams = new HashMap(); - - private String topic; - - private String schemaString; - - private String fieldDelimiter; - - private String enableKeyPartition; - - private String partitionKeys; - - private String updateMode; - - public void addKafkaParam(String key, String value) { - kafkaParams.put(key, value); - } - - public String getKafkaParam(String key) { - return kafkaParams.get(key); - } - - public Set getKafkaParamKeys() { - return kafkaParams.keySet(); - } - - public String getBootstrapServers() { - return bootstrapServers; - } - - public void setBootstrapServers(String bootstrapServers) { - this.bootstrapServers = bootstrapServers; - } - - public String getTopic() { - return topic; - } - - public void setTopic(String topic) { - this.topic = topic; - } - - public String getSchemaString() { - return schemaString; - } - - public void setSchemaString(String schemaString) { - this.schemaString = schemaString; - } - - public String getFieldDelimiter() { - return fieldDelimiter; - } - - public void setFieldDelimiter(String fieldDelimiter) { - this.fieldDelimiter = fieldDelimiter; - } - - public String getUpdateMode() { - return updateMode; - } - - public void setUpdateMode(String updateMode) { - this.updateMode = updateMode; - } - - @Override - public boolean check() { - Preconditions.checkNotNull(getType(), "kafka of type is required"); - Preconditions.checkNotNull(bootstrapServers, "kafka of bootstrapServers is required"); - Preconditions.checkNotNull(topic, "kafka of topic is required"); - - if (StringUtils.equalsIgnoreCase(getSinkDataType(), FormatType.AVRO.name())) { - avroParamCheck(); - } - - return false; - } - - public void avroParamCheck() { - Preconditions.checkNotNull(schemaString, "avro type schemaInfo is required"); - if (StringUtils.equalsIgnoreCase(updateMode, EUpdateMode.UPSERT.name())) { - Schema schema = new Schema.Parser().parse(schemaString); - schema.getFields() - .stream() - .filter(field -> StringUtils.equalsIgnoreCase(field.name(), RETRACT_FIELD_KEY)) - .findFirst() - .orElseThrow(() -> - new NullPointerException(String.valueOf("arvo upsert mode the retract attribute must be contained in schemaInfo field "))); - } - } - - public String getEnableKeyPartition() { - return enableKeyPartition; - } - - public void setEnableKeyPartition(String enableKeyPartition) { - this.enableKeyPartition = enableKeyPartition; - } - - public String getPartitionKeys() { - return partitionKeys; - } - - public void setPartitionKeys(String partitionKeys) { - this.partitionKeys = partitionKeys; - } - -} \ No newline at end of file diff --git a/kafka-base/kafka-base-sink/src/test/java/com/dtstack/flink/sql/sink/kafka/AbstractKafkaProducerFactoryTest.java b/kafka-base/kafka-base-sink/src/test/java/com/dtstack/flink/sql/sink/kafka/AbstractKafkaProducerFactoryTest.java deleted file mode 100644 index 85698728c..000000000 --- a/kafka-base/kafka-base-sink/src/test/java/com/dtstack/flink/sql/sink/kafka/AbstractKafkaProducerFactoryTest.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.dtstack.flink.sql.sink.kafka; - -import com.dtstack.flink.sql.sink.kafka.serialization.CsvTupleSerializationSchema; -import com.dtstack.flink.sql.sink.kafka.table.KafkaSinkTableInfo; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.common.typeinfo.Types; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.api.java.typeutils.TupleTypeInfo; -import org.apache.flink.streaming.api.functions.sink.RichSinkFunction; -import org.apache.flink.streaming.connectors.kafka.partitioner.FlinkKafkaPartitioner; -import org.apache.flink.types.Row; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -import java.util.Optional; -import java.util.Properties; - -@RunWith(PowerMockRunner.class) -@PrepareForTest({CsvTupleSerializationSchema.class, CsvTupleSerializationSchema.Builder.class}) -public class AbstractKafkaProducerFactoryTest { - private AbstractKafkaProducerFactory kafkaProducerFactory; - private KafkaSinkTableInfo kafkaSinkTableInfo; - private TypeInformation> typeInformation; - - @Before - public void init() { - kafkaProducerFactory = new AbstractKafkaProducerFactory() { - @Override - public RichSinkFunction> createKafkaProducer( - KafkaSinkTableInfo kafkaSinkTableInfo - , TypeInformation> typeInformation - , Properties properties - , Optional>> partitioner - , String[] partitionKeys) { - return null; - } - }; - kafkaSinkTableInfo = new KafkaSinkTableInfo(); - String[] fieldNames = new String[1]; - fieldNames[0] = "1"; - TypeInformation[] typeInformation = new TypeInformation[1]; - typeInformation[0] = Types.STRING; - this.typeInformation = new TupleTypeInfo<>(org.apache.flink.table.api.Types.BOOLEAN(), new RowTypeInfo(typeInformation, fieldNames)); - } - - @Test - public void createSerializationSchemaWithJson() { - kafkaSinkTableInfo.setSinkDataType("json"); - kafkaSinkTableInfo.setUpdateMode("append"); - try { - kafkaProducerFactory.createSerializationMetricWrapper(kafkaSinkTableInfo, typeInformation); - } catch (Exception ignored) { - } - kafkaProducerFactory.createSerializationMetricWrapper(kafkaSinkTableInfo, typeInformation); - kafkaSinkTableInfo.setSchemaString("{\"name\":\"channel\",\"type\":\"string\"}"); - kafkaProducerFactory.createSerializationMetricWrapper(kafkaSinkTableInfo, typeInformation); - } - - @Test - public void createSerializationSchemaWithCsv() { - kafkaSinkTableInfo.setSinkDataType("csv"); - try { - kafkaProducerFactory.createSerializationMetricWrapper(kafkaSinkTableInfo, typeInformation); - } catch (Exception ignored) { - } - kafkaSinkTableInfo.setFieldDelimiter(","); - kafkaSinkTableInfo.setUpdateMode("append"); - kafkaProducerFactory.createSerializationMetricWrapper(kafkaSinkTableInfo, typeInformation); - } - - @Test - public void createSerializationSchemaWithAvro() { - kafkaSinkTableInfo.setSinkDataType("avro"); - try { - kafkaProducerFactory.createSerializationMetricWrapper(kafkaSinkTableInfo, typeInformation); - } catch (Exception ignored) { - - } - kafkaSinkTableInfo.setUpdateMode("append"); - kafkaSinkTableInfo.setSchemaString("{\"name\":\"channel\",\"type\":\"string\"}"); - kafkaProducerFactory.createSerializationMetricWrapper(kafkaSinkTableInfo, typeInformation); - } -} diff --git a/kafka-base/kafka-base-sink/src/test/java/com/dtstack/flink/sql/sink/kafka/AbstractKafkaSinkTest.java b/kafka-base/kafka-base-sink/src/test/java/com/dtstack/flink/sql/sink/kafka/AbstractKafkaSinkTest.java deleted file mode 100644 index 048de0aeb..000000000 --- a/kafka-base/kafka-base-sink/src/test/java/com/dtstack/flink/sql/sink/kafka/AbstractKafkaSinkTest.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.dtstack.flink.sql.sink.kafka; - -import com.dtstack.flink.sql.sink.kafka.table.KafkaSinkTableInfo; -import com.dtstack.flink.sql.table.AbstractTargetTableInfo; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.streaming.api.datastream.DataStream; -import org.apache.flink.streaming.api.datastream.DataStreamSink; -import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator; -import org.junit.Before; -import org.junit.Test; -import static org.mockito.Mockito.*; - -public class AbstractKafkaSinkTest { - private AbstractKafkaSink kafkaSink; - - @Before - public void init(){ - kafkaSink = new AbstractKafkaSink() { - @Override - public Object genStreamSink(AbstractTargetTableInfo targetTableInfo) { - return null; - } - }; - } - -// @Test - public void testKafkaSink(){ - KafkaSinkTableInfo kafkaSinkTableInfo = new KafkaSinkTableInfo(); - kafkaSinkTableInfo.setBootstrapServers("localhost:9092"); - kafkaSinkTableInfo.setPartitionKeys("a,b"); - kafkaSink.getKafkaProperties(kafkaSinkTableInfo); - kafkaSink.getPartitionKeys(kafkaSinkTableInfo); - - - } - -// @Test - public void getTypeInformations(){ - KafkaSinkTableInfo kafkaSinkTableInfo = new KafkaSinkTableInfo(); - Class[] fieldClass = new Class[1]; - fieldClass[0] = String.class; - kafkaSinkTableInfo.setFieldClasses(fieldClass); - kafkaSink.getTypeInformations(kafkaSinkTableInfo); - } - - // @Test - public void buildTableSchema(){ - String[] fieldNames = new String[1]; - fieldNames[0] = "1"; - TypeInformation[] typeInformations = new TypeInformation[1]; - typeInformations[0] = mock(TypeInformation.class); - kafkaSink.buildTableSchema(fieldNames, typeInformations); - } - - // @Test - public void emitDataStream(){ - String[] fieldNames = new String[1]; - fieldNames[0] = "1"; - TypeInformation[] typeInformations = new TypeInformation[1]; - typeInformations[0] = mock(TypeInformation.class); - kafkaSink.configure(fieldNames, typeInformations); - kafkaSink.getFieldNames(); - DataStream dataStream = mock(DataStream.class); - DataStreamSink dataStreamSink = mock(DataStreamSink.class); - SingleOutputStreamOperator singleOutputStreamOperator = mock(SingleOutputStreamOperator.class); - when(dataStream.map(any())).thenReturn(singleOutputStreamOperator); - when(singleOutputStreamOperator.setParallelism(anyInt())).thenReturn(singleOutputStreamOperator); - when(singleOutputStreamOperator.addSink(anyObject())).thenReturn(dataStreamSink); - when(dataStreamSink.name(anyString())).thenReturn(dataStreamSink); - kafkaSink.emitDataStream(dataStream); - - } - - -} diff --git a/kafka-base/kafka-base-sink/src/test/java/com/dtstack/flink/sql/sink/kafka/CustomerFlinkPartitionTest.java b/kafka-base/kafka-base-sink/src/test/java/com/dtstack/flink/sql/sink/kafka/CustomerFlinkPartitionTest.java deleted file mode 100644 index 501ba7b5a..000000000 --- a/kafka-base/kafka-base-sink/src/test/java/com/dtstack/flink/sql/sink/kafka/CustomerFlinkPartitionTest.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.dtstack.flink.sql.sink.kafka; - -import com.google.common.collect.Lists; -import org.junit.Test; - -public class CustomerFlinkPartitionTest { - - @Test - public void testCustomerFlinkPartition(){ - CustomerFlinkPartition customerFlinkPartition = new CustomerFlinkPartition(); - customerFlinkPartition.open(1, 1); - int[] partition = new int[1]; - partition[0] = 1; - customerFlinkPartition.partition(null, "key".getBytes(), "value".getBytes(), "topic", partition); - customerFlinkPartition.partition(null, "key".getBytes(), "value".getBytes(), "topic", partition); - customerFlinkPartition.hashCode(); - customerFlinkPartition.equals(customerFlinkPartition); - - } -} diff --git a/kafka-base/kafka-base-sink/src/test/java/com/dtstack/flink/sql/sink/kafka/CustomerKeyedSerializationSchemaTest.java b/kafka-base/kafka-base-sink/src/test/java/com/dtstack/flink/sql/sink/kafka/CustomerKeyedSerializationSchemaTest.java deleted file mode 100644 index 2170d74c6..000000000 --- a/kafka-base/kafka-base-sink/src/test/java/com/dtstack/flink/sql/sink/kafka/CustomerKeyedSerializationSchemaTest.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.dtstack.flink.sql.sink.kafka; - -import com.dtstack.flink.sql.format.SerializationMetricWrapper; -import com.dtstack.flink.sql.sink.kafka.serialization.CustomerKeyedSerializationSchema; -import com.dtstack.flink.sql.sink.kafka.serialization.JsonTupleSerializationSchema; -import com.google.common.collect.Lists; -import org.apache.flink.api.java.tuple.Tuple2; -import org.junit.Test; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class CustomerKeyedSerializationSchemaTest { - - @Test - public void testCustomerKeyedSerializationSchema(){ - SerializationMetricWrapper serializationMetricWrapper = mock(SerializationMetricWrapper.class); - JsonTupleSerializationSchema jsonCRowSerializationSchema = mock(JsonTupleSerializationSchema.class); - when(serializationMetricWrapper.getSerializationSchema()).thenReturn(jsonCRowSerializationSchema); - when(jsonCRowSerializationSchema.serialize(any())).thenReturn("{\"a\":\"n\"}".getBytes()); - CustomerKeyedSerializationSchema customerKeyedSerializationSchema = new CustomerKeyedSerializationSchema(serializationMetricWrapper, Lists.newArrayList("a").toArray(new String[1])); - Tuple2 cRow = mock(Tuple2.class); - customerKeyedSerializationSchema.serializeKey(cRow); - customerKeyedSerializationSchema.getTargetTopic(cRow); - customerKeyedSerializationSchema.serializeValue(cRow); - } -} diff --git a/kafka-base/kafka-base-sink/src/test/java/com/dtstack/flink/sql/sink/kafka/serialization/AvroTuple2SerializationSchemaTest.java b/kafka-base/kafka-base-sink/src/test/java/com/dtstack/flink/sql/sink/kafka/serialization/AvroTuple2SerializationSchemaTest.java deleted file mode 100644 index 72760e12d..000000000 --- a/kafka-base/kafka-base-sink/src/test/java/com/dtstack/flink/sql/sink/kafka/serialization/AvroTuple2SerializationSchemaTest.java +++ /dev/null @@ -1,131 +0,0 @@ -package com.dtstack.flink.sql.sink.kafka.serialization; - -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import org.apache.avro.LogicalTypes; -import org.apache.avro.Schema; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.types.Row; -import org.junit.Before; -import org.junit.Test; -import org.powermock.api.mockito.PowerMockito; - -import java.lang.reflect.Method; -import java.math.BigDecimal; -import java.sql.Date; -import java.sql.Time; -import java.sql.Timestamp; -import java.util.Map; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class AvroTuple2SerializationSchemaTest { - - private AvroTuple2SerializationSchema avroTuple2SerializationSchema; - - @Before - public void init(){ - String schemaString = "{\"type\":\"record\",\"name\":\"MyResult\",\"fields\":[{\"name\":\"channel\",\"type\":\"string\"}]}"; - avroTuple2SerializationSchema = new AvroTuple2SerializationSchema(schemaString,"upsert"); - } - - @Test - public void serialize(){ - Row row = new Row(1); - row.setField(0, "1"); - avroTuple2SerializationSchema.serialize(new Tuple2<>(true, row)); - avroTuple2SerializationSchema.equals(avroTuple2SerializationSchema); - avroTuple2SerializationSchema.equals(null); - } - - @Test - public void convertFlinkType() throws Exception { - Schema schema = PowerMockito.mock(Schema.class); - when(schema.getType()).thenReturn(Schema.Type.RECORD); - Method method = AvroTuple2SerializationSchema.class.getDeclaredMethod("convertFlinkType", Schema.class, Object.class); - method.setAccessible(true); - method.invoke(avroTuple2SerializationSchema,schema, null); - Row row = new Row(1); - row.setField(0, "1"); - when(schema.getFields()).thenReturn(Lists.newArrayList()); - method.invoke(avroTuple2SerializationSchema,schema, row); - - when(schema.getType()).thenReturn(Schema.Type.ENUM); - method.invoke(avroTuple2SerializationSchema,schema, "test"); - - Schema schema1 = mock(Schema.class); - when(schema1.getType()).thenReturn(Schema.Type.ARRAY); - when(schema1.getElementType()).thenReturn(schema); - method.invoke(avroTuple2SerializationSchema,schema, new int[]{1}); - - Schema schema2 = mock(Schema.class); - when(schema2.getType()).thenReturn(Schema.Type.ARRAY); - when(schema2.getValueType()).thenReturn(schema); - Map meta = Maps.newHashMap(); - meta.put("key", "value"); - method.invoke(avroTuple2SerializationSchema,schema, meta); - - when(schema.getType()).thenReturn(Schema.Type.UNION); - when(schema.getTypes()).thenReturn(Lists.newArrayList()); - method.invoke(avroTuple2SerializationSchema,schema, "1".getBytes()); - - when(schema.getType()).thenReturn(Schema.Type.FIXED); - method.invoke(avroTuple2SerializationSchema,schema, "1".getBytes()); - - when(schema.getType()).thenReturn(Schema.Type.STRING); - method.invoke(avroTuple2SerializationSchema,schema, new BigDecimal("1")); - - when(schema.getType()).thenReturn(Schema.Type.BYTES); - method.invoke(avroTuple2SerializationSchema,schema, "1".getBytes()); - - when(schema.getType()).thenReturn(Schema.Type.INT); - method.invoke(avroTuple2SerializationSchema,schema, 1); - - when(schema.getType()).thenReturn(Schema.Type.LONG); - method.invoke(avroTuple2SerializationSchema,schema, 1); - - when(schema.getType()).thenReturn(Schema.Type.BOOLEAN); - method.invoke(avroTuple2SerializationSchema,schema, true); - } - - @Test - public void convertFromDecimal() throws Exception { - Schema schema = PowerMockito.mock(Schema.class); - LogicalTypes.Decimal decimalType = mock(LogicalTypes.Decimal.class); - when(schema.getLogicalType()).thenReturn(decimalType); - when(decimalType.getScale()).thenReturn(1); - Method method = AvroTuple2SerializationSchema.class.getDeclaredMethod("convertFromDecimal", Schema.class, BigDecimal.class); - method.setAccessible(true); - method.invoke(avroTuple2SerializationSchema,schema, new BigDecimal("1")); - } - - @Test - public void convertFromDate() throws Exception { - Schema schema = PowerMockito.mock(Schema.class); - LogicalTypes.Date date = LogicalTypes.date(); - when(schema.getLogicalType()).thenReturn(date); - Method method = AvroTuple2SerializationSchema.class.getDeclaredMethod("convertFromDate", Schema.class, Date.class); - method.setAccessible(true); - method.invoke(avroTuple2SerializationSchema,schema, new Date(System.currentTimeMillis())); - } - @Test - public void convertFromTime() throws Exception { - Schema schema = PowerMockito.mock(Schema.class); - when(schema.getLogicalType()).thenReturn( LogicalTypes.timeMillis()); - LogicalTypes.TimeMillis date = LogicalTypes.timeMillis(); - Method method = AvroTuple2SerializationSchema.class.getDeclaredMethod("convertFromTime", Schema.class, Time.class); - method.setAccessible(true); - method.invoke(avroTuple2SerializationSchema, schema, new Time(System.currentTimeMillis())); - } - @Test - public void convertFromTimestamp() throws Exception { - Schema schema = PowerMockito.mock(Schema.class); - LogicalTypes.TimestampMillis date = LogicalTypes.timestampMillis(); - when(schema.getLogicalType()).thenReturn(date); - Method method = AvroTuple2SerializationSchema.class.getDeclaredMethod("convertFromTimestamp", Schema.class, Timestamp.class); - method.setAccessible(true); - method.invoke(avroTuple2SerializationSchema,schema, new Timestamp(System.currentTimeMillis())); - } - -} diff --git a/kafka-base/kafka-base-sink/src/test/java/com/dtstack/flink/sql/sink/kafka/serialization/CsvTuple2SerializationSchemaTest.java b/kafka-base/kafka-base-sink/src/test/java/com/dtstack/flink/sql/sink/kafka/serialization/CsvTuple2SerializationSchemaTest.java deleted file mode 100644 index c33486b05..000000000 --- a/kafka-base/kafka-base-sink/src/test/java/com/dtstack/flink/sql/sink/kafka/serialization/CsvTuple2SerializationSchemaTest.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.dtstack.flink.sql.sink.kafka.serialization; - -import com.google.common.collect.Lists; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.common.typeinfo.Types; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.api.java.typeutils.TupleTypeInfo; -import org.apache.flink.types.Row; -import org.junit.Test; - -import java.math.BigDecimal; -import java.math.BigInteger; -import java.sql.Time; -import java.sql.Timestamp; -import java.util.List; - -public class CsvTuple2SerializationSchemaTest { - @Test - public void serialize(){ - List fieldNames = Lists.newArrayList("a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q"); - List> information = Lists.newArrayList(Types.VOID, Types.STRING, Types.BOOLEAN, Types.BYTE, - Types.SHORT,Types.INT,Types.LONG,Types.FLOAT, Types.DOUBLE, Types.BIG_DEC, Types.BIG_INT, - Types.SQL_DATE,Types.SQL_TIME, Types.SQL_TIMESTAMP, Types.ROW_NAMED(new String[]{"a"}, Types.STRING), - Types.OBJECT_ARRAY(Types.BOOLEAN), Types.OBJECT_ARRAY(Types.STRING)); - TypeInformation> typeInformation = - new TupleTypeInfo<>(org.apache.flink.table.api.Types.BOOLEAN(), new RowTypeInfo(information.toArray(new TypeInformation[13]), fieldNames.toArray(new String[13]))); - - - CsvTupleSerializationSchema csvTupleSerializationSchema = new CsvTupleSerializationSchema.Builder(typeInformation) - .setFieldDelimiter(',') - .setUpdateMode("upsert") - .setArrayElementDelimiter(",") - .setEscapeCharacter(',') - .setLineDelimiter("\n") - .setNullLiteral("") - .setQuoteCharacter('\'') - .build(); - Row row = new Row(17); - row.setField(0, "a"); - row.setField(1, "s"); - row.setField(2, true); - row.setField(3, Byte.valueOf("1")); - row.setField(4, new Short("1")); - row.setField(5, 1); - row.setField(6, 1L); - row.setField(7, 1f); - row.setField(8, 1d); - row.setField(9, new BigDecimal("1")); - row.setField(10, new BigInteger("1")); - row.setField(11, "2020"); - row.setField(12, new Time(System.currentTimeMillis())); - row.setField(13, new Timestamp(System.currentTimeMillis())); - Row rowNest = new Row(1); - rowNest.setField(0, "a"); - row.setField(14, rowNest); - row.setField(15, new Boolean[]{false}); - row.setField(16, new String[]{"a"}); - csvTupleSerializationSchema.serialize(new Tuple2<>(false, row)); - - } -} diff --git a/kafka-base/kafka-base-sink/src/test/java/com/dtstack/flink/sql/sink/kafka/serialization/DTJsonRowSerializationSchemaTest.java b/kafka-base/kafka-base-sink/src/test/java/com/dtstack/flink/sql/sink/kafka/serialization/DTJsonRowSerializationSchemaTest.java deleted file mode 100644 index e225ba08f..000000000 --- a/kafka-base/kafka-base-sink/src/test/java/com/dtstack/flink/sql/sink/kafka/serialization/DTJsonRowSerializationSchemaTest.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.dtstack.flink.sql.sink.kafka.serialization; - -import com.google.common.collect.Lists; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.common.typeinfo.Types; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.types.Row; -import org.junit.Test; - -import java.math.BigDecimal; -import java.math.BigInteger; -import java.sql.Time; -import java.sql.Timestamp; -import java.util.List; - -public class DTJsonRowSerializationSchemaTest { - - @Test - public void serialize(){ - List fieldNames = Lists.newArrayList("a","b","c","d","e","f","g","h","i","j","k","l","m"); - List typeInformations = Lists.newArrayList(Types.VOID, Types.BOOLEAN, Types.STRING, Types.BIG_DEC, - Types.BIG_INT,Types.SQL_DATE,Types.SQL_TIME, Types.SQL_TIMESTAMP, Types.ROW_NAMED(new String[]{"a"}, - new TypeInformation[]{Types.STRING}), Types.OBJECT_ARRAY(Types.BOOLEAN), Types.OBJECT_ARRAY(Types.STRING), - Types.PRIMITIVE_ARRAY(Types.BYTE), Types.INSTANT); - RowTypeInfo typeInformation = new RowTypeInfo(typeInformations.toArray(new TypeInformation[13]), fieldNames.toArray(new String[13])); - DTJsonRowSerializationSchema jsonCRowSerializationSchema = new DTJsonRowSerializationSchema(typeInformation); - Row row = new Row(13); - row.setField(0, "a"); - row.setField(1, true); - row.setField(2, "str"); - row.setField(3, new BigDecimal("1")); - row.setField(4, new BigInteger("1")); - row.setField(5, "2020"); - row.setField(6, new Time(System.currentTimeMillis())); - row.setField(7, new Timestamp(System.currentTimeMillis())); - Row rowNest = new Row(1); - rowNest.setField(0, "a"); - row.setField(8, rowNest); - row.setField(9, new Boolean[]{false}); - row.setField(10, new String[]{"a"}); - row.setField(11, new byte[]{1}); - row.setField(12, ""); - jsonCRowSerializationSchema.serialize(row); - } -} diff --git a/kafka-base/kafka-base-sink/src/test/java/com/dtstack/flink/sql/sink/kafka/serialization/JsonTuple2SerializationSchemaTest.java b/kafka-base/kafka-base-sink/src/test/java/com/dtstack/flink/sql/sink/kafka/serialization/JsonTuple2SerializationSchemaTest.java deleted file mode 100644 index 41fc070bc..000000000 --- a/kafka-base/kafka-base-sink/src/test/java/com/dtstack/flink/sql/sink/kafka/serialization/JsonTuple2SerializationSchemaTest.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.dtstack.flink.sql.sink.kafka.serialization; - -import com.google.common.collect.Lists; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.common.typeinfo.Types; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.api.java.typeutils.TupleTypeInfo; -import org.apache.flink.types.Row; -import org.junit.Test; - -import java.math.BigDecimal; -import java.math.BigInteger; -import java.sql.Time; -import java.sql.Timestamp; -import java.util.List; - -public class JsonTuple2SerializationSchemaTest { - - @Test - public void serialize(){ - List fieldNames = Lists.newArrayList("a","b","c","d","e","f","g","h","i","j","k","l","m"); - List> information = Lists.newArrayList(Types.VOID, Types.BOOLEAN, Types.STRING, Types.BIG_DEC, - Types.BIG_INT,Types.SQL_DATE,Types.SQL_TIME, Types.SQL_TIMESTAMP, Types.ROW_NAMED(new String[]{"a"}, - Types.STRING), Types.OBJECT_ARRAY(Types.BOOLEAN), Types.OBJECT_ARRAY(Types.STRING), - Types.PRIMITIVE_ARRAY(Types.BOOLEAN), Types.INSTANT); - TypeInformation typeInformation = new TupleTypeInfo(org.apache.flink.table.api.Types.BOOLEAN(), new RowTypeInfo(information.toArray(new TypeInformation[13]), fieldNames.toArray(new String[13]))); - JsonTupleSerializationSchema jsonCRowSerializationSchema = new JsonTupleSerializationSchema(typeInformation, "upsert"); - Row row = new Row(13); - row.setField(0, "a"); - row.setField(1, true); - row.setField(2, "str"); - row.setField(3, new BigDecimal("1")); - row.setField(4, new BigInteger("1")); - row.setField(5, "2020"); - row.setField(6, new Time(System.currentTimeMillis())); - row.setField(7, new Timestamp(System.currentTimeMillis())); - Row rowNest = new Row(1); - rowNest.setField(0, "a"); - row.setField(8, rowNest); - row.setField(9, new Boolean[]{false}); - row.setField(10, new String[]{"a"}); - row.setField(11, new byte[]{1}); - row.setField(12, ""); - jsonCRowSerializationSchema.serialize(new Tuple2<>(true, row)); - } -} diff --git a/kafka-base/kafka-base-sink/src/test/java/com/dtstack/flink/sql/sink/kafka/table/KafkaSinkParserTest.java b/kafka-base/kafka-base-sink/src/test/java/com/dtstack/flink/sql/sink/kafka/table/KafkaSinkParserTest.java deleted file mode 100644 index d38bc2d56..000000000 --- a/kafka-base/kafka-base-sink/src/test/java/com/dtstack/flink/sql/sink/kafka/table/KafkaSinkParserTest.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.dtstack.flink.sql.sink.kafka.table; - -import com.google.common.collect.Maps; -import org.junit.Test; - -import java.util.Map; - -public class KafkaSinkParserTest { - - @Test - public void getTableInfo(){ - KafkaSinkParser kafkaSinkParser = new KafkaSinkParser(); - Map prop = Maps.newHashMap(); - prop.put(KafkaSinkTableInfo.TYPE_KEY.toLowerCase(), "kafka"); - prop.put(KafkaSinkTableInfo.SINK_DATA_TYPE.toLowerCase(), "json"); - prop.put(KafkaSinkTableInfo.SCHEMA_STRING_KEY.toLowerCase(), "kafka"); - prop.put(KafkaSinkTableInfo.CSV_FIELD_DELIMITER_KEY.toLowerCase(), "kafka"); - prop.put(KafkaSinkTableInfo.BOOTSTRAPSERVERS_KEY.toLowerCase(), "kafka"); - prop.put(KafkaSinkTableInfo.TOPIC_KEY.toLowerCase(), "kafka"); - prop.put(KafkaSinkTableInfo.ENABLE_KEY_PARTITION_KEY.toLowerCase(), "kafka"); - prop.put(KafkaSinkTableInfo.PARALLELISM_KEY.toLowerCase(), "1"); - prop.put("kafka.test", "1"); - kafkaSinkParser.getTableInfo("tablea", "a varchar as a", prop); - } -} diff --git a/kafka-base/kafka-base-sink/src/test/java/com/dtstack/flink/sql/sink/kafka/table/KafkaSinkTableInfoTest.java b/kafka-base/kafka-base-sink/src/test/java/com/dtstack/flink/sql/sink/kafka/table/KafkaSinkTableInfoTest.java deleted file mode 100644 index 20acc0aca..000000000 --- a/kafka-base/kafka-base-sink/src/test/java/com/dtstack/flink/sql/sink/kafka/table/KafkaSinkTableInfoTest.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.dtstack.flink.sql.sink.kafka.table; - -import org.junit.Test; - -public class KafkaSinkTableInfoTest { - - @Test - public void testKafkaSinkTableInfo(){ - KafkaSinkTableInfo kafkaSinkTableInfo = new KafkaSinkTableInfo(); - kafkaSinkTableInfo.setType("kafka"); - kafkaSinkTableInfo.setTopic("a"); - kafkaSinkTableInfo.setBootstrapServers("localhost:9092"); - kafkaSinkTableInfo.setSinkDataType("avro"); - kafkaSinkTableInfo.setUpdateMode("append"); - kafkaSinkTableInfo.setSchemaString("{\"name\":\"channel\",\"type\":\"string\"}"); - kafkaSinkTableInfo.check(); - } -} diff --git a/kafka-base/kafka-base-source/pom.xml b/kafka-base/kafka-base-source/pom.xml deleted file mode 100644 index 6ea439645..000000000 --- a/kafka-base/kafka-base-source/pom.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - 4.0.0 - - sql.kafka-base - com.dtstack.flink - 1.0-SNAPSHOT - ../pom.xml - - - sql.source.kafka-base - kafka-base-source - - jar - http://maven.apache.org - - diff --git a/kafka-base/kafka-base-source/src/main/java/com/dtstack/flink/sql/source/kafka/AbstractKafkaConsumerFactory.java b/kafka-base/kafka-base-source/src/main/java/com/dtstack/flink/sql/source/kafka/AbstractKafkaConsumerFactory.java deleted file mode 100644 index 67c9af0ed..000000000 --- a/kafka-base/kafka-base-source/src/main/java/com/dtstack/flink/sql/source/kafka/AbstractKafkaConsumerFactory.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.source.kafka; - -import com.dtstack.flink.sql.dirtyManager.manager.DirtyDataManager; -import com.dtstack.flink.sql.format.DeserializationMetricWrapper; -import com.dtstack.flink.sql.source.kafka.deserialization.DeserializationSchemaFactory; -import com.dtstack.flink.sql.source.kafka.deserialization.KafkaDeserializationMetricWrapper; -import com.dtstack.flink.sql.source.kafka.table.KafkaSourceTableInfo; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumerBase; -import org.apache.flink.types.Row; - -import java.util.Properties; - -/** - * - * company: www.dtstack.com - * @author: toutian - * create: 2019/12/24 - */ -public abstract class AbstractKafkaConsumerFactory { - - protected abstract FlinkKafkaConsumerBase createKafkaTableSource(KafkaSourceTableInfo kafkaSourceTableInfo, - TypeInformation typeInformation, - Properties props); - - protected DeserializationMetricWrapper createDeserializationMetricWrapper(KafkaSourceTableInfo kafkaSourceTableInfo, - TypeInformation typeInformation, - Calculate calculate) { - return new KafkaDeserializationMetricWrapper(typeInformation, - DeserializationSchemaFactory.createDeserializationSchema(kafkaSourceTableInfo, typeInformation), - calculate, - DirtyDataManager.newInstance(kafkaSourceTableInfo.getDirtyProperties())); - } -} diff --git a/kafka-base/kafka-base-source/src/main/java/com/dtstack/flink/sql/source/kafka/AbstractKafkaSource.java b/kafka-base/kafka-base-source/src/main/java/com/dtstack/flink/sql/source/kafka/AbstractKafkaSource.java deleted file mode 100644 index 5da533b42..000000000 --- a/kafka-base/kafka-base-source/src/main/java/com/dtstack/flink/sql/source/kafka/AbstractKafkaSource.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.source.kafka; - -import com.dtstack.flink.sql.source.IStreamSourceGener; -import com.dtstack.flink.sql.source.kafka.enums.EKafkaOffset; -import com.dtstack.flink.sql.source.kafka.table.KafkaSourceTableInfo; -import com.dtstack.flink.sql.util.DataTypeUtils; -import com.dtstack.flink.sql.util.DtStringUtil; -import com.dtstack.flink.sql.util.PluginUtil; -import org.apache.commons.lang3.StringUtils; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.streaming.api.datastream.DataStreamSource; -import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumerBase; -import org.apache.flink.streaming.connectors.kafka.internals.KafkaTopicPartition; -import org.apache.flink.table.api.Table; -import org.apache.flink.types.Row; -import org.apache.kafka.clients.consumer.ConsumerConfig; - -import java.util.Map; -import java.util.Properties; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - -/** - * Date: 2020/3/20 - * Company: www.dtstack.com - * @author maqi - */ -public abstract class AbstractKafkaSource implements IStreamSourceGener

{ - - private static final String SOURCE_OPERATOR_NAME_TPL = "${topic}_${table}"; - - protected Properties getKafkaProperties(KafkaSourceTableInfo kafkaSourceTableInfo) { - Properties props = new Properties(); - props.setProperty(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, kafkaSourceTableInfo.getBootstrapServers()); - - if (DtStringUtil.isJson(kafkaSourceTableInfo.getOffsetReset())) { - props.setProperty(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, EKafkaOffset.NONE.name().toLowerCase()); - } else if(StringUtils.equalsIgnoreCase(EKafkaOffset.TIMESTAMP.name().toLowerCase(), kafkaSourceTableInfo.getOffsetReset())){ - props.setProperty(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, EKafkaOffset.EARLIEST.name().toLowerCase()); - } else { - props.setProperty(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, kafkaSourceTableInfo.getOffsetReset()); - } - - if (StringUtils.isNotBlank(kafkaSourceTableInfo.getGroupId())) { - props.setProperty(ConsumerConfig.GROUP_ID_CONFIG, kafkaSourceTableInfo.getGroupId()); - } - if("kafka".equalsIgnoreCase(kafkaSourceTableInfo.getType())){ - String keyDeserializer = kafkaSourceTableInfo.getKafkaParam(KafkaSourceTableInfo.KEY_DESERIALIZER); - if(StringUtils.isNotBlank(keyDeserializer)){ - kafkaSourceTableInfo.putKafkaParam(KafkaSourceTableInfo.KEY_DESERIALIZER, KafkaSourceTableInfo.DT_DESERIALIZER_CLASS_NAME); - kafkaSourceTableInfo.putKafkaParam(KafkaSourceTableInfo.DT_KEY_DESERIALIZER, keyDeserializer); - } - String valueDeserializer = kafkaSourceTableInfo.getKafkaParam(KafkaSourceTableInfo.VALUE_DESERIALIZER); - if(StringUtils.isNotBlank(valueDeserializer)){ - kafkaSourceTableInfo.putKafkaParam(KafkaSourceTableInfo.VALUE_DESERIALIZER, KafkaSourceTableInfo.DT_DESERIALIZER_CLASS_NAME); - kafkaSourceTableInfo.putKafkaParam(KafkaSourceTableInfo.DT_VALUE_DESERIALIZER, valueDeserializer); - } - } - for (String key : kafkaSourceTableInfo.getKafkaParamKeys()) { - props.setProperty(key, kafkaSourceTableInfo.getKafkaParam(key)); - } - return props; - } - - protected String generateOperatorName(String tabName, String topicName) { - return SOURCE_OPERATOR_NAME_TPL.replace("${topic}", topicName).replace("${table}", tabName); - } - - protected TypeInformation getRowTypeInformation(KafkaSourceTableInfo kafkaSourceTableInfo) { - String[] fieldTypes = kafkaSourceTableInfo.getFieldTypes(); - Class[] fieldClasses = kafkaSourceTableInfo.getFieldClasses(); - TypeInformation[] types = - IntStream.range(0, fieldClasses.length) - .mapToObj(i -> { - if (fieldClasses[i].isArray()) { - return DataTypeUtils.convertToArray(fieldTypes[i]); - } - return TypeInformation.of(fieldClasses[i]); - }) - .toArray(TypeInformation[]::new); - - - return new RowTypeInfo(types, kafkaSourceTableInfo.getFields()); - } - - protected void setParallelism(Integer parallelism, DataStreamSource kafkaSource) { - if (parallelism > 0) { - kafkaSource.setParallelism(parallelism); - } - } - - protected void setStartPosition(String offset, String topicName, FlinkKafkaConsumerBase kafkaSrc, Runnable runnable) { - if (StringUtils.equalsIgnoreCase(offset, EKafkaOffset.EARLIEST.name())) { - kafkaSrc.setStartFromEarliest(); - } else if(StringUtils.equalsIgnoreCase(offset, EKafkaOffset.TIMESTAMP.name())) { - runnable.run(); - }else if (DtStringUtil.isJson(offset)) { - Map specificStartupOffsets = buildOffsetMap(offset, topicName); - kafkaSrc.setStartFromSpecificOffsets(specificStartupOffsets); - } else { - kafkaSrc.setStartFromLatest(); - } - } - - /** - * kafka offset,eg.. {"0":12312,"1":12321,"2":12312} - * @param offsetJson - * @param topicName - * @return - */ - protected Map buildOffsetMap(String offsetJson, String topicName) { - try { - Properties properties = PluginUtil.jsonStrToObject(offsetJson, Properties.class); - Map offsetMap = PluginUtil.objectToMap(properties); - Map specificStartupOffsets = offsetMap - .entrySet() - .stream() - .collect(Collectors.toMap( - (Map.Entry entry) -> new KafkaTopicPartition(topicName, Integer.valueOf(entry.getKey())), - (Map.Entry entry) -> Long.valueOf(entry.getValue().toString())) - ); - - return specificStartupOffsets; - } catch (Exception e) { - throw new RuntimeException("not support offsetReset type:" + offsetJson); - } - } - -} diff --git a/kafka-base/kafka-base-source/src/main/java/com/dtstack/flink/sql/source/kafka/deserialization/DeserializationSchemaFactory.java b/kafka-base/kafka-base-source/src/main/java/com/dtstack/flink/sql/source/kafka/deserialization/DeserializationSchemaFactory.java deleted file mode 100644 index d5bd99b4a..000000000 --- a/kafka-base/kafka-base-source/src/main/java/com/dtstack/flink/sql/source/kafka/deserialization/DeserializationSchemaFactory.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.source.kafka.deserialization; - -import com.dtstack.flink.sql.format.FormatType; -import com.dtstack.flink.sql.format.dtnest.DtNestRowDeserializationSchema; -import com.dtstack.flink.sql.source.kafka.table.KafkaSourceTableInfo; -import org.apache.commons.lang3.StringUtils; -import org.apache.flink.api.common.serialization.DeserializationSchema; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.formats.avro.AvroRowDeserializationSchema; -import org.apache.flink.formats.csv.CsvRowDeserializationSchema; -import org.apache.flink.formats.json.DTJsonRowDeserializationSchema; -import org.apache.flink.types.Row; - -/** - * Date: 2021/05/25 Company: www.dtstack.com - * - * @author tiezhu - */ -public class DeserializationSchemaFactory { - - public static DeserializationSchema createDeserializationSchema( - KafkaSourceTableInfo kafkaSourceTableInfo, TypeInformation typeInformation) { - DeserializationSchema deserializationSchema = null; - if (FormatType.DT_NEST.name().equalsIgnoreCase(kafkaSourceTableInfo.getSourceDataType())) { - deserializationSchema = - new DtNestRowDeserializationSchema( - typeInformation, - kafkaSourceTableInfo.getPhysicalFields(), - kafkaSourceTableInfo.getFieldExtraInfoList(), - kafkaSourceTableInfo.getCharsetName()); - } else if (FormatType.JSON - .name() - .equalsIgnoreCase(kafkaSourceTableInfo.getSourceDataType())) { - - if (StringUtils.isNotBlank(kafkaSourceTableInfo.getSchemaString())) { - deserializationSchema = - new DTJsonRowDeserializationSchema(kafkaSourceTableInfo.getSchemaString()); - } else if (typeInformation != null && typeInformation.getArity() != 0) { - deserializationSchema = new DTJsonRowDeserializationSchema(typeInformation); - } else { - throw new IllegalArgumentException( - "sourceDataType:" - + FormatType.JSON.name() - + " must set schemaString(JSON Schema)or TypeInformation"); - } - - } else if (FormatType.CSV - .name() - .equalsIgnoreCase(kafkaSourceTableInfo.getSourceDataType())) { - - if (StringUtils.isBlank(kafkaSourceTableInfo.getFieldDelimiter())) { - throw new IllegalArgumentException( - "sourceDataType:" + FormatType.CSV.name() + " must set fieldDelimiter"); - } - - final CsvRowDeserializationSchema.Builder deserSchemaBuilder = - new CsvRowDeserializationSchema.Builder(typeInformation); - deserSchemaBuilder.setFieldDelimiter( - kafkaSourceTableInfo.getFieldDelimiter().toCharArray()[0]); - deserializationSchema = deserSchemaBuilder.build(); - - } else if (FormatType.AVRO - .name() - .equalsIgnoreCase(kafkaSourceTableInfo.getSourceDataType())) { - - if (StringUtils.isBlank(kafkaSourceTableInfo.getSchemaString())) { - throw new IllegalArgumentException( - "sourceDataType:" + FormatType.AVRO.name() + " must set schemaString"); - } - - deserializationSchema = - new AvroRowDeserializationSchema(kafkaSourceTableInfo.getSchemaString()); - } - - if (null == deserializationSchema) { - throw new UnsupportedOperationException( - "FormatType:" + kafkaSourceTableInfo.getSourceDataType()); - } - - return deserializationSchema; - } -} diff --git a/kafka-base/kafka-base-source/src/main/java/com/dtstack/flink/sql/source/kafka/deserialization/DtKafkaDeserializationSchemaWrapper.java b/kafka-base/kafka-base-source/src/main/java/com/dtstack/flink/sql/source/kafka/deserialization/DtKafkaDeserializationSchemaWrapper.java deleted file mode 100644 index 8aad14057..000000000 --- a/kafka-base/kafka-base-source/src/main/java/com/dtstack/flink/sql/source/kafka/deserialization/DtKafkaDeserializationSchemaWrapper.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.source.kafka.deserialization; - -import com.dtstack.flink.sql.source.kafka.sample.OffsetMap; -import org.apache.flink.api.common.serialization.DeserializationSchema; -import org.apache.flink.streaming.connectors.kafka.internals.KafkaDeserializationSchemaWrapper; -import org.apache.flink.streaming.connectors.kafka.internals.KafkaTopicPartition; -import org.apache.kafka.clients.consumer.ConsumerRecord; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * @author tiezhu - * @date 2021/4/26 - * Company dtstack - */ -public class DtKafkaDeserializationSchemaWrapper extends KafkaDeserializationSchemaWrapper { - - private final List endPartition = new ArrayList<>(); - - private Map specificEndOffsets; - - public DtKafkaDeserializationSchemaWrapper(DeserializationSchema deserializationSchema) { - super(deserializationSchema); - } - - public void setSpecificEndOffsets(OffsetMap offsetMap) { - Map latest = offsetMap.getLatest(); - Map earliest = offsetMap.getEarliest(); - - this.specificEndOffsets = new HashMap<>(latest); - - // 除去没有数据的分区,避免任务一直等待分区数据 - latest.keySet().forEach( - partition -> { - if (latest.get(partition).equals(earliest.get(partition))) { - specificEndOffsets.remove(partition); - } - } - ); - } - - @Override - public T deserialize(ConsumerRecord record) throws Exception { - KafkaTopicPartition topicPartition = new KafkaTopicPartition(record.topic(), record.partition()); - if (endPartition.contains(record.partition())) { - return null; - } - if (specificEndOffsets != null && !specificEndOffsets.isEmpty()) { - Long endOffset = specificEndOffsets.get(topicPartition); - if (endOffset != null && record.offset() >= endOffset - 1) { - endPartition.add(record.partition()); - return super.deserialize(record); - } - } - - return super.deserialize(record); - } - - public boolean isEndOfStream(T nextElement) { - boolean isEnd = - specificEndOffsets != null - && !specificEndOffsets.isEmpty() - && endPartition.size() == specificEndOffsets.size(); - return super.isEndOfStream(nextElement) || isEnd; - } -} diff --git a/kafka-base/kafka-base-source/src/main/java/com/dtstack/flink/sql/source/kafka/deserialization/KafkaDeserializationMetricWrapper.java b/kafka-base/kafka-base-source/src/main/java/com/dtstack/flink/sql/source/kafka/deserialization/KafkaDeserializationMetricWrapper.java deleted file mode 100644 index 692991c9c..000000000 --- a/kafka-base/kafka-base-source/src/main/java/com/dtstack/flink/sql/source/kafka/deserialization/KafkaDeserializationMetricWrapper.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.source.kafka.deserialization; - -import com.dtstack.flink.sql.dirtyManager.manager.DirtyDataManager; -import com.dtstack.flink.sql.format.DeserializationMetricWrapper; -import com.dtstack.flink.sql.source.kafka.Calculate; -import com.dtstack.flink.sql.util.ReflectionUtils; -import org.apache.flink.api.common.serialization.DeserializationSchema; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.metrics.Gauge; -import org.apache.flink.metrics.MetricGroup; -import org.apache.flink.streaming.connectors.kafka.internal.KafkaConsumerThread; -import org.apache.flink.streaming.connectors.kafka.internals.AbstractFetcher; -import org.apache.flink.streaming.connectors.kafka.internals.KafkaTopicPartition; -import org.apache.flink.streaming.connectors.kafka.internals.KafkaTopicPartitionState; -import org.apache.flink.types.Row; -import org.apache.kafka.clients.consumer.KafkaConsumer; -import org.apache.kafka.clients.consumer.internals.SubscriptionState; -import org.apache.kafka.common.TopicPartition; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.lang.reflect.Field; -import java.util.List; - -import static com.dtstack.flink.sql.metric.MetricConstant.DT_PARTITION_GROUP; -import static com.dtstack.flink.sql.metric.MetricConstant.DT_TOPIC_GROUP; -import static com.dtstack.flink.sql.metric.MetricConstant.DT_TOPIC_PARTITION_LAG_GAUGE; - -/** - * add metric for source - *

- * company: www.dtstack.com - * @author: toutian - * create: 2019/12/24 - */ -public class KafkaDeserializationMetricWrapper extends DeserializationMetricWrapper { - - private static final Logger LOG = LoggerFactory.getLogger(KafkaDeserializationMetricWrapper.class); - - private final Calculate calculate; - - public KafkaDeserializationMetricWrapper( - TypeInformation typeInfo, - DeserializationSchema deserializationSchema, - Calculate calculate, - DirtyDataManager dirtyDataManager) { - super(typeInfo, deserializationSchema, dirtyDataManager); - this.calculate = calculate; - } - - protected void registerPtMetric(AbstractFetcher fetcher) throws Exception { - Field consumerThreadField = ReflectionUtils.getDeclaredField(fetcher, "consumerThread"); - consumerThreadField.setAccessible(true); - KafkaConsumerThread consumerThread = (KafkaConsumerThread) consumerThreadField.get(fetcher); - - Field hasAssignedPartitionsField = consumerThread.getClass().getDeclaredField("hasAssignedPartitions"); - hasAssignedPartitionsField.setAccessible(true); - - // get subtask unassigned kafka topic partition - Field subscribedPartitionStatesField = ReflectionUtils.getDeclaredField(fetcher, "subscribedPartitionStates"); - subscribedPartitionStatesField.setAccessible(true); - List> subscribedPartitionStates = (List>) subscribedPartitionStatesField.get(fetcher); - - // init partition lag metric - for (KafkaTopicPartitionState kafkaTopicPartitionState : subscribedPartitionStates) { - KafkaTopicPartition kafkaTopicPartition = kafkaTopicPartitionState.getKafkaTopicPartition(); - MetricGroup topicMetricGroup = getRuntimeContext().getMetricGroup().addGroup(DT_TOPIC_GROUP, kafkaTopicPartition.getTopic()); - - MetricGroup metricGroup = topicMetricGroup.addGroup(DT_PARTITION_GROUP, kafkaTopicPartition.getPartition() + ""); - metricGroup.gauge(DT_TOPIC_PARTITION_LAG_GAUGE, new Gauge() { - // tmp variable - boolean initLag = true; - int partitionIndex; - SubscriptionState subscriptionState; - TopicPartition topicPartition; - - @Override - public Long getValue() { - // first time register metrics - if (initLag) { - partitionIndex = kafkaTopicPartition.getPartition(); - initLag = false; - return -1L; - } - // when kafka topic partition assigned calc metrics - if (subscriptionState == null) { - try { - Field consumerField = consumerThread.getClass().getDeclaredField("consumer"); - consumerField.setAccessible(true); - - KafkaConsumer kafkaConsumer = (KafkaConsumer) consumerField.get(consumerThread); - Field subscriptionStateField = kafkaConsumer.getClass().getDeclaredField("subscriptions"); - subscriptionStateField.setAccessible(true); - - boolean hasAssignedPartitions = (boolean) hasAssignedPartitionsField.get(consumerThread); - - if (!hasAssignedPartitions) { - LOG.error("wait 50 secs, but not assignedPartitions"); - } - - subscriptionState = (SubscriptionState) subscriptionStateField.get(kafkaConsumer); - - topicPartition = subscriptionState - .assignedPartitions() - .stream() - .filter(x -> x.partition() == partitionIndex) - .findFirst() - .get(); - - } catch (Exception e) { - LOG.error(e.getMessage()); - } - return -1L; - } else { - return calculate.calc(subscriptionState, topicPartition); - } - } - }); - } - } - - public void setFetcher(AbstractFetcher fetcher) { - try { - registerPtMetric(fetcher); - } catch (Exception e) { - LOG.error("register topic partition metric error.", e); - } - } -} diff --git a/kafka-base/kafka-base-source/src/main/java/com/dtstack/flink/sql/source/kafka/enums/EKafkaOffset.java b/kafka-base/kafka-base-source/src/main/java/com/dtstack/flink/sql/source/kafka/enums/EKafkaOffset.java deleted file mode 100644 index 6f2dde571..000000000 --- a/kafka-base/kafka-base-source/src/main/java/com/dtstack/flink/sql/source/kafka/enums/EKafkaOffset.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.source.kafka.enums; - -/** - * Date: 2020/3/20 - * Company: www.dtstack.com - * @author maqi - */ -public enum EKafkaOffset { - - LATEST, - EARLIEST, - TIMESTAMP, - NONE -} diff --git a/kafka-base/kafka-base-source/src/main/java/com/dtstack/flink/sql/source/kafka/sample/OffsetFetcher.java b/kafka-base/kafka-base-source/src/main/java/com/dtstack/flink/sql/source/kafka/sample/OffsetFetcher.java deleted file mode 100644 index 5891b8747..000000000 --- a/kafka-base/kafka-base-source/src/main/java/com/dtstack/flink/sql/source/kafka/sample/OffsetFetcher.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.source.kafka.sample; - -import com.dtstack.flink.sql.source.kafka.throwable.KafkaSamplingUnavailableException; -import org.apache.flink.streaming.connectors.kafka.internals.KafkaTopicPartition; -import org.apache.kafka.clients.consumer.ConsumerConfig; -import org.apache.kafka.clients.consumer.KafkaConsumer; -import org.apache.kafka.common.serialization.ByteArrayDeserializer; - -import java.util.Map; -import java.util.Properties; - -/** - * @author tiezhu - * @since 2021/6/15 星期二 - */ -public interface OffsetFetcher { - - OffsetMap fetchOffset(KafkaConsumer consumer, String topic); - - default OffsetMap seekOffset(Properties props, String topic) { - - setByteDeserializer(props); - - try (KafkaConsumer consumer = new KafkaConsumer<>(props)) { - OffsetMap offsetMap = fetchOffset(consumer, topic); - - judgeKafkaSampleIsAvailable(offsetMap, topic); - - return offsetMap; - } - } - - /** - * Judge whether there is data for consumption in each partition in Kafka. If there is no data - * consumption in all partitions, then this sampling task is not available - * - * @param offsetMap offset map - */ - default void judgeKafkaSampleIsAvailable(OffsetMap offsetMap, String topic) { - boolean kafkaSampleIsAvailable = false; - Map latest = offsetMap.getLatest(); - Map earliest = offsetMap.getEarliest(); - - for (KafkaTopicPartition partition : latest.keySet()) { - Long earliestOffset = earliest.get(partition); - Long latestOffset = latest.get(partition); - - if (!latestOffset.equals(earliestOffset)) { - kafkaSampleIsAvailable = true; - } - } - - if (!kafkaSampleIsAvailable) { - throw new KafkaSamplingUnavailableException( - String.format( - "Kafka sampling of [%s] is unavailable because there is no data in all partitions", - topic)); - } - } - - /** - * Makes sure that the ByteArrayDeserializer is registered in the Kafka properties. - * - * @param props The Kafka properties to register the serializer in. - */ - default void setByteDeserializer(Properties props) { - - final String deSerName = ByteArrayDeserializer.class.getName(); - - props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, deSerName); - props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, deSerName); - } -} diff --git a/kafka-base/kafka-base-source/src/main/java/com/dtstack/flink/sql/source/kafka/sample/OffsetMap.java b/kafka-base/kafka-base-source/src/main/java/com/dtstack/flink/sql/source/kafka/sample/OffsetMap.java deleted file mode 100644 index 8ce8ef984..000000000 --- a/kafka-base/kafka-base-source/src/main/java/com/dtstack/flink/sql/source/kafka/sample/OffsetMap.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.source.kafka.sample; - -import org.apache.flink.streaming.connectors.kafka.internals.KafkaTopicPartition; - -import java.io.Serializable; -import java.util.HashMap; -import java.util.Map; - -/** - * @author tiezhu - * @since 2021/6/16 星期三 - */ -public class OffsetMap implements Serializable { - - private static final long serialVersionUID = 1L; - - /** latest offset of kafka */ - private Map latest = new HashMap<>(); - - /** earliest offset of kafka */ - private Map earliest = new HashMap<>(); - - public void setLatest(Map latest) { - this.latest = latest; - } - - public void setEarliest(Map earliest) { - this.earliest = earliest; - } - - public Long getEarliestOffset(KafkaTopicPartition partition) { - return earliest.get(partition); - } - - public Long getLatestOffset(KafkaTopicPartition partition) { - return latest.get(partition); - } - - public void setLatest(KafkaTopicPartition partition, Long offset) { - latest.put(partition, offset); - } - - public void setEarliest(KafkaTopicPartition partition, Long offset) { - earliest.put(partition, offset); - } - - public Map getLatest() { - return latest; - } - - public Map getEarliest() { - return earliest; - } - - public Long getDifference(KafkaTopicPartition partition) { - return getLatestOffset(partition) - getEarliestOffset(partition); - } -} diff --git a/kafka-base/kafka-base-source/src/main/java/com/dtstack/flink/sql/source/kafka/sample/SampleCalculateHelper.java b/kafka-base/kafka-base-source/src/main/java/com/dtstack/flink/sql/source/kafka/sample/SampleCalculateHelper.java deleted file mode 100644 index 090dd9b00..000000000 --- a/kafka-base/kafka-base-source/src/main/java/com/dtstack/flink/sql/source/kafka/sample/SampleCalculateHelper.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.source.kafka.sample; - -import org.apache.flink.streaming.connectors.kafka.internals.KafkaTopicPartition; - -import java.util.HashMap; -import java.util.Map; - -/** - * Date: 2021/05/25 Company: www.dtstack.com - * - * @author tiezhu - */ -public class SampleCalculateHelper { - - /** 根据获取的 begin-offset 和 end-offset 来重新规划 */ - public static Map rebuildAssignedPartitionsWithInitialOffsets( - OffsetMap offsetMap, - Long sampleSize, - Map assignedPartitionsWithInitialOffsets) { - - Map latest = offsetMap.getLatest(); - Map earliest = offsetMap.getEarliest(); - Map resetOffsets = new HashMap<>(); - - Map sampleOfEachPartition = - calculateSampleSizeOfEachPartition(sampleSize, offsetMap); - - for (KafkaTopicPartition partition : assignedPartitionsWithInitialOffsets.keySet()) { - Long earliestOffset = earliest.get(partition); - Long latestOffset = latest.get(partition); - // 判断当前kafka 可消费数是否满足 样本大小sampleSize - Long sampleOfCurrentPartition = sampleOfEachPartition.get(partition); - - if (offsetMap.getDifference(partition) >= sampleOfCurrentPartition) { - resetOffsets.put(partition, latestOffset - sampleOfCurrentPartition - 1); - } else { - resetOffsets.put(partition, earliestOffset - 1); - } - } - - return resetOffsets; - } - - /** - * Calculate the sample size. - * - * @param sampleSize sample size - * @param offsetMap offset map - * @return the map of partition and sample size - */ - private static Map calculateSampleSizeOfEachPartition( - Long sampleSize, OffsetMap offsetMap) { - Map sampleSizeOfPartition = new HashMap<>(); - - Map latest = offsetMap.getLatest(); - - // 均分的样本数,在样本数小于分区数的情况下,样本数为 0 - long eachSampleSize = sampleSize / latest.keySet().size(); - // 余数,在部分场景下会丢失 - long remainder = sampleSize % latest.keySet().size(); - - // 样本数小于分区数 - if (eachSampleSize == 0) { - for (KafkaTopicPartition partition : latest.keySet()) { - if (remainder <= 0) { - sampleSizeOfPartition.put(partition, 0L); - } else if (offsetMap.getDifference(partition) > 0) { - sampleSizeOfPartition.put(partition, 1L); - remainder--; - } else { - sampleSizeOfPartition.put(partition, 0L); - } - } - } else { - // 样本数大于分区数 - for (KafkaTopicPartition partition : latest.keySet()) { - if (offsetMap.getDifference(partition) >= eachSampleSize) { - sampleSizeOfPartition.put(partition, eachSampleSize); - } else { - sampleSizeOfPartition.put(partition, offsetMap.getDifference(partition)); - } - } - } - - return sampleSizeOfPartition; - } -} diff --git a/kafka-base/kafka-base-source/src/main/java/com/dtstack/flink/sql/source/kafka/table/KafkaSourceParser.java b/kafka-base/kafka-base-source/src/main/java/com/dtstack/flink/sql/source/kafka/table/KafkaSourceParser.java deleted file mode 100644 index b5e2a2ce1..000000000 --- a/kafka-base/kafka-base-source/src/main/java/com/dtstack/flink/sql/source/kafka/table/KafkaSourceParser.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.source.kafka.table; - -import com.dtstack.flink.sql.format.FormatType; -import com.dtstack.flink.sql.source.kafka.enums.EKafkaOffset; -import com.dtstack.flink.sql.table.AbstractSourceParser; -import com.dtstack.flink.sql.table.AbstractTableInfo; -import com.dtstack.flink.sql.util.DtStringUtil; -import com.dtstack.flink.sql.util.MathUtil; -import com.dtstack.flink.sql.util.PluginUtil; -import org.apache.flink.streaming.connectors.kafka.internals.KafkaTopicPartition; - -import java.util.Map; -import java.util.Properties; -import java.util.UUID; -import java.util.stream.Collectors; - -/** - * Reason: - * Date: 2018/09/18 - * Company: www.dtstack.com - * - * @author sishu.yss - */ -public class KafkaSourceParser extends AbstractSourceParser { - @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) throws Exception { - - KafkaSourceTableInfo kafkaSourceTableInfo = new KafkaSourceTableInfo(); - - kafkaSourceTableInfo.setName(tableName); - parseFieldsInfo(fieldsInfo, kafkaSourceTableInfo); - - kafkaSourceTableInfo.setType(MathUtil.getString(props.get(KafkaSourceTableInfo.TYPE_KEY.toLowerCase()))); - kafkaSourceTableInfo.setParallelism(MathUtil.getIntegerVal(props.get(KafkaSourceTableInfo.PARALLELISM_KEY.toLowerCase()))); - kafkaSourceTableInfo.setBootstrapServers(MathUtil.getString(props.get(KafkaSourceTableInfo.BOOTSTRAPSERVERS_KEY.toLowerCase()))); - kafkaSourceTableInfo.setGroupId(MathUtil.getString(props.getOrDefault(KafkaSourceTableInfo.GROUPID_KEY.toLowerCase(), UUID.randomUUID().toString().replace("-", "")))); - kafkaSourceTableInfo.setTopic(MathUtil.getString(props.get(KafkaSourceTableInfo.TOPIC_KEY.toLowerCase()))); - kafkaSourceTableInfo.setTopicIsPattern(MathUtil.getBoolean(props.get(KafkaSourceTableInfo.TOPICISPATTERN_KEY.toLowerCase()), false)); - kafkaSourceTableInfo.setOffsetReset(MathUtil.getString(props.getOrDefault(KafkaSourceTableInfo.OFFSETRESET_KEY.toLowerCase(), EKafkaOffset.LATEST.name().toLowerCase()))); - - kafkaSourceTableInfo.setCharsetName(MathUtil.getString(props.getOrDefault(KafkaSourceTableInfo.CHARSET_NAME_KEY.toLowerCase(),"UTF-8"))); - - kafkaSourceTableInfo.setSchemaString(MathUtil.getString(props.get(KafkaSourceTableInfo.SCHEMA_STRING_KEY.toLowerCase()))); - kafkaSourceTableInfo.setFieldDelimiter(MathUtil.getString(props.getOrDefault(KafkaSourceTableInfo.CSV_FIELD_DELIMITER_KEY.toLowerCase(), "|"))); - kafkaSourceTableInfo.setSourceDataType(MathUtil.getString(props.getOrDefault(KafkaSourceTableInfo.SOURCE_DATA_TYPE_KEY.toLowerCase(), FormatType.DT_NEST.name()))); - kafkaSourceTableInfo.setTimeZone(MathUtil.getString(props.get(KafkaSourceTableInfo.TIME_ZONE_KEY.toLowerCase()))); - - kafkaSourceTableInfo.setSampleSize(MathUtil.getLongVal(props.getOrDefault(KafkaSourceTableInfo.SAMPLE_SIZE_KEY.toLowerCase(), -1L))); - - if(props.containsKey(KafkaSourceTableInfo.TIMESTAMP_OFFSET.toLowerCase())){ - kafkaSourceTableInfo.setTimestampOffset(MathUtil.getLongVal(props.getOrDefault(KafkaSourceTableInfo.TIMESTAMP_OFFSET.toLowerCase(), System.currentTimeMillis()))); - } - Map kafkaParams = props.keySet().stream() - .filter(key -> !key.isEmpty() && key.startsWith("kafka.")) - .collect(Collectors.toMap( - key -> key.substring(6), key -> props.get(key).toString()) - ); - - kafkaSourceTableInfo.addKafkaParam(kafkaParams); - kafkaSourceTableInfo.check(); - - return kafkaSourceTableInfo; - } -} diff --git a/kafka-base/kafka-base-source/src/main/java/com/dtstack/flink/sql/source/kafka/table/KafkaSourceTableInfo.java b/kafka-base/kafka-base-source/src/main/java/com/dtstack/flink/sql/source/kafka/table/KafkaSourceTableInfo.java deleted file mode 100644 index a38ff8c35..000000000 --- a/kafka-base/kafka-base-source/src/main/java/com/dtstack/flink/sql/source/kafka/table/KafkaSourceTableInfo.java +++ /dev/null @@ -1,208 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.source.kafka.table; - -import com.dtstack.flink.sql.table.AbstractSourceTableInfo; -import com.google.common.base.Preconditions; -import org.apache.flink.streaming.connectors.kafka.internals.KafkaTopicPartition; - -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -/** - * Reason: - * Date: 2018/09/18 - * Company: www.dtstack.com - * @author sishu.yss - */ - -public class KafkaSourceTableInfo extends AbstractSourceTableInfo { - - public static final String BOOTSTRAPSERVERS_KEY = "bootstrapServers"; - - public static final String TOPIC_KEY = "topic"; - - public static final String TYPE_KEY = "type"; - - public static final String GROUPID_KEY = "groupId"; - - public static final String OFFSETRESET_KEY = "offsetReset"; - - public static final String TOPICISPATTERN_KEY = "topicIsPattern"; - - public static final String SCHEMA_STRING_KEY = "schemaInfo"; - - public static final String CSV_FIELD_DELIMITER_KEY = "fieldDelimiter"; - - public static final String SOURCE_DATA_TYPE_KEY = "sourceDataType"; - - public static final String CHARSET_NAME_KEY = "charsetName"; - - public static final String SAMPLE_SIZE_KEY = "sampleSize"; - - public static final String TIMESTAMP_OFFSET = "timestampOffset"; - - public static final String KEY_DESERIALIZER = "key.deserializer"; - - public static final String DT_KEY_DESERIALIZER = "dt.key.deserializer"; - - public static final String VALUE_DESERIALIZER = "value.deserializer"; - - public static final String DT_VALUE_DESERIALIZER = "dt.value.deserializer"; - - public static final String DT_DESERIALIZER_CLASS_NAME = "com.dtstack.flink.sql.source.kafka.deserializer.DtKafkaDeserializer"; - - private String bootstrapServers; - - private String topic; - - private String groupId; - - private String offsetReset; - - private Boolean topicIsPattern = false; - - private String sourceDataType; - - private String schemaString; - - private String fieldDelimiter; - - public Map kafkaParams = new HashMap<>(); - - public String charsetName; - - private Long timestampOffset; - - private Long sampleSize; - - public String getBootstrapServers() { - return bootstrapServers; - } - - public void setBootstrapServers(String bootstrapServers) { - this.bootstrapServers = bootstrapServers; - } - - public String getTopic() { - return topic; - } - - public void setTopic(String topic) { - this.topic = topic; - } - - public String getGroupId() { - return groupId; - } - - public void setGroupId(String groupId) { - this.groupId = groupId; - } - - public String getOffsetReset() { - return offsetReset; - } - - public void setOffsetReset(String offsetReset) { - this.offsetReset = offsetReset; - } - - public Boolean getTopicIsPattern() { - return topicIsPattern; - } - - public void setTopicIsPattern(Boolean topicIsPattern) { - this.topicIsPattern = topicIsPattern; - } - - public void addKafkaParam(Map kafkaParam) { - kafkaParams.putAll(kafkaParam); - } - - public String getKafkaParam(String key) { - return kafkaParams.get(key); - } - - public void putKafkaParam(String key, String value) { - kafkaParams.put(key, value); - } - - public Set getKafkaParamKeys() { - return kafkaParams.keySet(); - } - - public String getSourceDataType() { - return sourceDataType; - } - - public void setSourceDataType(String sourceDataType) { - this.sourceDataType = sourceDataType; - } - - public String getSchemaString() { - return schemaString; - } - - public void setSchemaString(String schemaString) { - this.schemaString = schemaString; - } - - public String getFieldDelimiter() { - return fieldDelimiter; - } - - public void setFieldDelimiter(String fieldDelimiter) { - this.fieldDelimiter = fieldDelimiter; - } - - public String getCharsetName() { - return charsetName; - } - - public void setCharsetName(String charsetName) { - this.charsetName = charsetName; - } - - public Long getTimestampOffset() { - return timestampOffset; - } - - public void setTimestampOffset(Long timestampOffset) { - this.timestampOffset = timestampOffset; - } - - public Long getSampleSize() { - return sampleSize; - } - - public void setSampleSize(Long sampleSize) { - this.sampleSize = sampleSize; - } - - @Override - public boolean check() { - Preconditions.checkNotNull(getType(), "kafka of type is required"); - Preconditions.checkNotNull(bootstrapServers, "kafka of bootstrapServers is required"); - Preconditions.checkNotNull(topic, "kafka of topic is required"); - return false; - } -} diff --git a/kafka-base/kafka-base-source/src/main/java/com/dtstack/flink/sql/source/kafka/throwable/KafkaSamplingUnavailableException.java b/kafka-base/kafka-base-source/src/main/java/com/dtstack/flink/sql/source/kafka/throwable/KafkaSamplingUnavailableException.java deleted file mode 100644 index 3d92280e1..000000000 --- a/kafka-base/kafka-base-source/src/main/java/com/dtstack/flink/sql/source/kafka/throwable/KafkaSamplingUnavailableException.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.source.kafka.throwable; - -import org.apache.flink.runtime.throwable.ThrowableAnnotation; -import org.apache.flink.runtime.throwable.ThrowableType; -import org.apache.flink.util.FlinkRuntimeException; - -/** - * @author tiezhu - * @since 2021/6/17 星期四 - */ -@ThrowableAnnotation(ThrowableType.NonRecoverableError) -public class KafkaSamplingUnavailableException extends FlinkRuntimeException { - - public KafkaSamplingUnavailableException(String message) { - super(message); - } -} diff --git a/kafka-base/kafka-base-source/src/main/java/org/apache/flink/formats/json/DTJsonRowDeserializationSchema.java b/kafka-base/kafka-base-source/src/main/java/org/apache/flink/formats/json/DTJsonRowDeserializationSchema.java deleted file mode 100644 index 6204058fe..000000000 --- a/kafka-base/kafka-base-source/src/main/java/org/apache/flink/formats/json/DTJsonRowDeserializationSchema.java +++ /dev/null @@ -1,233 +0,0 @@ -/* - * 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.formats.json; - -import org.apache.flink.annotation.PublicEvolving; -import org.apache.flink.api.common.serialization.DeserializationSchema; -import org.apache.flink.api.common.typeinfo.BasicArrayTypeInfo; -import org.apache.flink.api.common.typeinfo.PrimitiveArrayTypeInfo; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.common.typeinfo.Types; -import org.apache.flink.api.java.typeutils.ObjectArrayTypeInfo; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.core.JsonProcessingException; -import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.JsonNode; -import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.ObjectMapper; -import org.apache.flink.types.Row; -import org.apache.flink.util.Preconditions; - -import java.io.IOException; -import java.lang.reflect.Array; -import java.sql.Date; -import java.sql.Time; -import java.sql.Timestamp; -import java.util.Objects; - -/** - * Deserialization schema from JSON to Flink types. - * - *

Deserializes a byte[] message as a JSON object and reads - * the specified fields. - * - *

Failures during deserialization are forwarded as wrapped IOExceptions. - */ -@PublicEvolving -public class DTJsonRowDeserializationSchema implements DeserializationSchema { - - private static final long serialVersionUID = -228294330688809195L; - - /** Type information describing the result type. */ - private final TypeInformation typeInfo; - - /** Object mapper for parsing the JSON. */ - private final ObjectMapper objectMapper = new ObjectMapper(); - - /** Flag indicating whether to fail on a missing field. */ - private boolean failOnMissingField; - - /** - * Creates a JSON deserialization schema for the given type information. - * - * @param typeInfo Type information describing the result type. The field names of {@link Row} - * are used to parse the JSON properties. - */ - public DTJsonRowDeserializationSchema(TypeInformation typeInfo) { - Preconditions.checkNotNull(typeInfo, "Type information"); - this.typeInfo = typeInfo; - - if (!(typeInfo instanceof RowTypeInfo)) { - throw new IllegalArgumentException("Row type information expected."); - } - } - - /** - * Creates a JSON deserialization schema for the given JSON schema. - * - * @param jsonSchema JSON schema describing the result type - * - * @see http://json-schema.org/ - */ - public DTJsonRowDeserializationSchema(String jsonSchema) { - this(JsonRowSchemaConverter.convert(jsonSchema)); - } - - @Override - public Row deserialize(byte[] message) throws IOException { - try { - final JsonNode root = objectMapper.readTree(message); - return convertRow(root, (RowTypeInfo) typeInfo); - } catch (Throwable t) { - throw new IOException("Failed to deserialize JSON object.", t); - } - } - - @Override - public boolean isEndOfStream(Row nextElement) { - return false; - } - - @Override - public TypeInformation getProducedType() { - return typeInfo; - } - - /** - * Configures the failure behaviour if a JSON field is missing. - * - *

By default, a missing field is ignored and the field is set to null. - * - * @param failOnMissingField Flag indicating whether to fail or not on a missing field. - */ - public void setFailOnMissingField(boolean failOnMissingField) { - this.failOnMissingField = failOnMissingField; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - final DTJsonRowDeserializationSchema that = (DTJsonRowDeserializationSchema) o; - return failOnMissingField == that.failOnMissingField && Objects.equals(typeInfo, that.typeInfo); - } - - @Override - public int hashCode() { - return Objects.hash(typeInfo, failOnMissingField); - } - - // -------------------------------------------------------------------------------------------- - - private Object convert(JsonNode node, TypeInformation info) { - if (info.equals(Types.VOID) || node.isNull()) { - return null; - } else if (info.equals(Types.BOOLEAN)) { - return node.asBoolean(); - } else if (info.equals(Types.STRING)) { - return node.asText(); - } else if (info.equals(Types.BIG_DEC)) { - return node.decimalValue(); - } else if (info.equals(Types.BIG_INT)) { - return node.bigIntegerValue(); - } else if (info.equals(Types.SQL_DATE)) { - return Date.valueOf(node.asText()); - } else if (info.equals(Types.SQL_TIME)) { - // according to RFC 3339 every full-time must have a timezone; - // until we have full timezone support, we only support UTC; - // users can parse their time as string as a workaround - final String time = node.asText(); - if (time.indexOf('Z') < 0 || time.indexOf('.') >= 0) { - throw new IllegalStateException( - "Invalid time format. Only a time in UTC timezone without milliseconds is supported yet. " + - "Format: HH:mm:ss'Z'"); - } - return Time.valueOf(time.substring(0, time.length() - 1)); - } else if (info.equals(Types.SQL_TIMESTAMP)) { - // according to RFC 3339 every date-time must have a timezone; - // until we have full timezone support, we only support UTC; - // users can parse their time as string as a workaround - final String timestamp = node.asText(); - if (timestamp.indexOf('Z') < 0) { - throw new IllegalStateException( - "Invalid timestamp format. Only a timestamp in UTC timezone is supported yet. " + - "Format: yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); - } - return Timestamp.valueOf(timestamp.substring(0, timestamp.length() - 1).replace('T', ' ')); - } else if (info instanceof RowTypeInfo) { - return convertRow(node, (RowTypeInfo) info); - } else if (info instanceof ObjectArrayTypeInfo) { - return convertObjectArray(node, ((ObjectArrayTypeInfo) info).getComponentInfo()); - } else if (info instanceof BasicArrayTypeInfo) { - return convertObjectArray(node, ((BasicArrayTypeInfo) info).getComponentInfo()); - } else if (info instanceof PrimitiveArrayTypeInfo && - ((PrimitiveArrayTypeInfo) info).getComponentType() == Types.BYTE) { - return convertByteArray(node); - } else { - // for types that were specified without JSON schema - // e.g. POJOs - try { - return objectMapper.treeToValue(node, info.getTypeClass()); - } catch (JsonProcessingException e) { - throw new IllegalStateException("Unsupported type information '" + info + "' for node: " + node); - } - } - } - - private Row convertRow(JsonNode node, RowTypeInfo info) { - final String[] names = info.getFieldNames(); - final TypeInformation[] types = info.getFieldTypes(); - - final Row row = new Row(names.length); - for (int i = 0; i < names.length; i++) { - final String name = names[i]; - final JsonNode subNode = node.get(name); - if (subNode == null) { - if (failOnMissingField) { - throw new IllegalStateException( - "Could not find field with name '" + name + "'."); - } else { - row.setField(i, null); - } - } else { - row.setField(i, convert(subNode, types[i])); - } - } - - return row; - } - - private Object convertObjectArray(JsonNode node, TypeInformation elementType) { - final Object[] array = (Object[]) Array.newInstance(elementType.getTypeClass(), node.size()); - for (int i = 0; i < node.size(); i++) { - array[i] = convert(node.get(i), elementType); - } - return array; - } - - private Object convertByteArray(JsonNode node) { - try { - return node.binaryValue(); - } catch (IOException e) { - throw new RuntimeException("Unable to deserialize byte array.", e); - } - } -} diff --git a/kafka-base/kafka-base-source/src/test/java/com/dtstack/flink/sql/source/kafka/AbstractKafkaConsumerFactoryTest.java b/kafka-base/kafka-base-source/src/test/java/com/dtstack/flink/sql/source/kafka/AbstractKafkaConsumerFactoryTest.java deleted file mode 100644 index c7ca4fd60..000000000 --- a/kafka-base/kafka-base-source/src/test/java/com/dtstack/flink/sql/source/kafka/AbstractKafkaConsumerFactoryTest.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.dtstack.flink.sql.source.kafka; - -import com.dtstack.flink.sql.source.kafka.table.KafkaSourceTableInfo; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.common.typeinfo.Types; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumerBase; -import org.apache.flink.types.Row; -import org.junit.Before; -import org.junit.Test; - -import java.util.Properties; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class AbstractKafkaConsumerFactoryTest { - - private AbstractKafkaConsumerFactory kafkaConsumerFactory; - private RowTypeInfo typeInformation; - - @Before - public void init(){ - kafkaConsumerFactory = new AbstractKafkaConsumerFactory() { - @Override - protected FlinkKafkaConsumerBase createKafkaTableSource(KafkaSourceTableInfo kafkaSourceTableInfo, TypeInformation typeInformation, Properties props) { - return null; - } - }; - - String[] fieldNames = new String[1]; - fieldNames[0] = "1"; - TypeInformation[] typeInformations = new TypeInformation[1]; - typeInformations[0] = Types.STRING; - typeInformation = new RowTypeInfo(typeInformations, fieldNames); - } - - @Test - public void createDeserializationMetricWrapper(){ - KafkaSourceTableInfo kafkaSourceTableInfo = mock(KafkaSourceTableInfo.class); - when(kafkaSourceTableInfo.getSourceDataType()).thenReturn("DT_NEST"); - Calculate calculate = mock(Calculate.class); -// kafkaConsumerFactory.createDeserializationMetricWrapper(kafkaSourceTableInfo, typeInformation, calculate); - - - when(kafkaSourceTableInfo.getSourceDataType()).thenReturn("JSON"); -// kafkaConsumerFactory.createDeserializationMetricWrapper(kafkaSourceTableInfo, typeInformation, calculate); - - when(kafkaSourceTableInfo.getSourceDataType()).thenReturn("CSV"); - when(kafkaSourceTableInfo.getFieldDelimiter()).thenReturn(","); -// kafkaConsumerFactory.createDeserializationMetricWrapper(kafkaSourceTableInfo, typeInformation, calculate); - - - when(kafkaSourceTableInfo.getSourceDataType()).thenReturn("AVRO"); - when(kafkaSourceTableInfo.getSchemaString()).thenReturn("{\"type\":\"record\",\"name\":\"MyResult\",\"fields\":[{\"name\":\"channel\",\"type\":\"string\"}]}"); -// kafkaConsumerFactory.createDeserializationMetricWrapper(kafkaSourceTableInfo, typeInformation, calculate); - - } - -} diff --git a/kafka-base/kafka-base-source/src/test/java/com/dtstack/flink/sql/source/kafka/AbstractKafkaSourceTest.java b/kafka-base/kafka-base-source/src/test/java/com/dtstack/flink/sql/source/kafka/AbstractKafkaSourceTest.java deleted file mode 100644 index 26da9c6fe..000000000 --- a/kafka-base/kafka-base-source/src/test/java/com/dtstack/flink/sql/source/kafka/AbstractKafkaSourceTest.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.dtstack.flink.sql.source.kafka; - -import com.dtstack.flink.sql.source.kafka.table.KafkaSourceTableInfo; -import com.dtstack.flink.sql.table.AbstractSourceTableInfo; -import com.google.common.collect.Lists; -import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; -import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumerBase; -import org.apache.flink.table.api.Table; -import org.apache.flink.table.api.java.StreamTableEnvironment; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mockito; - -public class AbstractKafkaSourceTest { - - private AbstractKafkaSource kafkaSource; - - @Before - public void init() { - kafkaSource = new AbstractKafkaSource() { - @Override - public Table genStreamSource(AbstractSourceTableInfo sourceTableInfo, StreamExecutionEnvironment env, StreamTableEnvironment tableEnv) { - return null; - } - }; - } - - @Test - public void getKafkaProperties() { - KafkaSourceTableInfo kafkaSourceTableInfo = new KafkaSourceTableInfo(); - kafkaSourceTableInfo.setBootstrapServers("localhost"); - kafkaSourceTableInfo.setOffsetReset("1"); - kafkaSourceTableInfo.setGroupId("1"); - kafkaSourceTableInfo.setPrimaryKeys(Lists.newArrayList("a")); - kafkaSource.getKafkaProperties(kafkaSourceTableInfo); - } - - @Test - public void generateOperatorName() { - kafkaSource.generateOperatorName("a", "b"); - } - - @Test - public void getRowTypeInformation() { - KafkaSourceTableInfo kafkaSourceTableInfo = new KafkaSourceTableInfo(); - kafkaSourceTableInfo.setFieldClasses(new Class[]{String.class}); - kafkaSourceTableInfo.setFields(new String[]{"a"}); - kafkaSource.getRowTypeInformation(kafkaSourceTableInfo); - - } - -// @Test - public void setStartPosition(){ - FlinkKafkaConsumerBase flinkKafkaConsumerBase = Mockito.mock(FlinkKafkaConsumerBase.class); -// kafkaSource.setStartPosition("1", "a", flinkKafkaConsumerBase); - } - - @Test - public void buildOffsetMap(){ - kafkaSource.buildOffsetMap("{\"12\":\"12\"}", "a"); - } -} diff --git a/kafka-base/kafka-base-source/src/test/java/com/dtstack/flink/sql/source/kafka/DTJsonRowDeserializationSchemaTest.java b/kafka-base/kafka-base-source/src/test/java/com/dtstack/flink/sql/source/kafka/DTJsonRowDeserializationSchemaTest.java deleted file mode 100644 index 4464cf284..000000000 --- a/kafka-base/kafka-base-source/src/test/java/com/dtstack/flink/sql/source/kafka/DTJsonRowDeserializationSchemaTest.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.dtstack.flink.sql.source.kafka; - -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.common.typeinfo.Types; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.formats.json.DTJsonRowDeserializationSchema; -import org.junit.Test; - -import java.io.IOException; - -import static org.mockito.Mockito.*; - -public class DTJsonRowDeserializationSchemaTest { - - @Test - public void mockDeserialize() throws IOException { - RowTypeInfo rowTypeInfo = mock(RowTypeInfo.class); - when(rowTypeInfo.getFieldNames()).thenReturn(new String[]{"name"}); - when(rowTypeInfo.getFieldTypes()).thenReturn(new TypeInformation[]{Types.STRING}); - DTJsonRowDeserializationSchema dtJsonRowDeserializationSchema = new DTJsonRowDeserializationSchema(rowTypeInfo); - - DTJsonRowDeserializationSchema dtJsonRowDeserializationSchemaSpy = spy(dtJsonRowDeserializationSchema); - String message = "{\"name\":\"roc\"}"; - dtJsonRowDeserializationSchemaSpy.deserialize(message.getBytes()); - verify(dtJsonRowDeserializationSchemaSpy).deserialize(message.getBytes()); - - } -} diff --git a/kafka-base/kafka-base-source/src/test/java/com/dtstack/flink/sql/source/kafka/DtKafkaDeserializationSchemaWrapperTest.java b/kafka-base/kafka-base-source/src/test/java/com/dtstack/flink/sql/source/kafka/DtKafkaDeserializationSchemaWrapperTest.java deleted file mode 100644 index dc71a35b2..000000000 --- a/kafka-base/kafka-base-source/src/test/java/com/dtstack/flink/sql/source/kafka/DtKafkaDeserializationSchemaWrapperTest.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.source.kafka; - -import com.dtstack.flink.sql.source.kafka.deserialization.DtKafkaDeserializationSchemaWrapper; -import org.apache.flink.api.common.serialization.SimpleStringSchema; -import org.apache.flink.streaming.connectors.kafka.internals.KafkaTopicPartition; -import org.apache.kafka.clients.consumer.ConsumerRecord; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import java.nio.charset.StandardCharsets; -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Collectors; - -/** - * @auther tiezhu - * @date 2021/4/27 4:33 下午 - */ -public class DtKafkaDeserializationSchemaWrapperTest { - public Map specificEndOffsets; - - private DtKafkaDeserializationSchemaWrapper kafkaDeserializationSchemaWrapper; - - @Before - public void setUp() { - String topic = "test"; - Map valueMap = new HashMap<>(); - - valueMap.put("1", 10); - - specificEndOffsets = valueMap - .entrySet() - .stream() - .collect(Collectors.toMap( - (Map.Entry entry) - -> new KafkaTopicPartition(topic, Integer.parseInt(entry.getKey())), - (Map.Entry entry) - -> Long.valueOf(entry.getValue().toString())) - ); - - kafkaDeserializationSchemaWrapper = new DtKafkaDeserializationSchemaWrapper<>(new SimpleStringSchema()); - } - - @Test - public void testIsEndOfStream() { - String topic = "test"; - - Assert.assertFalse(kafkaDeserializationSchemaWrapper.isEndOfStream(topic)); - } - - @Test - public void testDeserialize() throws Exception { - String str = "test"; - ConsumerRecord record = new ConsumerRecord<>( - "test", - 1, - 11, - str.getBytes(StandardCharsets.UTF_8), - str.getBytes(StandardCharsets.UTF_8) - ); - - String deserialize = kafkaDeserializationSchemaWrapper.deserialize(record); - - Assert.assertNull(deserialize); - } -} diff --git a/kafka-base/kafka-base-source/src/test/java/com/dtstack/flink/sql/source/kafka/KafkaDeserializationMetricWrapperTest.java b/kafka-base/kafka-base-source/src/test/java/com/dtstack/flink/sql/source/kafka/KafkaDeserializationMetricWrapperTest.java deleted file mode 100644 index 62eb908e4..000000000 --- a/kafka-base/kafka-base-source/src/test/java/com/dtstack/flink/sql/source/kafka/KafkaDeserializationMetricWrapperTest.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.dtstack.flink.sql.source.kafka; - -import com.dtstack.flink.sql.source.kafka.deserialization.KafkaDeserializationMetricWrapper; -import org.apache.flink.api.common.serialization.DeserializationSchema; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.types.Row; -import org.junit.Before; -import org.junit.Test; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -import static org.mockito.Mockito.*; - -public class KafkaDeserializationMetricWrapperTest { - private KafkaDeserializationMetricWrapper kafkaDeserializationMetricWrapper; - - @Before - public void init() { - Map dirtyMap = new HashMap<>(); - dirtyMap.put("type", "console"); - // 多少条数据打印一次 - dirtyMap.put("printLimit", "100"); - dirtyMap.put("url", "jdbc:mysql://localhost:3306/tiezhu"); - dirtyMap.put("userName", "root"); - dirtyMap.put("password", "abc123"); - dirtyMap.put("isCreateTable", "false"); - // 多少条数据写入一次 - dirtyMap.put("batchSize", "1"); - dirtyMap.put("tableName", "dirtyData"); - dirtyMap.put("pluginLoadMode", "localTest"); - TypeInformation typeInfo = mock(TypeInformation.class); - DeserializationSchema deserializationSchema = mock(DeserializationSchema.class); - Calculate calculate = mock(Calculate.class); -// kafkaDeserializationMetricWrapper = new KafkaDeserializationMetricWrapper(typeInfo, deserializationSchema, calculate, DirtyDataManager.newInstance(dirtyMap)); - } - - @Test - public void beforeDeserialize() throws IOException { - //kafkaDeserializationMetricWrapper.beforeDeserialize(); - } - -} diff --git a/kafka-base/kafka-base-source/src/test/java/com/dtstack/flink/sql/source/kafka/KafkaSourceParserTest.java b/kafka-base/kafka-base-source/src/test/java/com/dtstack/flink/sql/source/kafka/KafkaSourceParserTest.java deleted file mode 100644 index c393c3076..000000000 --- a/kafka-base/kafka-base-source/src/test/java/com/dtstack/flink/sql/source/kafka/KafkaSourceParserTest.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.dtstack.flink.sql.source.kafka; - -import com.dtstack.flink.sql.source.kafka.table.KafkaSourceParser; -import com.google.common.collect.Maps; -import org.junit.Test; - -import java.util.Map; - -import static org.mockito.Mockito.*; - -public class KafkaSourceParserTest { - - @Test - public void mockGetTableInfo() throws Exception { - String tableName = "table"; - String fieldsInfo = "aa varchar"; - Map props = Maps.newHashMap(); - props.put("type", "kafka10"); - props.put("parallelism", "1"); - props.put("bootstrapservers", "localhost"); - props.put("groupid", "groupId"); - props.put("topic", "topic"); - props.put("offsetreset", "1atest"); - props.put("topicsspattern", "false"); - props.put("sourcedataType", "json"); - KafkaSourceParser kafkaSourceParser = new KafkaSourceParser(); - KafkaSourceParser kafkaSourceParserSpy = spy(kafkaSourceParser); - kafkaSourceParserSpy.getTableInfo(tableName, fieldsInfo, props); - verify(kafkaSourceParserSpy).getTableInfo(tableName, fieldsInfo, props); - } -} diff --git a/kafka-base/pom.xml b/kafka-base/pom.xml deleted file mode 100644 index 39a9ab5b2..000000000 --- a/kafka-base/pom.xml +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - flink.sql - com.dtstack.flink - 1.0-SNAPSHOT - ../pom.xml - - 4.0.0 - - pom - - sql.kafka-base - - - kafka-base-sink - kafka-base-source - - - - - - com.dtstack.flink - sql.core - 1.0-SNAPSHOT - provided - - - - org.apache.flink - flink-connector-kafka-0.9_2.11 - ${flink.version} - provided - - - - org.apache.flink - flink-avro - ${flink.version} - - - - org.apache.flink - flink-csv - ${flink.version} - - - - org.apache.flink - flink-json - ${flink.version} - - - - - - \ No newline at end of file diff --git a/kafka/kafka-sink/pom.xml b/kafka/kafka-sink/pom.xml index 8e0e0e2ae..41aa899c2 100644 --- a/kafka/kafka-sink/pom.xml +++ b/kafka/kafka-sink/pom.xml @@ -15,11 +15,12 @@ kafka-sink jar + - sql.sink.kafka-base - com.dtstack.flink - 1.0-SNAPSHOT + org.apache.flink + flink-json + ${flink.version} @@ -36,7 +37,6 @@ shade - false org.slf4j @@ -70,14 +70,14 @@ - + - + diff --git a/kafka/kafka-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerFlinkKafkaProducer.java b/kafka/kafka-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerFlinkKafkaProducer.java new file mode 100644 index 000000000..b7976a30e --- /dev/null +++ b/kafka/kafka-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerFlinkKafkaProducer.java @@ -0,0 +1,60 @@ +/* + * 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 com.dtstack.flink.sql.sink.kafka; + +import com.dtstack.flink.sql.metric.MetricConstant; +import org.apache.flink.api.common.functions.RuntimeContext; +import org.apache.flink.api.common.serialization.SerializationSchema; +import org.apache.flink.configuration.Configuration; +import org.apache.flink.metrics.Counter; +import org.apache.flink.metrics.MeterView; +import org.apache.flink.streaming.connectors.kafka.FlinkKafkaProducer; + +import java.util.Properties; + +/** + * @author: chuixue + * @create: 2019-11-05 11:54 + * @description: + **/ +public class CustomerFlinkKafkaProducer extends FlinkKafkaProducer { + + CustomerJsonRowSerializationSchema schema; + + public CustomerFlinkKafkaProducer(String topicId, SerializationSchema serializationSchema, Properties producerConfig) { + super(topicId, serializationSchema, producerConfig); + this.schema = (CustomerJsonRowSerializationSchema) serializationSchema; + } + + @Override + public void open(Configuration configuration) { + RuntimeContext ctx = getRuntimeContext(); + Counter counter = ctx.getMetricGroup().counter(MetricConstant.DT_NUM_RECORDS_OUT); + MeterView meter = ctx.getMetricGroup().meter(MetricConstant.DT_NUM_RECORDS_OUT_RATE, new MeterView(counter, 20)); + + schema.setCounter(counter); + + try { + super.open(configuration); + } catch (Exception e) { + throw new RuntimeException("",e); + } + } + +} diff --git a/kafka-base/kafka-base-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/serialization/JsonTupleSerializationSchema.java b/kafka/kafka-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerJsonRowSerializationSchema.java similarity index 74% rename from kafka-base/kafka-base-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/serialization/JsonTupleSerializationSchema.java rename to kafka/kafka-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerJsonRowSerializationSchema.java index 54c547aad..d698d3ee2 100644 --- a/kafka-base/kafka-base-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/serialization/JsonTupleSerializationSchema.java +++ b/kafka/kafka-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerJsonRowSerializationSchema.java @@ -1,12 +1,13 @@ /* - * 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 + * 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 + * 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, @@ -15,20 +16,19 @@ * limitations under the License. */ -package com.dtstack.flink.sql.sink.kafka.serialization; +package com.dtstack.flink.sql.sink.kafka; -import com.dtstack.flink.sql.enums.EUpdateMode; -import org.apache.commons.lang3.StringUtils; +import org.apache.flink.annotation.PublicEvolving; import org.apache.flink.api.common.serialization.SerializationSchema; import org.apache.flink.api.common.typeinfo.BasicArrayTypeInfo; import org.apache.flink.api.common.typeinfo.PrimitiveArrayTypeInfo; import org.apache.flink.api.common.typeinfo.TypeInformation; import org.apache.flink.api.common.typeinfo.Types; -import org.apache.flink.api.java.tuple.Tuple2; import org.apache.flink.api.java.typeutils.ObjectArrayTypeInfo; import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.api.java.typeutils.TupleTypeInfo; +import org.apache.flink.formats.json.JsonRowDeserializationSchema; import org.apache.flink.formats.json.JsonRowSchemaConverter; +import org.apache.flink.metrics.Counter; import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.JsonNode; import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.ObjectMapper; import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.node.ArrayNode; @@ -42,22 +42,22 @@ import java.sql.Time; import java.sql.Timestamp; import java.text.SimpleDateFormat; -import java.util.Objects; /** - * * Serialization schema that serializes an object of Flink types into a JSON bytes. * *

Serializes the input Flink object into a JSON string and * converts it into byte[]. * + *

Result byte[] messages can be deserialized using {@link JsonRowDeserializationSchema}. */ -public class JsonTupleSerializationSchema implements SerializationSchema> { +@PublicEvolving +public class CustomerJsonRowSerializationSchema implements SerializationSchema { private static final long serialVersionUID = -2885556750743978636L; /** Type information describing the input type. */ - private final TypeInformation> typeInfo; + private final TypeInformation typeInfo; /** Object mapper that is used to create output JSON objects. */ private final ObjectMapper mapper = new ObjectMapper(); @@ -74,40 +74,38 @@ public class JsonTupleSerializationSchema implements SerializationSchema> typeInfo, String updateMode) { + public CustomerJsonRowSerializationSchema(TypeInformation typeInfo) { Preconditions.checkNotNull(typeInfo, "Type information"); this.typeInfo = typeInfo; - this.updateMode = updateMode; } + /** + * Creates a JSON serialization schema for the given JSON schema. + * + * @param jsonSchema JSON schema describing the result type + * + * @see http://json-schema.org/ + */ + public CustomerJsonRowSerializationSchema(String jsonSchema) { + this(JsonRowSchemaConverter.convert(jsonSchema)); + } @Override - public byte[] serialize(Tuple2 tuple2) { - Row row = tuple2.f1; - boolean change = tuple2.f0; + public byte[] serialize(Row row) { if (node == null) { node = mapper.createObjectNode(); } - RowTypeInfo rowTypeInfo = (RowTypeInfo) ((TupleTypeInfo) typeInfo).getTypeAt(1); try { - convertRow(node, rowTypeInfo, row); - if (StringUtils.equalsIgnoreCase(updateMode, EUpdateMode.UPSERT.name())) { - node.put(retractKey, change); - } + convertRow(node, (RowTypeInfo) typeInfo, row); + counter.inc(); return mapper.writeValueAsBytes(node); } catch (Throwable t) { throw new RuntimeException("Could not serialize row '" + row + "'. " + @@ -115,23 +113,6 @@ public byte[] serialize(Tuple2 tuple2) { } } - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - final JsonTupleSerializationSchema that = (JsonTupleSerializationSchema) o; - return Objects.equals(typeInfo, that.typeInfo); - } - - @Override - public int hashCode() { - return Objects.hash(typeInfo); - } - // -------------------------------------------------------------------------------------------- private ObjectNode convertRow(ObjectNode reuse, RowTypeInfo info, Row row) { @@ -139,7 +120,6 @@ private ObjectNode convertRow(ObjectNode reuse, RowTypeInfo info, Row row) { reuse = mapper.createObjectNode(); } final String[] fieldNames = info.getFieldNames(); - final TypeInformation[] fieldTypes = info.getFieldTypes(); // validate the row @@ -159,34 +139,34 @@ private ObjectNode convertRow(ObjectNode reuse, RowTypeInfo info, Row row) { } private JsonNode convert(ContainerNode container, JsonNode reuse, TypeInformation info, Object object) { - if (info.equals(Types.VOID) || object == null) { + if (info == Types.VOID || object == null) { return container.nullNode(); - } else if (info.equals(Types.BOOLEAN)) { + } else if (info == Types.BOOLEAN) { return container.booleanNode((Boolean) object); - } else if (info.equals(Types.STRING)) { + } else if (info == Types.STRING) { return container.textNode((String) object); - } else if (info.equals(Types.BIG_DEC)) { + } else if (info == Types.BIG_DEC) { // convert decimal if necessary if (object instanceof BigDecimal) { return container.numberNode((BigDecimal) object); } return container.numberNode(BigDecimal.valueOf(((Number) object).doubleValue())); - } else if (info.equals(Types.BIG_INT)) { + } else if (info == Types.BIG_INT) { // convert integer if necessary if (object instanceof BigInteger) { return container.numberNode((BigInteger) object); } return container.numberNode(BigInteger.valueOf(((Number) object).longValue())); - } else if (info.equals(Types.SQL_DATE)) { + } else if (info == Types.SQL_DATE) { return container.textNode(object.toString()); - } else if (info.equals(Types.SQL_TIME)) { + } else if (info == Types.SQL_TIME) { final Time time = (Time) object; // strip milliseconds if possible if (time.getTime() % 1000 > 0) { return container.textNode(timeFormatWithMillis.format(time)); } return container.textNode(timeFormat.format(time)); - } else if (info.equals(Types.SQL_TIMESTAMP)) { + } else if (info == Types.SQL_TIMESTAMP) { return container.textNode(timestampFormat.format((Timestamp) object)); } else if (info instanceof RowTypeInfo) { if (reuse != null && reuse instanceof ObjectNode) { @@ -231,4 +211,12 @@ private ArrayNode convertObjectArray(ArrayNode reuse, TypeInformation info, O } return reuse; } + + public Counter getCounter() { + return counter; + } + + public void setCounter(Counter counter) { + this.counter = counter; + } } diff --git a/kafka/kafka-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerKafkaJsonTableSink.java b/kafka/kafka-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerKafkaJsonTableSink.java new file mode 100644 index 000000000..af6e54854 --- /dev/null +++ b/kafka/kafka-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerKafkaJsonTableSink.java @@ -0,0 +1,65 @@ +/* + * 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 com.dtstack.flink.sql.sink.kafka; + +import org.apache.flink.api.common.serialization.SerializationSchema; +import org.apache.flink.streaming.api.datastream.DataStream; +import org.apache.flink.streaming.api.functions.sink.SinkFunction; +import org.apache.flink.streaming.connectors.kafka.KafkaTableSink; +import org.apache.flink.streaming.connectors.kafka.partitioner.FlinkKafkaPartitioner; +import org.apache.flink.table.api.TableSchema; +import org.apache.flink.table.utils.TableConnectorUtils; +import org.apache.flink.types.Row; + +import java.util.Optional; +import java.util.Properties; + +/** + * @author: chuixue + * @create: 2019-11-05 11:54 + * @description: + **/ +public class CustomerKafkaJsonTableSink extends KafkaTableSink { + + protected SerializationSchema schema; + + + public CustomerKafkaJsonTableSink(TableSchema schema, + String topic, + Properties properties, + Optional> partitioner, + SerializationSchema serializationSchema) { + + super(schema, topic, properties, partitioner, serializationSchema); + this.schema = serializationSchema; + } + + @Override + protected SinkFunction createKafkaProducer(String topic, Properties properties, SerializationSchema serializationSchema, Optional> optional) { + return new CustomerFlinkKafkaProducer(topic, serializationSchema, properties); + } + + @Override + public void emitDataStream(DataStream dataStream) { + SinkFunction kafkaProducer = createKafkaProducer(topic, properties, schema, partitioner); + // always enable flush on checkpoint to achieve at-least-once if query runs with checkpointing enabled. + //kafkaProducer.setFlushOnCheckpoint(true); + dataStream.addSink(kafkaProducer).name(TableConnectorUtils.generateRuntimeName(this.getClass(), getFieldNames())); + } +} diff --git a/kafka/kafka-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/KafkaProducer.java b/kafka/kafka-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/KafkaProducer.java deleted file mode 100644 index 9553b2345..000000000 --- a/kafka/kafka-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/KafkaProducer.java +++ /dev/null @@ -1,65 +0,0 @@ -/** - * 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 com.dtstack.flink.sql.sink.kafka; - -import com.dtstack.flink.sql.format.SerializationMetricWrapper; -import com.dtstack.flink.sql.sink.kafka.serialization.CustomerKeyedSerializationSchema; -import org.apache.flink.api.common.functions.RuntimeContext; -import org.apache.flink.api.common.serialization.SerializationSchema; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.configuration.Configuration; -import org.apache.flink.streaming.connectors.kafka.FlinkKafkaProducer; -import org.apache.flink.streaming.connectors.kafka.partitioner.FlinkKafkaPartitioner; -import org.apache.flink.types.Row; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Optional; -import java.util.Properties; - -/** - * Reason: - * Date: 2019/4/24 - * Company: www.dtstack.com - * - * @author maqi - */ -public class KafkaProducer extends FlinkKafkaProducer> { - - private static final Logger LOG = LoggerFactory.getLogger(KafkaProducer.class); - - private static final long serialVersionUID = 1L; - - private SerializationMetricWrapper serializationMetricWrapper; - - public KafkaProducer(String topicId, SerializationSchema> serializationSchema, Properties producerConfig, - Optional>> customPartitioner, String[] parititonKeys) { - super(topicId, new CustomerKeyedSerializationSchema((SerializationMetricWrapper)serializationSchema, parititonKeys), producerConfig, customPartitioner); - this.serializationMetricWrapper = (SerializationMetricWrapper) serializationSchema; - } - - @Override - public void open(Configuration configuration) throws Exception { - LOG.warn("---open KafkaProducer--"); - RuntimeContext runtimeContext = getRuntimeContext(); - serializationMetricWrapper.setRuntimeContext(runtimeContext); - serializationMetricWrapper.initMetric(); - super.open(configuration); - } - -} \ No newline at end of file diff --git a/kafka/kafka-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/KafkaProducerFactory.java b/kafka/kafka-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/KafkaProducerFactory.java deleted file mode 100644 index 5a3786377..000000000 --- a/kafka/kafka-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/KafkaProducerFactory.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.kafka; - -import com.dtstack.flink.sql.sink.kafka.table.KafkaSinkTableInfo; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.streaming.api.functions.sink.RichSinkFunction; -import org.apache.flink.streaming.connectors.kafka.partitioner.FlinkKafkaPartitioner; -import org.apache.flink.types.Row; - -import java.util.Optional; -import java.util.Properties; - -/** - * company: www.dtstack.com - * - * @author: toutian - * create: 2019/12/24 - */ -public class KafkaProducerFactory extends AbstractKafkaProducerFactory { - - @Override - public RichSinkFunction> createKafkaProducer(KafkaSinkTableInfo kafkaSinkTableInfo, TypeInformation> typeInformation, - Properties properties, Optional>> partitioner, String[] partitionKeys) { - return new KafkaProducer(kafkaSinkTableInfo.getTopic(), createSerializationMetricWrapper(kafkaSinkTableInfo, typeInformation), properties, partitioner, partitionKeys); - } -} diff --git a/kafka/kafka-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/KafkaSink.java b/kafka/kafka-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/KafkaSink.java index 1dc655a0d..44bf9f98b 100644 --- a/kafka/kafka-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/KafkaSink.java +++ b/kafka/kafka-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/KafkaSink.java @@ -18,8 +18,22 @@ package com.dtstack.flink.sql.sink.kafka; +import com.dtstack.flink.sql.sink.IStreamSinkGener; import com.dtstack.flink.sql.sink.kafka.table.KafkaSinkTableInfo; -import com.dtstack.flink.sql.table.AbstractTargetTableInfo; +import com.dtstack.flink.sql.table.TargetTableInfo; +import org.apache.flink.api.common.serialization.SerializationSchema; +import org.apache.flink.api.common.typeinfo.TypeInformation; +import org.apache.flink.api.java.tuple.Tuple2; +import org.apache.flink.api.java.typeutils.RowTypeInfo; +import org.apache.flink.api.java.typeutils.TupleTypeInfo; +import org.apache.flink.streaming.api.datastream.DataStream; +import org.apache.flink.streaming.connectors.kafka.KafkaTableSinkBase; +import org.apache.flink.streaming.connectors.kafka.partitioner.FlinkFixedPartitioner; +import org.apache.flink.streaming.connectors.kafka.partitioner.FlinkKafkaPartitioner; +import org.apache.flink.table.api.TableSchema; +import org.apache.flink.table.sinks.RetractStreamTableSink; +import org.apache.flink.table.sinks.TableSink; +import org.apache.flink.types.Row; import java.util.Optional; import java.util.Properties; @@ -29,23 +43,102 @@ * @create: 2019-11-05 11:45 * @description: **/ -public class KafkaSink extends AbstractKafkaSink { +public class KafkaSink implements RetractStreamTableSink, IStreamSinkGener { + + protected String[] fieldNames; + + protected TypeInformation[] fieldTypes; + + protected String topic; + + protected int parallelism; + + protected Properties properties; + + /** Serialization schema for encoding records to Kafka. */ + protected SerializationSchema serializationSchema; + + /** The schema of the table. */ + private TableSchema schema; + + /** Partitioner to select Kafka partition for each item. */ + protected Optional> partitioner; + @Override - public KafkaSink genStreamSink(AbstractTargetTableInfo targetTableInfo) { + public KafkaSink genStreamSink(TargetTableInfo targetTableInfo) { KafkaSinkTableInfo kafkaSinkTableInfo = (KafkaSinkTableInfo) targetTableInfo; - - Properties kafkaProperties = getKafkaProperties(kafkaSinkTableInfo); - this.tableName = kafkaSinkTableInfo.getName(); - this.updateMode = kafkaSinkTableInfo.getUpdateMode(); this.topic = kafkaSinkTableInfo.getTopic(); - this.partitioner = Optional.of(new CustomerFlinkPartition<>()); - this.partitionKeys = getPartitionKeys(kafkaSinkTableInfo); + + properties = new Properties(); + properties.setProperty("bootstrap.servers", kafkaSinkTableInfo.getBootstrapServers()); + + for (String key : kafkaSinkTableInfo.getKafkaParamKeys()) { + properties.setProperty(key, kafkaSinkTableInfo.getKafkaParam(key)); + } + this.partitioner = Optional.of(new FlinkFixedPartitioner<>()); this.fieldNames = kafkaSinkTableInfo.getFields(); - this.fieldTypes = getTypeInformations(kafkaSinkTableInfo); - this.schema = buildTableSchema(fieldNames, fieldTypes); - this.parallelism = kafkaSinkTableInfo.getParallelism(); - this.sinkOperatorName = SINK_OPERATOR_NAME_TPL.replace("${topic}", topic).replace("${table}", tableName); - this.kafkaProducer011 = new KafkaProducerFactory().createKafkaProducer(kafkaSinkTableInfo, getOutputType(), kafkaProperties, partitioner, partitionKeys); + TypeInformation[] types = new TypeInformation[kafkaSinkTableInfo.getFields().length]; + for (int i = 0; i < kafkaSinkTableInfo.getFieldClasses().length; i++) { + types[i] = TypeInformation.of(kafkaSinkTableInfo.getFieldClasses()[i]); + } + this.fieldTypes = types; + + TableSchema.Builder schemaBuilder = TableSchema.builder(); + for (int i=0;i getRecordType() { + return new RowTypeInfo(fieldTypes, fieldNames); + } + + @Override + public void emitDataStream(DataStream> dataStream) { + KafkaTableSinkBase kafkaTableSink = new CustomerKafkaJsonTableSink( + schema, + topic, + properties, + partitioner, + serializationSchema + ); + + DataStream ds = dataStream.map((Tuple2 record) -> { + return record.f1; + }).returns(getOutputType().getTypeAt(1)).setParallelism(parallelism); + + kafkaTableSink.emitDataStream(ds); + } + + @Override + public TupleTypeInfo> getOutputType() { + return new TupleTypeInfo(org.apache.flink.table.api.Types.BOOLEAN(), new RowTypeInfo(fieldTypes, fieldNames)); + } + + @Override + public String[] getFieldNames() { + return fieldNames; + } + + @Override + public TypeInformation[] getFieldTypes() { + return fieldTypes; + } + + @Override + public TableSink> configure(String[] fieldNames, TypeInformation[] fieldTypes) { + this.fieldNames = fieldNames; + this.fieldTypes = fieldTypes; return this; } } diff --git a/kafka-base/kafka-base-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/table/KafkaSinkParser.java b/kafka/kafka-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/table/KafkaSinkParser.java similarity index 59% rename from kafka-base/kafka-base-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/table/KafkaSinkParser.java rename to kafka/kafka-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/table/KafkaSinkParser.java index 4ad8947a8..f633c8112 100644 --- a/kafka-base/kafka-base-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/table/KafkaSinkParser.java +++ b/kafka/kafka-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/table/KafkaSinkParser.java @@ -18,45 +18,36 @@ package com.dtstack.flink.sql.sink.kafka.table; -import com.dtstack.flink.sql.enums.EUpdateMode; -import com.dtstack.flink.sql.format.FormatType; -import com.dtstack.flink.sql.table.AbstractTableParser; -import com.dtstack.flink.sql.table.AbstractTableInfo; +import com.dtstack.flink.sql.table.AbsTableParser; +import com.dtstack.flink.sql.table.TableInfo; import com.dtstack.flink.sql.util.MathUtil; import java.util.Map; /** - * Date: 2018/12/18 - * Company: www.dtstack.com - * - * @author DocLi - * @modifyer maqi - */ -public class KafkaSinkParser extends AbstractTableParser { + * @author: chuixue + * @create: 2019-11-05 11:46 + * @description: + **/ +public class KafkaSinkParser extends AbsTableParser { @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { + public TableInfo getTableInfo(String tableName, String fieldsInfo, Map props) throws Exception { KafkaSinkTableInfo kafkaSinkTableInfo = new KafkaSinkTableInfo(); kafkaSinkTableInfo.setName(tableName); - kafkaSinkTableInfo.setType(MathUtil.getString(props.get(KafkaSinkTableInfo.TYPE_KEY.toLowerCase()))); - parseFieldsInfo(fieldsInfo, kafkaSinkTableInfo); + kafkaSinkTableInfo.setParallelism(MathUtil.getIntegerVal(props.get(KafkaSinkTableInfo.PARALLELISM_KEY.toLowerCase()))); if (props.get(KafkaSinkTableInfo.SINK_DATA_TYPE) != null) { kafkaSinkTableInfo.setSinkDataType(props.get(KafkaSinkTableInfo.SINK_DATA_TYPE).toString()); - } else { - kafkaSinkTableInfo.setSinkDataType(FormatType.JSON.name()); } - kafkaSinkTableInfo.setSchemaString(MathUtil.getString(props.get(KafkaSinkTableInfo.SCHEMA_STRING_KEY.toLowerCase()))); - kafkaSinkTableInfo.setFieldDelimiter(MathUtil.getString(props.getOrDefault(KafkaSinkTableInfo.CSV_FIELD_DELIMITER_KEY.toLowerCase(), ","))); +// if (props.get(KafkaSinkTableInfo.FIELD_DELINITER) != null) { +// kafka11SinkTableInfo.setFieldDelimiter(props.get(KafkaSinkTableInfo.FIELD_DELINITER).toString()); +// } + kafkaSinkTableInfo.setBootstrapServers(MathUtil.getString(props.get(KafkaSinkTableInfo.BOOTSTRAPSERVERS_KEY.toLowerCase()))); kafkaSinkTableInfo.setTopic(MathUtil.getString(props.get(KafkaSinkTableInfo.TOPIC_KEY.toLowerCase()))); - kafkaSinkTableInfo.setEnableKeyPartition(MathUtil.getString(props.get(KafkaSinkTableInfo.ENABLE_KEY_PARTITION_KEY.toLowerCase()))); - kafkaSinkTableInfo.setPartitionKeys(MathUtil.getString(props.get(KafkaSinkTableInfo.PARTITION_KEY.toLowerCase()))); - kafkaSinkTableInfo.setUpdateMode(MathUtil.getString(props.getOrDefault(KafkaSinkTableInfo.UPDATE_KEY.toLowerCase(), EUpdateMode.APPEND.name()))); - Integer parallelism = MathUtil.getIntegerVal(props.get(KafkaSinkTableInfo.PARALLELISM_KEY.toLowerCase())); kafkaSinkTableInfo.setParallelism(parallelism); @@ -69,4 +60,4 @@ public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map kafkaParam = new HashMap(); + + private String topic; + + + public void addKafkaParam(String key,String value){ + kafkaParam.put(key,value); + } + + public String getKafkaParam(String key){ + return kafkaParam.get(key); + } + + public Set getKafkaParamKeys(){ + return kafkaParam.keySet(); + } + + + public String getBootstrapServers() { + return bootstrapServers; + } + + public void setBootstrapServers(String bootstrapServers) { + this.bootstrapServers = bootstrapServers; + } + + public String getTopic() { + return topic; + } + + public void setTopic(String topic) { + this.topic = topic; + } + + + @Override + public boolean check() { + Preconditions.checkNotNull(bootstrapServers, "kafka of bootstrapServers is required"); + Preconditions.checkNotNull(topic, "kafka of topic is required"); + //Preconditions.checkNotNull(kafkaParam.get("groupId"), "kafka of groupId is required"); + return false; + } + + @Override + public String getType() { + return super.getType(); + } +} diff --git a/kafka/kafka-sink/src/test/java/com/dtstack/flink/sql/sink/kafka/KafkaProducerFactoryTest.java b/kafka/kafka-sink/src/test/java/com/dtstack/flink/sql/sink/kafka/KafkaProducerFactoryTest.java deleted file mode 100644 index 8e869f48f..000000000 --- a/kafka/kafka-sink/src/test/java/com/dtstack/flink/sql/sink/kafka/KafkaProducerFactoryTest.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.dtstack.flink.sql.sink.kafka; - -import com.dtstack.flink.sql.sink.kafka.table.KafkaSinkTableInfo; -import com.google.common.collect.Sets; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.api.java.typeutils.TupleTypeInfo; -import org.apache.flink.streaming.connectors.kafka.partitioner.FlinkKafkaPartitioner; -import org.apache.kafka.clients.consumer.ConsumerConfig; -import org.junit.Test; - -import java.util.Optional; -import java.util.Properties; -import java.util.stream.IntStream; - -import static org.mockito.Mockito.*; - -public class KafkaProducerFactoryTest { - - @Test - public void mockCreateKafkaProducer(){ - KafkaSinkTableInfo kafkaSinkTableInfo = mock(KafkaSinkTableInfo.class); - when(kafkaSinkTableInfo.getName()).thenReturn("roc"); - when(kafkaSinkTableInfo.getTopic()).thenReturn("topic"); - when(kafkaSinkTableInfo.getBootstrapServers()).thenReturn("localhost"); - when(kafkaSinkTableInfo.getKafkaParamKeys()).thenReturn(Sets.newHashSet("aa")); - when(kafkaSinkTableInfo.getKafkaParam("aa")).thenReturn("xx"); - when(kafkaSinkTableInfo.getPartitionKeys()).thenReturn(null); - when(kafkaSinkTableInfo.getFields()).thenReturn(new String[]{"aa"}); - when(kafkaSinkTableInfo.getFieldClasses()).thenReturn(new Class[]{String.class}); - when(kafkaSinkTableInfo.getParallelism()).thenReturn(1); - when(kafkaSinkTableInfo.getSinkDataType()).thenReturn("json"); - when(kafkaSinkTableInfo.getUpdateMode()).thenReturn("append"); - - TypeInformation typeInformation = new TupleTypeInfo(new RowTypeInfo(getTypeInformations(kafkaSinkTableInfo), new String[]{"ss"})); - - Properties properties = getKafkaProperties(kafkaSinkTableInfo); - - FlinkKafkaPartitioner partitioner = mock(FlinkKafkaPartitioner.class); - - KafkaProducerFactory kafkaProducerFactory = new KafkaProducerFactory(); - KafkaProducerFactory kafkaProducerFactorySpy = spy(kafkaProducerFactory); - kafkaProducerFactorySpy.createKafkaProducer(kafkaSinkTableInfo, typeInformation, properties, Optional.of(partitioner), null); - verify(kafkaProducerFactorySpy).createKafkaProducer(kafkaSinkTableInfo, typeInformation, properties, Optional.of(partitioner), null); - } - - protected TypeInformation[] getTypeInformations(KafkaSinkTableInfo kafka11SinkTableInfo) { - Class[] fieldClasses = kafka11SinkTableInfo.getFieldClasses(); - TypeInformation[] types = IntStream.range(0, fieldClasses.length) - .mapToObj(i -> TypeInformation.of(fieldClasses[i])) - .toArray(TypeInformation[]::new); - return types; - } - - protected Properties getKafkaProperties(KafkaSinkTableInfo KafkaSinkTableInfo) { - Properties props = new Properties(); - props.setProperty(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, KafkaSinkTableInfo.getBootstrapServers()); - - for (String key : KafkaSinkTableInfo.getKafkaParamKeys()) { - props.setProperty(key, KafkaSinkTableInfo.getKafkaParam(key)); - } - return props; - } - -} diff --git a/kafka/kafka-sink/src/test/java/com/dtstack/flink/sql/sink/kafka/KafkaProduerTest.java b/kafka/kafka-sink/src/test/java/com/dtstack/flink/sql/sink/kafka/KafkaProduerTest.java deleted file mode 100644 index 918e1dc30..000000000 --- a/kafka/kafka-sink/src/test/java/com/dtstack/flink/sql/sink/kafka/KafkaProduerTest.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.dtstack.flink.sql.sink.kafka; - -import org.junit.Test; - -public class KafkaProduerTest { - - @Test - public void mockOpen(){ - - } - -} diff --git a/kafka/kafka-sink/src/test/java/com/dtstack/flink/sql/sink/kafka/KafkaSinkTest.java b/kafka/kafka-sink/src/test/java/com/dtstack/flink/sql/sink/kafka/KafkaSinkTest.java deleted file mode 100644 index 648b15b26..000000000 --- a/kafka/kafka-sink/src/test/java/com/dtstack/flink/sql/sink/kafka/KafkaSinkTest.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.dtstack.flink.sql.sink.kafka; - -import com.dtstack.flink.sql.sink.kafka.table.KafkaSinkTableInfo; -import com.google.common.collect.Sets; -import org.junit.Test; -import static org.mockito.Mockito.*; - -public class KafkaSinkTest { - - @Test - public void mockGenStreamSink(){ - KafkaSinkTableInfo kafkaSinkTableInfo = mock(KafkaSinkTableInfo.class); - when(kafkaSinkTableInfo.getName()).thenReturn("roc"); - when(kafkaSinkTableInfo.getTopic()).thenReturn("topic"); - when(kafkaSinkTableInfo.getBootstrapServers()).thenReturn("localhost"); - when(kafkaSinkTableInfo.getKafkaParamKeys()).thenReturn(Sets.newHashSet("aa")); - when(kafkaSinkTableInfo.getKafkaParam("aa")).thenReturn("xx"); - when(kafkaSinkTableInfo.getPartitionKeys()).thenReturn(null); - when(kafkaSinkTableInfo.getFields()).thenReturn(new String[]{"aa"}); - when(kafkaSinkTableInfo.getFieldClasses()).thenReturn(new Class[]{String.class}); - when(kafkaSinkTableInfo.getParallelism()).thenReturn(1); - when(kafkaSinkTableInfo.getSinkDataType()).thenReturn("json"); - when(kafkaSinkTableInfo.getUpdateMode()).thenReturn("append"); - - KafkaSink kafkaSink = new KafkaSink(); - KafkaSink kafkaSinkSpy = spy(kafkaSink); - kafkaSinkSpy.genStreamSink(kafkaSinkTableInfo); - } -} diff --git a/kafka/kafka-source/pom.xml b/kafka/kafka-source/pom.xml index 6415ec06a..55ca950fb 100644 --- a/kafka/kafka-source/pom.xml +++ b/kafka/kafka-source/pom.xml @@ -15,13 +15,7 @@ kafka-source http://maven.apache.org - - - sql.source.kafka-base - com.dtstack.flink - 1.0-SNAPSHOT - - + @@ -36,7 +30,6 @@ shade - false org.slf4j @@ -70,14 +63,14 @@ - + - + diff --git a/kafka/kafka-source/src/main/java/com/dtstack/flink/sql/source/kafka/CustomerJsonDeserialization.java b/kafka/kafka-source/src/main/java/com/dtstack/flink/sql/source/kafka/CustomerJsonDeserialization.java new file mode 100644 index 000000000..6d3e57957 --- /dev/null +++ b/kafka/kafka-source/src/main/java/com/dtstack/flink/sql/source/kafka/CustomerJsonDeserialization.java @@ -0,0 +1,280 @@ +/* + * 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 com.dtstack.flink.sql.source.kafka; + +import com.dtstack.flink.sql.source.AbsDeserialization; +import com.dtstack.flink.sql.source.kafka.metric.KafkaTopicPartitionLagMetric; +import com.dtstack.flink.sql.table.TableInfo; +import org.apache.flink.api.common.typeinfo.TypeInformation; +import org.apache.flink.api.common.typeinfo.Types; +import org.apache.flink.api.java.typeutils.RowTypeInfo; +import org.apache.flink.calcite.shaded.com.google.common.base.Strings; +import org.apache.flink.metrics.MetricGroup; +import org.apache.flink.shaded.guava18.com.google.common.collect.Maps; +import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.core.JsonProcessingException; +import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.JsonNode; +import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.node.ArrayNode; +import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.node.JsonNodeType; +import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.node.TextNode; +import org.apache.flink.streaming.connectors.kafka.internal.KafkaConsumerThread; +import org.apache.flink.streaming.connectors.kafka.internals.AbstractFetcher; +import org.apache.flink.types.Row; +import org.apache.kafka.clients.consumer.KafkaConsumer; +import org.apache.kafka.clients.consumer.internals.SubscriptionState; +import org.apache.kafka.common.TopicPartition; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.lang.reflect.Field; +import java.sql.Date; +import java.sql.Time; +import java.sql.Timestamp; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static com.dtstack.flink.sql.metric.MetricConstant.*; + +/** + * @author: chuixue + * @create: 2019-11-05 10:57 + * @description: + **/ +public class CustomerJsonDeserialization extends AbsDeserialization { + + private static final Logger LOG = LoggerFactory.getLogger(CustomerJsonDeserialization.class); + + private static final long serialVersionUID = 2385115520960444192L; + + private static int dirtyDataFrequency = 1000; + + private final ObjectMapper objectMapper = new ObjectMapper(); + + /** Type information describing the result type. */ + private final TypeInformation typeInfo; + + /** Field names to parse. Indices match fieldTypes indices. */ + private final String[] fieldNames; + + /** Types to parse fields as. Indices match fieldNames indices. */ + private final TypeInformation[] fieldTypes; + + private AbstractFetcher fetcher; + + private boolean firstMsg = true; + + private Map nodeAndJsonNodeMapping = Maps.newHashMap(); + + private Map rowAndFieldMapping; + + private List fieldExtraInfos; + + public CustomerJsonDeserialization(TypeInformation typeInfo, Map rowAndFieldMapping, List fieldExtraInfos){ + this.typeInfo = typeInfo; + this.fieldNames = ((RowTypeInfo) typeInfo).getFieldNames(); + this.fieldTypes = ((RowTypeInfo) typeInfo).getFieldTypes(); + this.rowAndFieldMapping= rowAndFieldMapping; + this.fieldExtraInfos = fieldExtraInfos; + } + + @Override + public Row deserialize(byte[] message) throws IOException { + + if(firstMsg){ + try { + registerPtMetric(fetcher); + } catch (Exception e) { + LOG.error("register topic partition metric error.", e); + } + + firstMsg = false; + } + + try { + JsonNode root = objectMapper.readTree(message); + + if (numInRecord.getCount() % dirtyDataFrequency == 0) { + LOG.info(root.toString()); + } + + numInRecord.inc(); + numInBytes.inc(message.length); + + parseTree(root, null); + Row row = new Row(fieldNames.length); + + for (int i = 0; i < fieldNames.length; i++) { + JsonNode node = getIgnoreCase(fieldNames[i]); + TableInfo.FieldExtraInfo fieldExtraInfo = fieldExtraInfos.get(i); + + if (node == null) { + if (fieldExtraInfo != null && fieldExtraInfo.getNotNull()) { + throw new IllegalStateException("Failed to find field with name '" + + fieldNames[i] + "'."); + } else { + row.setField(i, null); + } + } else { + // Read the value as specified type + + Object value = convert(node, fieldTypes[i]); + row.setField(i, value); + } + } + + numInResolveRecord.inc(); + return row; + } catch (Exception e) { + //add metric of dirty data + if (dirtyDataCounter.getCount() % dirtyDataFrequency == 0) { + LOG.info("dirtyData: " + new String(message)); + LOG.error("" , e); + } + dirtyDataCounter.inc(); + return null; + }finally { + nodeAndJsonNodeMapping.clear(); + } + } + + public JsonNode getIgnoreCase(String key) { + String nodeMappingKey = rowAndFieldMapping.getOrDefault(key, key); + return nodeAndJsonNodeMapping.get(nodeMappingKey); + } + + private void parseTree(JsonNode jsonNode, String prefix){ + if (jsonNode.isArray()) { + ArrayNode array = (ArrayNode) jsonNode; + for (int i = 0; i < array.size(); i++) { + JsonNode child = array.get(i); + String nodeKey = getNodeKey(prefix, i); + + if (child.isValueNode()) { + nodeAndJsonNodeMapping.put(nodeKey, child); + } else { + if (rowAndFieldMapping.containsValue(nodeKey)) { + nodeAndJsonNodeMapping.put(nodeKey, child); + } + parseTree(child, nodeKey); + } + } + return; + } + + Iterator iterator = jsonNode.fieldNames(); + while (iterator.hasNext()){ + String next = iterator.next(); + JsonNode child = jsonNode.get(next); + String nodeKey = getNodeKey(prefix, next); + + if (child.isValueNode()){ + nodeAndJsonNodeMapping.put(nodeKey, child); + }else if(child.isArray()){ + parseTree(child, nodeKey); + }else { + parseTree(child, nodeKey); + } + } + } + + private String getNodeKey(String prefix, String nodeName){ + if(Strings.isNullOrEmpty(prefix)){ + return nodeName; + } + + return prefix + "." + nodeName; + } + + private String getNodeKey(String prefix, int i) { + if (Strings.isNullOrEmpty(prefix)) { + return "[" + i + "]"; + } + return prefix + "[" + i + "]"; + } + + public void setFetcher(AbstractFetcher fetcher) { + this.fetcher = fetcher; + } + + protected void registerPtMetric(AbstractFetcher fetcher) throws Exception { + + Field consumerThreadField = fetcher.getClass().getSuperclass().getDeclaredField("consumerThread"); + consumerThreadField.setAccessible(true); + KafkaConsumerThread consumerThread = (KafkaConsumerThread) consumerThreadField.get(fetcher); + + Field hasAssignedPartitionsField = consumerThread.getClass().getDeclaredField("hasAssignedPartitions"); + hasAssignedPartitionsField.setAccessible(true); + + //wait until assignedPartitions + + boolean hasAssignedPartitions = (boolean) hasAssignedPartitionsField.get(consumerThread); + + if(!hasAssignedPartitions){ + throw new RuntimeException("wait 50 secs, but not assignedPartitions"); + } + + Field consumerField = consumerThread.getClass().getDeclaredField("consumer"); + consumerField.setAccessible(true); + + KafkaConsumer kafkaConsumer = (KafkaConsumer) consumerField.get(consumerThread); + Field subscriptionStateField = kafkaConsumer.getClass().getDeclaredField("subscriptions"); + subscriptionStateField.setAccessible(true); + + //topic partitions lag + SubscriptionState subscriptionState = (SubscriptionState) subscriptionStateField.get(kafkaConsumer); + Set assignedPartitions = subscriptionState.assignedPartitions(); + for(TopicPartition topicPartition : assignedPartitions){ + MetricGroup metricGroup = getRuntimeContext().getMetricGroup().addGroup(DT_TOPIC_GROUP, topicPartition.topic()) + .addGroup(DT_PARTITION_GROUP, topicPartition.partition() + ""); + metricGroup.gauge(DT_TOPIC_PARTITION_LAG_GAUGE, new KafkaTopicPartitionLagMetric(subscriptionState, topicPartition)); + } + + } + + private static String partitionLagMetricName(TopicPartition tp) { + return tp + ".records-lag"; + } + + private Object convert(JsonNode node, TypeInformation info) { + if (info.getTypeClass().equals(Types.BOOLEAN.getTypeClass())) { + return node.asBoolean(); + } else if (info.getTypeClass().equals(Types.STRING.getTypeClass())) { + return node.asText(); + } else if (info.getTypeClass().equals(Types.SQL_DATE.getTypeClass())) { + return Date.valueOf(node.asText()); + } else if (info.getTypeClass().equals(Types.SQL_TIME.getTypeClass())) { + // local zone + return Time.valueOf(node.asText()); + } else if (info.getTypeClass().equals(Types.SQL_TIMESTAMP.getTypeClass())) { + // local zone + return Timestamp.valueOf(node.asText()); + } else { + // for types that were specified without JSON schema + // e.g. POJOs + try { + return objectMapper.treeToValue(node, info.getTypeClass()); + } catch (JsonProcessingException e) { + throw new IllegalStateException("Unsupported type information '" + info + "' for node: " + node); + } + } + } +} diff --git a/kafka/kafka-source/src/main/java/com/dtstack/flink/sql/source/kafka/CustomerKafkaConsumer.java b/kafka/kafka-source/src/main/java/com/dtstack/flink/sql/source/kafka/CustomerKafkaConsumer.java new file mode 100644 index 000000000..7d35a35b3 --- /dev/null +++ b/kafka/kafka-source/src/main/java/com/dtstack/flink/sql/source/kafka/CustomerKafkaConsumer.java @@ -0,0 +1,72 @@ +/* + * 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 com.dtstack.flink.sql.source.kafka; + +import com.dtstack.flink.sql.source.AbsDeserialization; +import org.apache.flink.metrics.MetricGroup; +import org.apache.flink.streaming.api.functions.AssignerWithPeriodicWatermarks; +import org.apache.flink.streaming.api.functions.AssignerWithPunctuatedWatermarks; +import org.apache.flink.streaming.api.operators.StreamingRuntimeContext; +import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer; +import org.apache.flink.streaming.connectors.kafka.config.OffsetCommitMode; +import org.apache.flink.streaming.connectors.kafka.internals.AbstractFetcher; +import org.apache.flink.streaming.connectors.kafka.internals.KafkaTopicPartition; +import org.apache.flink.types.Row; +import org.apache.flink.util.SerializedValue; + +import java.util.Arrays; +import java.util.Map; +import java.util.Properties; +import java.util.regex.Pattern; + +/** + * @author: chuixue + * @create: 2019-11-05 10:58 + * @description: + **/ +public class CustomerKafkaConsumer extends FlinkKafkaConsumer { + + private static final long serialVersionUID = -2265366268827807739L; + + private CustomerJsonDeserialization customerJsonDeserialization; + + public CustomerKafkaConsumer(String topic, AbsDeserialization valueDeserializer, Properties props) { + super(Arrays.asList(topic.split(",")), valueDeserializer, props); + this.customerJsonDeserialization = (CustomerJsonDeserialization) valueDeserializer; + } + + public CustomerKafkaConsumer(Pattern subscriptionPattern, AbsDeserialization valueDeserializer, Properties props) { + super(subscriptionPattern, valueDeserializer, props); + this.customerJsonDeserialization = (CustomerJsonDeserialization) valueDeserializer; + } + + @Override + public void run(SourceContext sourceContext) throws Exception { + customerJsonDeserialization.setRuntimeContext(getRuntimeContext()); + customerJsonDeserialization.initMetric(); + super.run(sourceContext); + } + + @Override + protected AbstractFetcher createFetcher(SourceContext sourceContext, Map assignedPartitionsWithInitialOffsets, SerializedValue> watermarksPeriodic, SerializedValue> watermarksPunctuated, StreamingRuntimeContext runtimeContext, OffsetCommitMode offsetCommitMode, MetricGroup consumerMetricGroup, boolean useMetrics) throws Exception { + AbstractFetcher fetcher = super.createFetcher(sourceContext, assignedPartitionsWithInitialOffsets, watermarksPeriodic, watermarksPunctuated, runtimeContext, offsetCommitMode, consumerMetricGroup, useMetrics); + customerJsonDeserialization.setFetcher(fetcher); + return fetcher; + } +} diff --git a/kafka/kafka-source/src/main/java/com/dtstack/flink/sql/source/kafka/KafkaConsumer.java b/kafka/kafka-source/src/main/java/com/dtstack/flink/sql/source/kafka/KafkaConsumer.java deleted file mode 100644 index 32f1e6d2f..000000000 --- a/kafka/kafka-source/src/main/java/com/dtstack/flink/sql/source/kafka/KafkaConsumer.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.source.kafka; - -import com.dtstack.flink.sql.format.DeserializationMetricWrapper; -import com.dtstack.flink.sql.source.kafka.deserialization.DtKafkaDeserializationSchemaWrapper; -import com.dtstack.flink.sql.source.kafka.deserialization.KafkaDeserializationMetricWrapper; -import com.dtstack.flink.sql.source.kafka.sample.OffsetFetcher; -import com.dtstack.flink.sql.source.kafka.sample.OffsetMap; -import com.dtstack.flink.sql.source.kafka.sample.SampleCalculateHelper; -import org.apache.commons.lang3.StringUtils; -import org.apache.flink.api.common.serialization.DeserializationSchema; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.metrics.MetricGroup; -import org.apache.flink.streaming.api.functions.AssignerWithPeriodicWatermarks; -import org.apache.flink.streaming.api.functions.AssignerWithPunctuatedWatermarks; -import org.apache.flink.streaming.api.functions.source.SourceFunction; -import org.apache.flink.streaming.api.operators.StreamingRuntimeContext; -import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer; -import org.apache.flink.streaming.connectors.kafka.config.OffsetCommitMode; -import org.apache.flink.streaming.connectors.kafka.internals.AbstractFetcher; -import org.apache.flink.streaming.connectors.kafka.internals.KafkaTopicPartition; -import org.apache.flink.types.Row; -import org.apache.flink.util.SerializedValue; -import org.apache.kafka.common.PartitionInfo; -import org.apache.kafka.common.TopicPartition; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.regex.Pattern; - - -/** - * Reason: - * Date: 2018/10/19 - * Company: www.dtstack.com - * @author xuchao - */ -public class KafkaConsumer extends FlinkKafkaConsumer implements OffsetFetcher { - - private final DeserializationMetricWrapper deserializationMetricWrapper; - - private String topic; - - private final Properties props; - - private final Long sampleSize; - - public KafkaConsumer( - String topic, - Long sampleSize, - DeserializationMetricWrapper deserializationMetricWrapper, - Properties props) { - super( - Arrays.asList(StringUtils.split(topic, ",")), - new DtKafkaDeserializationSchemaWrapper<>(deserializationMetricWrapper), - props); - this.topic = topic; - this.props = props; - this.sampleSize = sampleSize; - this.deserializationMetricWrapper = deserializationMetricWrapper; - } - - public KafkaConsumer( - Pattern subscriptionPattern, - Long sampleSize, - DeserializationMetricWrapper deserializationMetricWrapper, - Properties props) { - super( - subscriptionPattern, - new DtKafkaDeserializationSchemaWrapper<>(deserializationMetricWrapper), - props); - this.sampleSize = sampleSize; - this.props = props; - this.deserializationMetricWrapper = deserializationMetricWrapper; - } - - @Override - public void run(SourceFunction.SourceContext sourceContext) throws Exception { - deserializationMetricWrapper.setRuntimeContext(getRuntimeContext()); - deserializationMetricWrapper.initMetric(); - super.run(sourceContext); - } - - @Override - protected AbstractFetcher createFetcher(SourceFunction.SourceContext sourceContext, - Map assignedPartitionsWithInitialOffsets, - SerializedValue> watermarksPeriodic, - SerializedValue> watermarksPunctuated, - StreamingRuntimeContext runtimeContext, - OffsetCommitMode offsetCommitMode, - MetricGroup consumerMetricGroup, - boolean useMetrics) throws Exception { - - final OffsetMap offsetMap = sampleSize > 0 ? seekOffset(props, topic) : new OffsetMap(); - Map rebuild; - - rebuild = - sampleSize > 0 - ? SampleCalculateHelper.rebuildAssignedPartitionsWithInitialOffsets( - offsetMap, sampleSize, assignedPartitionsWithInitialOffsets) - : assignedPartitionsWithInitialOffsets; - - AbstractFetcher fetcher = - super.createFetcher( - sourceContext, - rebuild, - watermarksPeriodic, - watermarksPunctuated, - runtimeContext, - offsetCommitMode, - consumerMetricGroup, - useMetrics); - ((KafkaDeserializationMetricWrapper) deserializationMetricWrapper).setFetcher(fetcher); - ((DtKafkaDeserializationSchemaWrapper) deserializer).setSpecificEndOffsets(offsetMap); - return fetcher; - } - - @Override - public TypeInformation getProducedType() { - DeserializationSchema deserializationSchema = deserializationMetricWrapper.getDeserializationSchema(); - return deserializationSchema.getProducedType(); - } - - @Override - public OffsetMap fetchOffset( - org.apache.kafka.clients.consumer.KafkaConsumer consumer, String topic) { - OffsetMap offsetMap = new OffsetMap(); - - List topicPartitions = new ArrayList<>(); - - consumer.subscribe(Collections.singleton(topic)); - List partitionInfos = consumer.partitionsFor(topic); - - partitionInfos.forEach( - item -> topicPartitions.add(new TopicPartition(topic, item.partition()))); - - Map beginningOffsets = consumer.beginningOffsets(topicPartitions); - beginningOffsets - .keySet() - .forEach( - item -> - offsetMap.setEarliest( - new KafkaTopicPartition(topic, item.partition()), - beginningOffsets.get(item))); - - Map endOffsets = consumer.endOffsets(topicPartitions); - endOffsets - .keySet() - .forEach( - item -> - offsetMap.setLatest( - new KafkaTopicPartition(topic, item.partition()), - endOffsets.get(item))); - - return offsetMap; - } -} \ No newline at end of file diff --git a/kafka/kafka-source/src/main/java/com/dtstack/flink/sql/source/kafka/KafkaConsumerFactory.java b/kafka/kafka-source/src/main/java/com/dtstack/flink/sql/source/kafka/KafkaConsumerFactory.java deleted file mode 100644 index 0bf951d6e..000000000 --- a/kafka/kafka-source/src/main/java/com/dtstack/flink/sql/source/kafka/KafkaConsumerFactory.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.source.kafka; - -import com.dtstack.flink.sql.format.DeserializationMetricWrapper; -import com.dtstack.flink.sql.source.kafka.table.KafkaSourceTableInfo; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumerBase; -import org.apache.flink.types.Row; -import org.apache.kafka.common.requests.IsolationLevel; - -import java.io.Serializable; -import java.util.Properties; -import java.util.regex.Pattern; - -/** - * company: www.dtstack.com - * - * @author: toutian - * create: 2019/12/24 - */ -public class KafkaConsumerFactory extends AbstractKafkaConsumerFactory { - - @Override - public FlinkKafkaConsumerBase createKafkaTableSource(KafkaSourceTableInfo kafkaSourceTableInfo, TypeInformation typeInformation, Properties props) { - KafkaConsumer kafkaSrc; - if (kafkaSourceTableInfo.getTopicIsPattern()) { - DeserializationMetricWrapper deserMetricWrapper = createDeserializationMetricWrapper(kafkaSourceTableInfo, typeInformation, (Calculate & Serializable) (subscriptionState, tp) -> subscriptionState.partitionLag(tp, IsolationLevel.READ_UNCOMMITTED)); - kafkaSrc = - new KafkaConsumer( - Pattern.compile(kafkaSourceTableInfo.getTopic()), - kafkaSourceTableInfo.getSampleSize(), - deserMetricWrapper, - props); - } else { - DeserializationMetricWrapper deserMetricWrapper = createDeserializationMetricWrapper(kafkaSourceTableInfo, typeInformation, (Calculate & Serializable) (subscriptionState, tp) -> subscriptionState.partitionLag(tp, IsolationLevel.READ_UNCOMMITTED)); - kafkaSrc = - new KafkaConsumer( - kafkaSourceTableInfo.getTopic(), - kafkaSourceTableInfo.getSampleSize(), - deserMetricWrapper, - props); - } - return kafkaSrc; - } - -} diff --git a/kafka/kafka-source/src/main/java/com/dtstack/flink/sql/source/kafka/KafkaSource.java b/kafka/kafka-source/src/main/java/com/dtstack/flink/sql/source/kafka/KafkaSource.java index 022a4ce3c..c26d99b62 100644 --- a/kafka/kafka-source/src/main/java/com/dtstack/flink/sql/source/kafka/KafkaSource.java +++ b/kafka/kafka-source/src/main/java/com/dtstack/flink/sql/source/kafka/KafkaSource.java @@ -18,42 +18,105 @@ package com.dtstack.flink.sql.source.kafka; +import com.dtstack.flink.sql.source.IStreamSourceGener; import com.dtstack.flink.sql.source.kafka.table.KafkaSourceTableInfo; -import com.dtstack.flink.sql.table.AbstractSourceTableInfo; +import com.dtstack.flink.sql.table.SourceTableInfo; +import com.dtstack.flink.sql.util.DtStringUtil; +import com.dtstack.flink.sql.util.PluginUtil; +import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; import org.apache.flink.api.common.typeinfo.TypeInformation; +import org.apache.flink.api.java.typeutils.RowTypeInfo; import org.apache.flink.streaming.api.datastream.DataStreamSource; import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer; +import org.apache.flink.streaming.connectors.kafka.internals.KafkaTopicPartition; import org.apache.flink.table.api.Table; import org.apache.flink.table.api.java.StreamTableEnvironment; import org.apache.flink.types.Row; +import java.util.HashMap; +import java.util.Map; import java.util.Properties; +import java.util.regex.Pattern; /** * @author: chuixue * @create: 2019-11-05 10:55 * @description: **/ -public class KafkaSource extends AbstractKafkaSource { +public class KafkaSource implements IStreamSourceGener

{ + private static final String SOURCE_OPERATOR_NAME_TPL = "${topic}_${table}"; + + /** + * Get kafka data source, you need to provide the data field names, data types + * If you do not specify auto.offset.reset, the default use groupoffset + * + * @param sourceTableInfo + * @return + */ + @SuppressWarnings("rawtypes") @Override - public Table genStreamSource(AbstractSourceTableInfo sourceTableInfo, StreamExecutionEnvironment env, StreamTableEnvironment tableEnv) { + public Table genStreamSource(SourceTableInfo sourceTableInfo, StreamExecutionEnvironment env, StreamTableEnvironment tableEnv) { + KafkaSourceTableInfo kafkaSourceTableInfo = (KafkaSourceTableInfo) sourceTableInfo; String topicName = kafkaSourceTableInfo.getTopic(); - Properties kafkaProperties = getKafkaProperties(kafkaSourceTableInfo); - TypeInformation typeInformation = getRowTypeInformation(kafkaSourceTableInfo); - FlinkKafkaConsumer kafkaSrc = (FlinkKafkaConsumer) new KafkaConsumerFactory().createKafkaTableSource(kafkaSourceTableInfo, typeInformation, kafkaProperties); + Properties props = new Properties(); + props.setProperty("bootstrap.servers", kafkaSourceTableInfo.getBootstrapServers()); + if (DtStringUtil.isJosn(kafkaSourceTableInfo.getOffsetReset())) { + props.setProperty("auto.offset.reset", "none"); + } else { + props.setProperty("auto.offset.reset", kafkaSourceTableInfo.getOffsetReset()); + } + if (StringUtils.isNotBlank(kafkaSourceTableInfo.getGroupId())) { + props.setProperty("group.id", kafkaSourceTableInfo.getGroupId()); + } - String sourceOperatorName = generateOperatorName(sourceTableInfo.getName(), topicName); - DataStreamSource kafkaSource = env.addSource(kafkaSrc, sourceOperatorName, typeInformation); + TypeInformation[] types = new TypeInformation[kafkaSourceTableInfo.getFields().length]; + for (int i = 0; i < kafkaSourceTableInfo.getFieldClasses().length; i++) { + types[i] = TypeInformation.of(kafkaSourceTableInfo.getFieldClasses()[i]); + } + + TypeInformation typeInformation = new RowTypeInfo(types, kafkaSourceTableInfo.getFields()); + + FlinkKafkaConsumer kafkaSrc; + if (BooleanUtils.isTrue(kafkaSourceTableInfo.getTopicIsPattern())) { + kafkaSrc = new CustomerKafkaConsumer(Pattern.compile(topicName), + new CustomerJsonDeserialization(typeInformation, kafkaSourceTableInfo.getPhysicalFields(), kafkaSourceTableInfo.getFieldExtraInfoList()), props); + } else { + kafkaSrc = new CustomerKafkaConsumer(topicName, + new CustomerJsonDeserialization(typeInformation, kafkaSourceTableInfo.getPhysicalFields(), kafkaSourceTableInfo.getFieldExtraInfoList()), props); + } + + //earliest,latest + if ("earliest".equalsIgnoreCase(kafkaSourceTableInfo.getOffsetReset())) { + kafkaSrc.setStartFromEarliest(); + } else if (DtStringUtil.isJosn(kafkaSourceTableInfo.getOffsetReset())) {// {"0":12312,"1":12321,"2":12312} + try { + Properties properties = PluginUtil.jsonStrToObject(kafkaSourceTableInfo.getOffsetReset(), Properties.class); + Map offsetMap = PluginUtil.ObjectToMap(properties); + Map specificStartupOffsets = new HashMap<>(); + for (Map.Entry entry : offsetMap.entrySet()) { + specificStartupOffsets.put(new KafkaTopicPartition(topicName, Integer.valueOf(entry.getKey())), Long.valueOf(entry.getValue().toString())); + } + kafkaSrc.setStartFromSpecificOffsets(specificStartupOffsets); + } catch (Exception e) { + throw new RuntimeException("not support offsetReset type:" + kafkaSourceTableInfo.getOffsetReset()); + } + } else { + kafkaSrc.setStartFromLatest(); + } - setParallelism(kafkaSourceTableInfo.getParallelism(), kafkaSource); - setStartPosition(kafkaSourceTableInfo.getOffsetReset(), topicName, kafkaSrc, () -> kafkaSrc.setStartFromTimestamp(kafkaSourceTableInfo.getTimestampOffset())); String fields = StringUtils.join(kafkaSourceTableInfo.getFields(), ","); + String sourceOperatorName = SOURCE_OPERATOR_NAME_TPL.replace("${topic}", topicName).replace("${table}", sourceTableInfo.getName()); + DataStreamSource kafkaSource = env.addSource(kafkaSrc, sourceOperatorName, typeInformation); + Integer parallelism = kafkaSourceTableInfo.getParallelism(); + if (parallelism != null) { + kafkaSource.setParallelism(parallelism); + } return tableEnv.fromDataStream(kafkaSource, fields); } } diff --git a/kafka/kafka-source/src/main/java/com/dtstack/flink/sql/source/kafka/deserializer/DtKafkaDeserializer.java b/kafka/kafka-source/src/main/java/com/dtstack/flink/sql/source/kafka/deserializer/DtKafkaDeserializer.java deleted file mode 100644 index c9053ffe0..000000000 --- a/kafka/kafka-source/src/main/java/com/dtstack/flink/sql/source/kafka/deserializer/DtKafkaDeserializer.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.source.kafka.deserializer; - -import com.dtstack.flink.sql.source.kafka.table.KafkaSourceTableInfo; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.apache.kafka.common.errors.SerializationException; -import org.apache.kafka.common.header.Headers; -import org.apache.kafka.common.serialization.Deserializer; - -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.Map; - -/** - * Date: 2021/04/20 - * Company: www.dtstack.com - * - * @author tudou - */ -public class DtKafkaDeserializer implements Deserializer { - protected ObjectMapper objectMapper = new ObjectMapper(); - private Deserializer deserializer; - - @Override - @SuppressWarnings("unchecked") - public void configure(Map configs, boolean isKey) { - String deserializerClassName; - if(isKey){ - deserializerClassName = (String)configs.get(KafkaSourceTableInfo.DT_KEY_DESERIALIZER); - }else{ - deserializerClassName = (String)configs.get(KafkaSourceTableInfo.DT_VALUE_DESERIALIZER); - } - try { - this.deserializer = (Deserializer)Class.forName(deserializerClassName).newInstance(); - } catch (Exception e) { - throw new RuntimeException("Can't create instance: " + deserializerClassName, e); - } - this.deserializer.configure(configs, isKey); - } - - @Override - public byte[] deserialize(String topic, Headers headers, byte[] data) { - return toBytes(deserializer.deserialize(topic, headers, data)); - } - - @Override - public byte[] deserialize(String topic, byte[] data) { - return toBytes(deserializer.deserialize(topic, data)); - } - - /** - * T value to byte[] - * @param value - * @return - */ - private byte[] toBytes(T value){ - if(value instanceof byte[]){ - return (byte[])value; - }else{ - try { - return this.objectMapper.readValue(this.objectMapper.writeValueAsBytes(value), String.class).getBytes(StandardCharsets.UTF_8); - } catch (IOException e) { - throw new SerializationException("Can't deserialize data", e); - } - } - } - - @Override - public void close() { - this.deserializer.close(); - } -} diff --git a/kafka-base/kafka-base-source/src/main/java/com/dtstack/flink/sql/source/kafka/Calculate.java b/kafka/kafka-source/src/main/java/com/dtstack/flink/sql/source/kafka/metric/KafkaTopicPartitionLagMetric.java similarity index 57% rename from kafka-base/kafka-base-source/src/main/java/com/dtstack/flink/sql/source/kafka/Calculate.java rename to kafka/kafka-source/src/main/java/com/dtstack/flink/sql/source/kafka/metric/KafkaTopicPartitionLagMetric.java index df399e391..7810056d7 100644 --- a/kafka-base/kafka-base-source/src/main/java/com/dtstack/flink/sql/source/kafka/Calculate.java +++ b/kafka/kafka-source/src/main/java/com/dtstack/flink/sql/source/kafka/metric/KafkaTopicPartitionLagMetric.java @@ -16,18 +16,31 @@ * limitations under the License. */ -package com.dtstack.flink.sql.source.kafka; +package com.dtstack.flink.sql.source.kafka.metric; +import org.apache.flink.metrics.Gauge; import org.apache.kafka.clients.consumer.internals.SubscriptionState; import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.requests.IsolationLevel; /** - * company: www.dtstack.com - * @author: toutian - * create: 2019/12/24 - */ -@FunctionalInterface -public interface Calculate { + * @author: chuixue + * @create: 2019-11-05 11:09 + * @description: + **/ +public class KafkaTopicPartitionLagMetric implements Gauge { + + private SubscriptionState subscriptionState; + + private TopicPartition tp; + + public KafkaTopicPartitionLagMetric(SubscriptionState subscriptionState, TopicPartition tp){ + this.subscriptionState = subscriptionState; + this.tp = tp; + } - Long calc(SubscriptionState subscriptionState, TopicPartition topicPartition); -} \ No newline at end of file + @Override + public Long getValue() { + return subscriptionState.partitionLag(tp, IsolationLevel.READ_UNCOMMITTED); + } +} diff --git a/kafka/kafka-source/src/main/java/com/dtstack/flink/sql/source/kafka/table/KafkaSourceParser.java b/kafka/kafka-source/src/main/java/com/dtstack/flink/sql/source/kafka/table/KafkaSourceParser.java new file mode 100644 index 000000000..a99f49298 --- /dev/null +++ b/kafka/kafka-source/src/main/java/com/dtstack/flink/sql/source/kafka/table/KafkaSourceParser.java @@ -0,0 +1,97 @@ +/* + * 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 com.dtstack.flink.sql.source.kafka.table; + +import com.dtstack.flink.sql.table.AbsSourceParser; +import com.dtstack.flink.sql.table.TableInfo; +import com.dtstack.flink.sql.util.ClassUtil; +import com.dtstack.flink.sql.util.MathUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * @author: chuixue + * @create: 2019-11-05 11:08 + * @description: + **/ +public class KafkaSourceParser extends AbsSourceParser { + + private static final Logger LOG = LoggerFactory.getLogger(KafkaSourceParser.class); + + private static final String KAFKA_NEST_FIELD_KEY = "nestFieldKey"; + + private static Pattern kafkaNestFieldKeyPattern = Pattern.compile("(?i)((@*\\S+\\.)*\\S+)\\s+(\\w+)\\s+AS\\s+(\\w+)(\\s+NOT\\s+NULL)?$"); + + static { + keyPatternMap.put(KAFKA_NEST_FIELD_KEY, kafkaNestFieldKeyPattern); + + keyHandlerMap.put(KAFKA_NEST_FIELD_KEY, KafkaSourceParser::dealNestField); + } + + /** + * add parser for alias field + * + * @param matcher + * @param tableInfo + */ + static void dealNestField(Matcher matcher, TableInfo tableInfo) { + String physicalField = matcher.group(1); + String fieldType = matcher.group(3); + String mappingField = matcher.group(4); + Class fieldClass = ClassUtil.stringConvertClass(fieldType); + boolean notNull = matcher.group(5) != null; + TableInfo.FieldExtraInfo fieldExtraInfo = new TableInfo.FieldExtraInfo(); + fieldExtraInfo.setNotNull(notNull); + + tableInfo.addPhysicalMappings(mappingField, physicalField); + tableInfo.addField(mappingField); + tableInfo.addFieldClass(fieldClass); + tableInfo.addFieldType(fieldType); + tableInfo.addFieldExtraInfo(fieldExtraInfo); + if (LOG.isInfoEnabled()) { + LOG.info(physicalField + "--->" + mappingField + " Class: " + fieldClass.toString()); + } + } + + @Override + public TableInfo getTableInfo(String tableName, String fieldsInfo, Map props) throws Exception { + KafkaSourceTableInfo kafkaSourceTableInfo = new KafkaSourceTableInfo(); + kafkaSourceTableInfo.setName(tableName); + parseFieldsInfo(fieldsInfo, kafkaSourceTableInfo); + + kafkaSourceTableInfo.setParallelism(MathUtil.getIntegerVal(props.get(KafkaSourceTableInfo.PARALLELISM_KEY.toLowerCase()))); + String bootstrapServer = MathUtil.getString(props.get(KafkaSourceTableInfo.BOOTSTRAPSERVERS_KEY.toLowerCase())); + if (bootstrapServer == null || bootstrapServer.trim().equals("")) { + throw new Exception("BootstrapServers can not be empty!"); + } else { + kafkaSourceTableInfo.setBootstrapServers(bootstrapServer); + } + kafkaSourceTableInfo.setGroupId(MathUtil.getString(props.get(KafkaSourceTableInfo.GROUPID_KEY.toLowerCase()))); + kafkaSourceTableInfo.setTopic(MathUtil.getString(props.get(KafkaSourceTableInfo.TOPIC_KEY.toLowerCase()))); + kafkaSourceTableInfo.setOffsetReset(MathUtil.getString(props.get(KafkaSourceTableInfo.OFFSETRESET_KEY.toLowerCase()))); + kafkaSourceTableInfo.setTopicIsPattern(MathUtil.getBoolean(props.get(KafkaSourceTableInfo.TOPICISPATTERN_KEY.toLowerCase()))); + kafkaSourceTableInfo.setTimeZone(MathUtil.getString(props.get(KafkaSourceTableInfo.TIME_ZONE_KEY.toLowerCase()))); + kafkaSourceTableInfo.check(); + return kafkaSourceTableInfo; + } +} diff --git a/kafka/kafka-source/src/main/java/com/dtstack/flink/sql/source/kafka/table/KafkaSourceTableInfo.java b/kafka/kafka-source/src/main/java/com/dtstack/flink/sql/source/kafka/table/KafkaSourceTableInfo.java new file mode 100644 index 000000000..33b704ac0 --- /dev/null +++ b/kafka/kafka-source/src/main/java/com/dtstack/flink/sql/source/kafka/table/KafkaSourceTableInfo.java @@ -0,0 +1,128 @@ +/* + * 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 com.dtstack.flink.sql.source.kafka.table; + +import com.dtstack.flink.sql.table.SourceTableInfo; +import org.apache.flink.calcite.shaded.com.google.common.base.Preconditions; + +/** + * @author: chuixue + * @create: 2019-11-05 11:09 + * @description: + **/ +public class KafkaSourceTableInfo extends SourceTableInfo { + + //version + private static final String CURR_TYPE = "kafka"; + + public static final String BOOTSTRAPSERVERS_KEY = "bootstrapServers"; + + public static final String TOPIC_KEY = "topic"; + + public static final String GROUPID_KEY = "groupId"; + + public static final String OFFSETRESET_KEY = "offsetReset"; + + public static final String TOPICISPATTERN_KEY = "topicIsPattern"; + + private String bootstrapServers; + + private String topic; + + private String groupId; + + private Boolean topicIsPattern = false; + + public Boolean getTopicIsPattern() { + return topicIsPattern; + } + + public void setTopicIsPattern(Boolean topicIsPattern) { + if (topicIsPattern == null) return; + + this.topicIsPattern = topicIsPattern; + } + + //latest, earliest + private String offsetReset = "latest"; + + private String offset; + + public KafkaSourceTableInfo() { + super.setType(CURR_TYPE); + } + + + public String getBootstrapServers() { + return bootstrapServers; + } + + public void setBootstrapServers(String bootstrapServers) { + this.bootstrapServers = bootstrapServers; + } + + public String getTopic() { + return topic; + } + + public void setTopic(String topic) { + this.topic = topic; + } + + public String getGroupId() { + return groupId; + } + + public void setGroupId(String groupId) { + this.groupId = groupId; + } + + public String getOffsetReset() { + return offsetReset; + } + + public void setOffsetReset(String offsetReset) { + if (offsetReset == null) { + return; + } + + this.offsetReset = offsetReset; + } + + public String getOffset() { + return offset; + } + + public void setOffset(String offset) { + this.offset = offset; + } + + @Override + public boolean check() { + Preconditions.checkNotNull(bootstrapServers, "kafka of bootstrapServers is required"); + Preconditions.checkNotNull(topic, "kafka of topic is required"); + return false; + } + + @Override + public String getType() { +// return super.getType() + SOURCE_SUFFIX; + return super.getType(); + } +} diff --git a/kafka/kafka-source/src/main/java/org/apache/flink/streaming/connectors/kafka/FlinkKafkaConsumer.java b/kafka/kafka-source/src/main/java/org/apache/flink/streaming/connectors/kafka/FlinkKafkaConsumer.java deleted file mode 100644 index 64aebe1e6..000000000 --- a/kafka/kafka-source/src/main/java/org/apache/flink/streaming/connectors/kafka/FlinkKafkaConsumer.java +++ /dev/null @@ -1,321 +0,0 @@ -/* - * 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.streaming.connectors.kafka; - -import org.apache.flink.annotation.PublicEvolving; -import org.apache.flink.api.common.serialization.DeserializationSchema; -import org.apache.flink.metrics.MetricGroup; -import org.apache.flink.streaming.api.functions.AssignerWithPeriodicWatermarks; -import org.apache.flink.streaming.api.functions.AssignerWithPunctuatedWatermarks; -import org.apache.flink.streaming.api.operators.StreamingRuntimeContext; -import org.apache.flink.streaming.connectors.kafka.config.OffsetCommitMode; -import org.apache.flink.streaming.connectors.kafka.internal.KafkaFetcher; -import org.apache.flink.streaming.connectors.kafka.internal.KafkaPartitionDiscoverer; -import org.apache.flink.streaming.connectors.kafka.internals.AbstractFetcher; -import org.apache.flink.streaming.connectors.kafka.internals.AbstractPartitionDiscoverer; -import org.apache.flink.streaming.connectors.kafka.internals.KafkaDeserializationSchemaWrapper; -import org.apache.flink.streaming.connectors.kafka.internals.KafkaTopicPartition; -import org.apache.flink.streaming.connectors.kafka.internals.KafkaTopicsDescriptor; -import org.apache.flink.util.PropertiesUtil; -import org.apache.flink.util.SerializedValue; -import org.apache.kafka.clients.consumer.ConsumerConfig; -import org.apache.kafka.clients.consumer.KafkaConsumer; -import org.apache.kafka.clients.consumer.OffsetAndTimestamp; -import org.apache.kafka.common.TopicPartition; -import org.apache.kafka.common.serialization.ByteArrayDeserializer; - -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.regex.Pattern; - -import static org.apache.flink.util.Preconditions.checkNotNull; -import static org.apache.flink.util.PropertiesUtil.getBoolean; -import static org.apache.flink.util.PropertiesUtil.getLong; - -/** - * The Flink Kafka Consumer is a streaming data source that pulls a parallel data stream from - * Apache Kafka. The consumer can run in multiple parallel instances, each of which will pull - * data from one or more Kafka partitions. - * - *

The Flink Kafka Consumer participates in checkpointing and guarantees that no data is lost - * during a failure, and that the computation processes elements "exactly once". - * (Note: These guarantees naturally assume that Kafka itself does not loose any data.)

- * - *

Please note that Flink snapshots the offsets internally as part of its distributed checkpoints. The offsets - * committed to Kafka are only to bring the outside view of progress in sync with Flink's view - * of the progress. That way, monitoring and other jobs can get a view of how far the Flink Kafka consumer - * has consumed a topic.

- * - *

Please refer to Kafka's documentation for the available configuration properties: - * http://kafka.apache.org/documentation.html#newconsumerconfigs

- */ -@PublicEvolving -public class FlinkKafkaConsumer extends FlinkKafkaConsumerBase { - - /** Configuration key to change the polling timeout. **/ - public static final String KEY_POLL_TIMEOUT = "flink.poll-timeout"; - - /** From Kafka's Javadoc: The time, in milliseconds, spent waiting in poll if data is not - * available. If 0, returns immediately with any records that are available now. */ - public static final long DEFAULT_POLL_TIMEOUT = 100L; - - // ------------------------------------------------------------------------ - - /** User-supplied properties for Kafka. **/ - protected final Properties properties; - - /** From Kafka's Javadoc: The time, in milliseconds, spent waiting in poll if data is not - * available. If 0, returns immediately with any records that are available now */ - protected final long pollTimeout; - - // ------------------------------------------------------------------------ - - /** - * Creates a new Kafka streaming source consumer. - * - * @param topic The name of the topic that should be consumed. - * @param valueDeserializer The de-/serializer used to convert between Kafka's byte messages and Flink's objects. - * @param props - */ - public FlinkKafkaConsumer(String topic, DeserializationSchema valueDeserializer, Properties props) { - this(Collections.singletonList(topic), valueDeserializer, props); - } - - /** - * Creates a new Kafka streaming source consumer. - * - *

This constructor allows passing a {@see KafkaDeserializationSchema} for reading key/value - * pairs, offsets, and topic names from Kafka. - * - * @param topic The name of the topic that should be consumed. - * @param deserializer The keyed de-/serializer used to convert between Kafka's byte messages and Flink's objects. - * @param props - */ - public FlinkKafkaConsumer(String topic, KafkaDeserializationSchema deserializer, Properties props) { - this(Collections.singletonList(topic), deserializer, props); - } - - /** - * Creates a new Kafka streaming source consumer. - * - *

This constructor allows passing multiple topics to the consumer. - * - * @param topics The Kafka topics to read from. - * @param deserializer The de-/serializer used to convert between Kafka's byte messages and Flink's objects. - * @param props - */ - public FlinkKafkaConsumer(List topics, DeserializationSchema deserializer, Properties props) { - this(topics, new KafkaDeserializationSchemaWrapper<>(deserializer), props); - } - - /** - * Creates a new Kafka streaming source consumer. - * - *

This constructor allows passing multiple topics and a key/value deserialization schema. - * - * @param topics The Kafka topics to read from. - * @param deserializer The keyed de-/serializer used to convert between Kafka's byte messages and Flink's objects. - * @param props - */ - public FlinkKafkaConsumer(List topics, KafkaDeserializationSchema deserializer, Properties props) { - this(topics, null, deserializer, props); - } - - /** - * Creates a new Kafka streaming source consumer. Use this constructor to - * subscribe to multiple topics based on a regular expression pattern. - * - *

If partition discovery is enabled (by setting a non-negative value for - * {@link FlinkKafkaConsumer#KEY_PARTITION_DISCOVERY_INTERVAL_MILLIS} in the properties), topics - * with names matching the pattern will also be subscribed to as they are created on the fly. - * - * @param subscriptionPattern The regular expression for a pattern of topic names to subscribe to. - * @param valueDeserializer The de-/serializer used to convert between Kafka's byte messages and Flink's objects. - * @param props - */ - public FlinkKafkaConsumer(Pattern subscriptionPattern, DeserializationSchema valueDeserializer, Properties props) { - this(null, subscriptionPattern, new KafkaDeserializationSchemaWrapper<>(valueDeserializer), props); - } - - /** - * Creates a new Kafka streaming source consumer. Use this constructor to - * subscribe to multiple topics based on a regular expression pattern. - * - *

If partition discovery is enabled (by setting a non-negative value for - * {@link FlinkKafkaConsumer#KEY_PARTITION_DISCOVERY_INTERVAL_MILLIS} in the properties), topics - * with names matching the pattern will also be subscribed to as they are created on the fly. - * - *

This constructor allows passing a {@see KafkaDeserializationSchema} for reading key/value - * pairs, offsets, and topic names from Kafka. - * - * @param subscriptionPattern The regular expression for a pattern of topic names to subscribe to. - * @param deserializer The keyed de-/serializer used to convert between Kafka's byte messages and Flink's objects. - * @param props - */ - public FlinkKafkaConsumer(Pattern subscriptionPattern, KafkaDeserializationSchema deserializer, Properties props) { - this(null, subscriptionPattern, deserializer, props); - } - - private FlinkKafkaConsumer( - List topics, - Pattern subscriptionPattern, - KafkaDeserializationSchema deserializer, - Properties props) { - - super( - topics, - subscriptionPattern, - deserializer, - getLong( - checkNotNull(props, "props"), - KEY_PARTITION_DISCOVERY_INTERVAL_MILLIS, PARTITION_DISCOVERY_DISABLED), - !getBoolean(props, KEY_DISABLE_METRICS, false)); - - this.properties = props; - setDeserializer(this.properties); - - // configure the polling timeout - try { - if (properties.containsKey(KEY_POLL_TIMEOUT)) { - this.pollTimeout = Long.parseLong(properties.getProperty(KEY_POLL_TIMEOUT)); - } else { - this.pollTimeout = DEFAULT_POLL_TIMEOUT; - } - } - catch (Exception e) { - throw new IllegalArgumentException("Cannot parse poll timeout for '" + KEY_POLL_TIMEOUT + '\'', e); - } - } - - @Override - protected AbstractFetcher createFetcher( - SourceContext sourceContext, - Map assignedPartitionsWithInitialOffsets, - SerializedValue> watermarksPeriodic, - SerializedValue> watermarksPunctuated, - StreamingRuntimeContext runtimeContext, - OffsetCommitMode offsetCommitMode, - MetricGroup consumerMetricGroup, - boolean useMetrics) throws Exception { - - // make sure that auto commit is disabled when our offset commit mode is ON_CHECKPOINTS; - // this overwrites whatever setting the user configured in the properties - adjustAutoCommitConfig(properties, offsetCommitMode); - - return new KafkaFetcher<>( - sourceContext, - assignedPartitionsWithInitialOffsets, - watermarksPeriodic, - watermarksPunctuated, - runtimeContext.getProcessingTimeService(), - runtimeContext.getExecutionConfig().getAutoWatermarkInterval(), - runtimeContext.getUserCodeClassLoader(), - runtimeContext.getTaskNameWithSubtasks(), - deserializer, - properties, - pollTimeout, - runtimeContext.getMetricGroup(), - consumerMetricGroup, - useMetrics); - } - - @Override - protected AbstractPartitionDiscoverer createPartitionDiscoverer( - KafkaTopicsDescriptor topicsDescriptor, - int indexOfThisSubtask, - int numParallelSubtasks) { - - return new KafkaPartitionDiscoverer(topicsDescriptor, indexOfThisSubtask, numParallelSubtasks, properties); - } - - // ------------------------------------------------------------------------ - // Timestamp-based startup - // ------------------------------------------------------------------------ - - @Override - public FlinkKafkaConsumerBase setStartFromTimestamp(long startupOffsetsTimestamp) { - // the purpose of this override is just to publicly expose the method for Kafka 0.10+; - // the base class doesn't publicly expose it since not all Kafka versions support the functionality - return super.setStartFromTimestamp(startupOffsetsTimestamp); - } - - @Override - protected Map fetchOffsetsWithTimestamp( - Collection partitions, - long timestamp) { - - Map partitionOffsetsRequest = new HashMap<>(partitions.size()); - for (KafkaTopicPartition partition : partitions) { - partitionOffsetsRequest.put( - new TopicPartition(partition.getTopic(), partition.getPartition()), - timestamp); - } - - final Map result = new HashMap<>(partitions.size()); - // use a short-lived consumer to fetch the offsets; - // this is ok because this is a one-time operation that happens only on startup - try (KafkaConsumer consumer = new KafkaConsumer(properties)) { - for (Map.Entry partitionToOffset : - consumer.offsetsForTimes(partitionOffsetsRequest).entrySet()) { - - result.put( - new KafkaTopicPartition(partitionToOffset.getKey().topic(), partitionToOffset.getKey().partition()), - (partitionToOffset.getValue() == null) ? null : partitionToOffset.getValue().offset()); - } - - } - return result; - } - - @Override - protected boolean getIsAutoCommitEnabled() { - return getBoolean(properties, ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, true) && - PropertiesUtil.getLong(properties, ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, 5000) > 0; - } - - /** - * Makes sure that the ByteArrayDeserializer is registered in the Kafka properties. - * - * @param props The Kafka properties to register the serializer in. - */ - private static void setDeserializer(Properties props) { - final String deSerName = ByteArrayDeserializer.class.getName(); - - Object keyDeSer = props.get(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG); - Object valDeSer = props.get(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG); - - //放开flink对key.deserializer、value.deserializer的限制 - if (keyDeSer != null && !keyDeSer.equals(deSerName)) { - LOG.warn("Set configured key DeSerializer ({} = {})", ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, keyDeSer); - props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, keyDeSer.toString()); - }else{ - props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, deSerName); - } - - if (valDeSer != null && !valDeSer.equals(deSerName)) { - LOG.warn("Set configured value DeSerializer ({} = {})", ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, valDeSer); - props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, valDeSer.toString()); - }else{ - props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, deSerName); - } - } -} diff --git a/kafka/kafka-source/src/test/java/com/dtstack/flink/sql/source/kafka/KafkaSourceTest.java b/kafka/kafka-source/src/test/java/com/dtstack/flink/sql/source/kafka/KafkaSourceTest.java deleted file mode 100644 index 396b69550..000000000 --- a/kafka/kafka-source/src/test/java/com/dtstack/flink/sql/source/kafka/KafkaSourceTest.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.dtstack.flink.sql.source.kafka; - -import com.dtstack.flink.sql.source.kafka.table.KafkaSourceTableInfo; -import com.google.common.collect.Sets; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.streaming.api.datastream.DataStreamSource; -import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; -import org.apache.flink.streaming.api.functions.source.SourceFunction; -import org.apache.flink.table.api.java.StreamTableEnvironment; -import org.junit.Test; -import org.mockito.ArgumentMatcher; - -import static org.mockito.Mockito.*; - -public class KafkaSourceTest { - - @Test - public void mockGenStreamSource(){ - KafkaSourceTableInfo kafkaSourceTableInfo = mock(KafkaSourceTableInfo.class); - when(kafkaSourceTableInfo.getTopic()).thenReturn("topic"); - when(kafkaSourceTableInfo.getGroupId()).thenReturn("groupId"); - when(kafkaSourceTableInfo.getBootstrapServers()).thenReturn("localhost"); - when(kafkaSourceTableInfo.getKafkaParamKeys()).thenReturn(Sets.newHashSet("aa")); - when(kafkaSourceTableInfo.getKafkaParam("aa")).thenReturn("xx"); - when(kafkaSourceTableInfo.getFields()).thenReturn(new String[]{"aa"}); - when(kafkaSourceTableInfo.getFieldClasses()).thenReturn(new Class[]{String.class}); - when(kafkaSourceTableInfo.getParallelism()).thenReturn(1); - when(kafkaSourceTableInfo.getName()).thenReturn("roc"); - when(kafkaSourceTableInfo.getOffsetReset()).thenReturn("1"); - when(kafkaSourceTableInfo.getSourceDataType()).thenReturn("json"); - - DataStreamSource dataStreamSource = mock(DataStreamSource.class); - - StreamExecutionEnvironment env = mock(StreamExecutionEnvironment.class); - when(env.addSource(argThat(new ArgumentMatcher>() { - @Override - public boolean matches(SourceFunction sourceFunction) { - return true; - } - }), argThat(new ArgumentMatcher() { - @Override - public boolean matches(String s) { - return true; - } - }), argThat(new ArgumentMatcher() { - @Override - public boolean matches(TypeInformation typeInformation) { - return true; - } - }))).thenReturn(dataStreamSource); - - StreamTableEnvironment tableEnv = mock(StreamTableEnvironment.class); - - KafkaSource kafkaSource = new KafkaSource(); - KafkaSource kafkaSourceSpy = spy(kafkaSource); -// kafkaSourceSpy.genStreamSource(kafkaSourceTableInfo, env, tableEnv); - } - -} - diff --git a/kafka/kafka-source/src/test/java/com/dtstack/flink/sql/source/kafka/deserializer/DtKafkaDeserializerTest.java b/kafka/kafka-source/src/test/java/com/dtstack/flink/sql/source/kafka/deserializer/DtKafkaDeserializerTest.java deleted file mode 100644 index 2b4f1fd36..000000000 --- a/kafka/kafka-source/src/test/java/com/dtstack/flink/sql/source/kafka/deserializer/DtKafkaDeserializerTest.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.source.kafka.deserializer; - -import com.dtstack.flink.sql.source.kafka.table.KafkaSourceTableInfo; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.apache.kafka.common.serialization.Deserializer; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.HashMap; -import java.util.Map; - -import static org.mockito.Mockito.*; - -public class DtKafkaDeserializerTest { - @InjectMocks - DtKafkaDeserializer dtKafkaDeserializer; - - @Before - public void setUp() { - dtKafkaDeserializer = new DtKafkaDeserializer<>(); - } - - @Test - public void testConfigure() { - Map map = new HashMap<>(); - String deserializer = "org.apache.kafka.common.serialization.ByteArrayDeserializer"; - map.put(KafkaSourceTableInfo.DT_KEY_DESERIALIZER, deserializer); - map.put(KafkaSourceTableInfo.DT_VALUE_DESERIALIZER, deserializer); - dtKafkaDeserializer.configure(map, true); - dtKafkaDeserializer.configure(map, false); - String nonexistentDeserializer = "xxx.xxx.xxx.serialization.XxxDeserializer"; - map.put(KafkaSourceTableInfo.DT_KEY_DESERIALIZER, nonexistentDeserializer); - try { - dtKafkaDeserializer.configure(map, true); - }catch (Exception e){ - Assert.assertEquals("Can't create instance: " + nonexistentDeserializer, e.getMessage()); - } - } - - @Test - public void testDeserialize() { - Map map = new HashMap<>(); - String deserializer = "org.apache.kafka.common.serialization.ByteArrayDeserializer"; - map.put(KafkaSourceTableInfo.DT_KEY_DESERIALIZER, deserializer); - dtKafkaDeserializer.configure(map, true); - - byte[] result = dtKafkaDeserializer.deserialize("topic", null, new byte[]{(byte) 0}); - Assert.assertArrayEquals(new byte[]{(byte) 0}, result); - } - - @Test - public void testDeserialize2() { - Map map = new HashMap<>(); - String deserializer = "org.apache.kafka.common.serialization.StringDeserializer"; - map.put(KafkaSourceTableInfo.DT_KEY_DESERIALIZER, deserializer); - dtKafkaDeserializer.configure(map, true); - byte[] result = dtKafkaDeserializer.deserialize("topic", new byte[]{(byte) 0}); - Assert.assertArrayEquals(new byte[]{(byte) 0}, result); - } - - @Test - public void testClose() { - Map map = new HashMap<>(); - String deserializer = "org.apache.kafka.common.serialization.ByteArrayDeserializer"; - map.put(KafkaSourceTableInfo.DT_KEY_DESERIALIZER, deserializer); - dtKafkaDeserializer.configure(map, true); - dtKafkaDeserializer.close(); - } -} diff --git a/kafka/pom.xml b/kafka/pom.xml index c409a1693..772671ff6 100644 --- a/kafka/pom.xml +++ b/kafka/pom.xml @@ -24,6 +24,13 @@ ${flink.version} + + junit + junit + 3.8.1 + test + + com.dtstack.flink sql.core diff --git a/polardb/polardb-sink/pom.xml b/kafka08/kafka08-sink/pom.xml similarity index 77% rename from polardb/polardb-sink/pom.xml rename to kafka08/kafka08-sink/pom.xml index 1d90fa9a9..47391d182 100644 --- a/polardb/polardb-sink/pom.xml +++ b/kafka08/kafka08-sink/pom.xml @@ -3,28 +3,29 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - sql.polardb + sql.kafka08 com.dtstack.flink 1.0-SNAPSHOT ../pom.xml 4.0.0 - sql.sink.polardb + sql.sink.kafka08 jar - polardb-sink + kafka08-sink http://maven.apache.org - - 1.0-SNAPSHOT - - - com.dtstack.flink - sql.sink.rdb - ${sql.sink.rdb.version} + org.apache.flink + flink-connector-kafka-0.8_2.11 + ${flink.version} + + + org.apache.flink + flink-json + ${flink.version} @@ -74,14 +75,14 @@ - + - + - + @@ -89,4 +90,5 @@ + \ No newline at end of file diff --git a/kafka08/kafka08-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerCsvSerialization.java b/kafka08/kafka08-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerCsvSerialization.java new file mode 100644 index 000000000..4168edbd1 --- /dev/null +++ b/kafka08/kafka08-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerCsvSerialization.java @@ -0,0 +1,123 @@ +package com.dtstack.flink.sql.sink.kafka; + +import org.apache.commons.lang3.StringEscapeUtils; +import org.apache.flink.annotation.Internal; +import org.apache.flink.api.common.ExecutionConfig; +import org.apache.flink.api.common.typeinfo.TypeInformation; +import org.apache.flink.api.common.typeutils.TypeSerializer; +import org.apache.flink.api.common.typeutils.TypeSerializerSnapshot; +import org.apache.flink.api.common.typeutils.base.TypeSerializerSingleton; +import org.apache.flink.core.memory.DataInputView; +import org.apache.flink.core.memory.DataOutputView; +import org.apache.flink.types.Row; +import org.apache.flink.types.StringValue; + +import java.io.IOException; + +import static org.apache.flink.api.java.typeutils.runtime.NullMaskUtils.writeNullMask; + +/** + * + * Date: 2018/12/18 + * Company: www.dtstack.com + * @author DocLi + * + * @modifyer maqi + */ +@Internal +public final class CustomerCsvSerialization extends TypeSerializerSingleton { + + private static final long serialVersionUID = 1L; + + private String fieldDelimiter = "\u0001"; + private TypeInformation[] fieldTypes; + private TypeSerializer[] fieldSerializers; + private static final Row EMPTY = null; + + public CustomerCsvSerialization(String fielddelimiter,TypeInformation[] fieldTypes) { + this.fieldDelimiter = fielddelimiter; + this.fieldTypes = fieldTypes; + this.fieldSerializers = (TypeSerializer[])createSerializer(new ExecutionConfig()); + } + + public TypeSerializer[] createSerializer(ExecutionConfig config) { + int len = fieldTypes.length; + TypeSerializer[] fieldSerializers = new TypeSerializer[len]; + for (int i = 0; i < len; i++) { + fieldSerializers[i] = fieldTypes[i].createSerializer(config); + } + return fieldSerializers; + } + + @Override + public boolean isImmutableType() { + return true; + } + + @Override + public Row createInstance() { + return EMPTY; + } + + @Override + public Row copy(Row from) { + return null; + } + + @Override + public Row copy(Row from, Row reuse) { + return null; + } + + @Override + public int getLength() { + return -1; + } + + @Override + public void serialize(Row record, DataOutputView target) throws IOException { + int len = fieldSerializers.length; + + if (record.getArity() != len) { + throw new RuntimeException("Row arity of from does not match serializers."); + } + + // write a null mask + writeNullMask(len, record, target); + + // serialize non-null fields + StringBuffer stringBuffer = new StringBuffer(); + for (int i = 0; i < len; i++) { + Object o = record.getField(i); + if (o != null) { + //fieldSerializers[i].serialize(o, target); + stringBuffer.append(o); + } + if(i != len-1){ + stringBuffer.append(StringEscapeUtils.unescapeJava(fieldDelimiter)); + //fieldSerializers[i].serialize(fieldDelimiter, target); + } + } + StringValue.writeString(stringBuffer.toString(), target); + } + + @Override + public Row deserialize(DataInputView source) throws IOException { + return null; + } + + @Override + public Row deserialize(Row reuse, DataInputView source) throws IOException { + return null; + } + + @Override + public void copy(DataInputView source, DataOutputView target) throws IOException { + StringValue.copyString(source, target); + } + + @Override + public TypeSerializerSnapshot snapshotConfiguration() { + return null; + } +} diff --git a/kafka08/kafka08-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/KafkaSink.java b/kafka08/kafka08-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/KafkaSink.java new file mode 100644 index 000000000..fe3c00f03 --- /dev/null +++ b/kafka08/kafka08-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/KafkaSink.java @@ -0,0 +1,138 @@ +/* + * 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 com.dtstack.flink.sql.sink.kafka; + +import com.dtstack.flink.sql.sink.IStreamSinkGener; +import com.dtstack.flink.sql.sink.kafka.table.KafkaSinkTableInfo; +import com.dtstack.flink.sql.table.TargetTableInfo; +import org.apache.flink.api.common.serialization.SerializationSchema; +import org.apache.flink.api.common.serialization.TypeInformationSerializationSchema; +import org.apache.flink.api.common.typeinfo.TypeInformation; +import org.apache.flink.api.java.typeutils.RowTypeInfo; +import org.apache.flink.formats.json.JsonRowSerializationSchema; +import org.apache.flink.streaming.api.datastream.DataStream; +import org.apache.flink.streaming.connectors.kafka.Kafka08TableSink; +import org.apache.flink.streaming.connectors.kafka.KafkaTableSinkBase; +import org.apache.flink.streaming.connectors.kafka.partitioner.FlinkFixedPartitioner; +import org.apache.flink.streaming.connectors.kafka.partitioner.FlinkKafkaPartitioner; +import org.apache.flink.table.api.TableSchema; +import org.apache.flink.table.sinks.AppendStreamTableSink; +import org.apache.flink.table.sinks.TableSink; +import org.apache.flink.types.Row; + +import java.util.Optional; +import java.util.Properties; +/** + * Date: 2018/12/18 + * Company: www.dtstack.com + * @author DocLi + * + * @modifyer maqi + */ +public class KafkaSink implements AppendStreamTableSink, IStreamSinkGener { + + protected String[] fieldNames; + + protected TypeInformation[] fieldTypes; + + /** The schema of the table. */ + private TableSchema schema; + + /** The Kafka topic to write to. */ + protected String topic; + + /** Properties for the Kafka producer. */ + protected Properties properties; + + /** Serialization schema for encoding records to Kafka. */ + protected SerializationSchema serializationSchema; + + /** Partitioner to select Kafka partition for each item. */ + protected Optional> partitioner; + + @Override + public KafkaSink genStreamSink(TargetTableInfo targetTableInfo) { + KafkaSinkTableInfo kafka08SinkTableInfo = (KafkaSinkTableInfo) targetTableInfo; + this.topic = kafka08SinkTableInfo.getKafkaParam("topic"); + + Properties props = new Properties(); + for (String key:kafka08SinkTableInfo.getKafkaParamKeys()) { + props.setProperty(key, kafka08SinkTableInfo.getKafkaParam(key)); + } + this.properties = props; + this.partitioner = Optional.of(new FlinkFixedPartitioner<>()); + this.fieldNames = kafka08SinkTableInfo.getFields(); + TypeInformation[] types = new TypeInformation[kafka08SinkTableInfo.getFields().length]; + for(int i = 0; i< kafka08SinkTableInfo.getFieldClasses().length; i++){ + types[i] = TypeInformation.of(kafka08SinkTableInfo.getFieldClasses()[i]); + } + this.fieldTypes = types; + + TableSchema.Builder schemaBuilder = TableSchema.builder(); + for (int i=0;i dataStream) { + KafkaTableSinkBase kafkaTableSink = new Kafka08TableSink( + schema, + topic, + properties, + partitioner, + serializationSchema + ); + + kafkaTableSink.emitDataStream(dataStream); + } + + @Override + public TypeInformation getOutputType() { + return new RowTypeInfo(fieldTypes, fieldNames); + } + + @Override + public String[] getFieldNames() { + return fieldNames; + } + + @Override + public TypeInformation[] getFieldTypes() { + return fieldTypes; + } + + @Override + public TableSink configure(String[] fieldNames, TypeInformation[] fieldTypes) { + this.fieldNames = fieldNames; + this.fieldTypes = fieldTypes; + return this; + } + +} diff --git a/kafka08/kafka08-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/table/KafkaSinkParser.java b/kafka08/kafka08-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/table/KafkaSinkParser.java new file mode 100644 index 000000000..2b6c50512 --- /dev/null +++ b/kafka08/kafka08-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/table/KafkaSinkParser.java @@ -0,0 +1,58 @@ +/* + * 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 com.dtstack.flink.sql.sink.kafka.table; + +import com.dtstack.flink.sql.table.AbsTableParser; +import com.dtstack.flink.sql.table.TableInfo; +import com.dtstack.flink.sql.util.MathUtil; + +import java.util.Map; + +/** + * + * Date: 2018/12/18 + * Company: www.dtstack.com + * + * @author DocLi + * + * @modifyer maqi + * + */ +public class KafkaSinkParser extends AbsTableParser { + @Override + public TableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { + KafkaSinkTableInfo kafka08SinkTableInfo = new KafkaSinkTableInfo(); + kafka08SinkTableInfo.setName(tableName); + parseFieldsInfo(fieldsInfo, kafka08SinkTableInfo); + kafka08SinkTableInfo.setParallelism(MathUtil.getIntegerVal(props.get(KafkaSinkTableInfo.PARALLELISM_KEY.toLowerCase()))); + if (props.get(KafkaSinkTableInfo.SINK_DATA_TYPE) != null) { + kafka08SinkTableInfo.setSinkDataType(props.get(KafkaSinkTableInfo.SINK_DATA_TYPE).toString()); + } + if (props.get(KafkaSinkTableInfo.FIELD_DELINITER) != null) { + kafka08SinkTableInfo.setFieldDelimiter(props.get(KafkaSinkTableInfo.FIELD_DELINITER).toString()); + } + + for (String key:props.keySet()) { + if (!key.isEmpty() && key.startsWith("kafka.")) { + kafka08SinkTableInfo.addKafkaParam(key.substring(6), props.get(key).toString()); + } + } + return kafka08SinkTableInfo; + } +} diff --git a/kafka08/kafka08-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/table/KafkaSinkTableInfo.java b/kafka08/kafka08-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/table/KafkaSinkTableInfo.java new file mode 100644 index 000000000..61acfa2d6 --- /dev/null +++ b/kafka08/kafka08-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/table/KafkaSinkTableInfo.java @@ -0,0 +1,71 @@ +/* + * 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 com.dtstack.flink.sql.sink.kafka.table; + +import com.dtstack.flink.sql.table.TargetTableInfo; +import com.google.common.base.Preconditions; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +/** + * + * Date: 2018/12/18 + * Company: www.dtstack.com + * @author DocLi + * + * @modifyer maqi + * + */ +public class KafkaSinkTableInfo extends TargetTableInfo { + //version + private static final String CURR_TYPE = "kafka08"; + + public KafkaSinkTableInfo(){ + super.setType(CURR_TYPE); + } + + public Map kafkaParam = new HashMap(); + + public void addKafkaParam(String key,String value){ + kafkaParam.put(key,value); + } + + public String getKafkaParam(String key){ + return kafkaParam.get(key); + } + + public Set getKafkaParamKeys(){ + return kafkaParam.keySet(); + } + + @Override + public boolean check() { + Preconditions.checkNotNull(kafkaParam.get("bootstrap.servers"), "kafka of bootstrapServers is required"); + Preconditions.checkNotNull(kafkaParam.get("topic"), "kafka of topic is required"); + // Preconditions.checkNotNull(kafkaParam.get("groupId"), "kafka of groupId is required"); + return false; + } + + @Override + public String getType() { + return super.getType(); + } +} diff --git a/aws/aws-sink/pom.xml b/kafka08/kafka08-source/pom.xml similarity index 79% rename from aws/aws-sink/pom.xml rename to kafka08/kafka08-source/pom.xml index 1b321467c..64264fd46 100644 --- a/aws/aws-sink/pom.xml +++ b/kafka08/kafka08-source/pom.xml @@ -3,27 +3,28 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - sql.aws + sql.kafka08 com.dtstack.flink 1.0-SNAPSHOT ../pom.xml 4.0.0 - sql.sink.aws + sql.source.kafka08 jar - aws-sink + kafka08-source http://maven.apache.org - com.cmcc - onest-s3-java-sdk - 1.0 + org.apache.flink + flink-connector-kafka-0.8_2.11 + ${flink.version} + @@ -37,10 +38,9 @@ shade - false - + org.slf4j @@ -71,14 +71,14 @@ - + - + - + @@ -86,4 +86,6 @@ + + \ No newline at end of file diff --git a/kafka08/kafka08-source/src/main/java/com/dtstack/flink/sql/source/kafka/KafkaSource.java b/kafka08/kafka08-source/src/main/java/com/dtstack/flink/sql/source/kafka/KafkaSource.java new file mode 100644 index 000000000..bfbffdf14 --- /dev/null +++ b/kafka08/kafka08-source/src/main/java/com/dtstack/flink/sql/source/kafka/KafkaSource.java @@ -0,0 +1,135 @@ +/* + * 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 com.dtstack.flink.sql.source.kafka; + +import com.dtstack.flink.sql.source.IStreamSourceGener; +import com.dtstack.flink.sql.source.kafka.consumer.CustomerCommonConsumer; +import com.dtstack.flink.sql.source.kafka.consumer.CustomerCsvConsumer; +import com.dtstack.flink.sql.source.kafka.consumer.CustomerJsonConsumer; +import com.dtstack.flink.sql.source.kafka.deserialization.CustomerCommonDeserialization; +import com.dtstack.flink.sql.source.kafka.deserialization.CustomerCsvDeserialization; +import com.dtstack.flink.sql.source.kafka.deserialization.CustomerJsonDeserialization; +import com.dtstack.flink.sql.source.kafka.table.KafkaSourceTableInfo; +import com.dtstack.flink.sql.table.SourceTableInfo; +import com.dtstack.flink.sql.util.DtStringUtil; +import com.dtstack.flink.sql.util.PluginUtil; +import org.apache.commons.lang3.StringUtils; +import org.apache.flink.api.common.typeinfo.TypeInformation; +import org.apache.flink.api.java.typeutils.RowTypeInfo; +import org.apache.flink.streaming.api.datastream.DataStreamSource; +import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; +import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer08; +import org.apache.flink.streaming.connectors.kafka.internals.KafkaTopicPartition; +import org.apache.flink.table.api.Table; +import org.apache.flink.table.api.java.StreamTableEnvironment; +import org.apache.flink.types.Row; + +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; +import java.util.regex.Pattern; + +public class KafkaSource implements IStreamSourceGener

{ + + private static final String SOURCE_OPERATOR_NAME_TPL = "${topic}_${table}"; + + /** + * Get kafka data source, you need to provide the data field names, data types + * If you do not specify auto.offset.reset, the default use groupoffset + * + * @param sourceTableInfo + * @return + */ + @SuppressWarnings("rawtypes") + @Override + public Table genStreamSource(SourceTableInfo sourceTableInfo, StreamExecutionEnvironment env, StreamTableEnvironment tableEnv) { + KafkaSourceTableInfo kafka08SourceTableInfo = (KafkaSourceTableInfo) sourceTableInfo; + String topicName = kafka08SourceTableInfo.getKafkaParam("topic"); + String offsetReset = kafka08SourceTableInfo.getKafkaParam("auto.offset.reset"); + Boolean topicIsPattern = kafka08SourceTableInfo.getPatternTopic(); + + Properties props = new Properties(); + for (String key : kafka08SourceTableInfo.getKafkaParamKeys()) { + props.setProperty(key, kafka08SourceTableInfo.getKafkaParam(key)); + } + + TypeInformation[] types = new TypeInformation[kafka08SourceTableInfo.getFields().length]; + for (int i = 0; i < kafka08SourceTableInfo.getFieldClasses().length; i++) { + types[i] = TypeInformation.of(kafka08SourceTableInfo.getFieldClasses()[i]); + } + + TypeInformation typeInformation = new RowTypeInfo(types, kafka08SourceTableInfo.getFields()); + + FlinkKafkaConsumer08 kafkaSrc; + String fields = StringUtils.join(kafka08SourceTableInfo.getFields(), ","); + + if ("json".equalsIgnoreCase(kafka08SourceTableInfo.getSourceDataType())) { + if (topicIsPattern) { + kafkaSrc = new CustomerJsonConsumer(Pattern.compile(topicName), + new com.dtstack.flink.sql.source.kafka.deserialization.CustomerJsonDeserialization(typeInformation), props); + } else { + kafkaSrc = new CustomerJsonConsumer(topicName, + new CustomerJsonDeserialization(typeInformation), props); + } + } else if ("csv".equalsIgnoreCase(kafka08SourceTableInfo.getSourceDataType())) { + if (topicIsPattern) { + kafkaSrc = new CustomerCsvConsumer(Pattern.compile(topicName), + new com.dtstack.flink.sql.source.kafka.deserialization.CustomerCsvDeserialization(typeInformation, + kafka08SourceTableInfo.getFieldDelimiter(), kafka08SourceTableInfo.getLengthCheckPolicy()), props); + } else { + kafkaSrc = new CustomerCsvConsumer(topicName, + new CustomerCsvDeserialization(typeInformation, + kafka08SourceTableInfo.getFieldDelimiter(), kafka08SourceTableInfo.getLengthCheckPolicy()), props); + } + } else { + if (topicIsPattern) { + kafkaSrc = new CustomerCommonConsumer(Pattern.compile(topicName), new com.dtstack.flink.sql.source.kafka.deserialization.CustomerCommonDeserialization(), props); + } else { + kafkaSrc = new CustomerCommonConsumer(topicName, new CustomerCommonDeserialization(), props); + } + } + + //earliest,latest + if ("earliest".equalsIgnoreCase(offsetReset)) { + kafkaSrc.setStartFromEarliest(); + } else if (DtStringUtil.isJosn(offsetReset)) {// {"0":12312,"1":12321,"2":12312} + try { + Properties properties = PluginUtil.jsonStrToObject(offsetReset, Properties.class); + Map offsetMap = PluginUtil.ObjectToMap(properties); + Map specificStartupOffsets = new HashMap<>(); + for (Map.Entry entry : offsetMap.entrySet()) { + specificStartupOffsets.put(new KafkaTopicPartition(topicName, Integer.valueOf(entry.getKey())), Long.valueOf(entry.getValue().toString())); + } + kafkaSrc.setStartFromSpecificOffsets(specificStartupOffsets); + } catch (Exception e) { + throw new RuntimeException("not support offsetReset type:" + offsetReset); + } + } else { + kafkaSrc.setStartFromLatest(); + } + String sourceOperatorName = SOURCE_OPERATOR_NAME_TPL.replace("${topic}", topicName).replace("${table}", sourceTableInfo.getName()); + DataStreamSource kafkaSource = env.addSource(kafkaSrc, sourceOperatorName, typeInformation); + Integer parallelism = kafka08SourceTableInfo.getParallelism(); + if (parallelism != null) { + kafkaSource.setParallelism(parallelism); + } + return tableEnv.fromDataStream(kafkaSource, fields); + } +} diff --git a/kafka08/kafka08-source/src/main/java/com/dtstack/flink/sql/source/kafka/consumer/CustomerCommonConsumer.java b/kafka08/kafka08-source/src/main/java/com/dtstack/flink/sql/source/kafka/consumer/CustomerCommonConsumer.java new file mode 100644 index 000000000..34b349e2c --- /dev/null +++ b/kafka08/kafka08-source/src/main/java/com/dtstack/flink/sql/source/kafka/consumer/CustomerCommonConsumer.java @@ -0,0 +1,60 @@ +/** + * 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 com.dtstack.flink.sql.source.kafka.consumer; + +import com.dtstack.flink.sql.source.kafka.deserialization.CustomerCommonDeserialization; +import org.apache.flink.streaming.api.functions.source.SourceFunction; +import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer08; +import org.apache.flink.streaming.util.serialization.KeyedDeserializationSchema; +import org.apache.flink.types.Row; + +import java.util.Properties; +import java.util.regex.Pattern; + +/** + * + * Date: 2018/12/18 + * Company: www.dtstack.com + * @author DocLi + * + * @modifyer maqi + */ +public class CustomerCommonConsumer extends FlinkKafkaConsumer08 { + + private CustomerCommonDeserialization customerCommonDeserialization; + + + public CustomerCommonConsumer(String topic, KeyedDeserializationSchema deserializer, Properties props) { + super(topic, deserializer, props); + this.customerCommonDeserialization= (CustomerCommonDeserialization) deserializer; + } + + public CustomerCommonConsumer(Pattern subscriptionPattern, KeyedDeserializationSchema deserializer, Properties props) { + super(subscriptionPattern, deserializer, props); + this.customerCommonDeserialization= (CustomerCommonDeserialization) deserializer; + } + + + @Override + public void run(SourceFunction.SourceContext sourceContext) throws Exception { + customerCommonDeserialization.setRuntimeContext(getRuntimeContext()); + customerCommonDeserialization.initMetric(); + super.run(sourceContext); + } + +} diff --git a/kafka08/kafka08-source/src/main/java/com/dtstack/flink/sql/source/kafka/consumer/CustomerCsvConsumer.java b/kafka08/kafka08-source/src/main/java/com/dtstack/flink/sql/source/kafka/consumer/CustomerCsvConsumer.java new file mode 100644 index 000000000..7dc95450e --- /dev/null +++ b/kafka08/kafka08-source/src/main/java/com/dtstack/flink/sql/source/kafka/consumer/CustomerCsvConsumer.java @@ -0,0 +1,65 @@ +/* + * 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 com.dtstack.flink.sql.source.kafka.consumer; + +import com.dtstack.flink.sql.source.AbsDeserialization; +import com.dtstack.flink.sql.source.kafka.deserialization.CustomerCsvDeserialization; +import org.apache.flink.streaming.api.functions.source.SourceFunction; +import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer08; +import org.apache.flink.types.Row; + +import java.util.Arrays; +import java.util.Properties; +import java.util.regex.Pattern; + +/** + * Date: 2018/12/18 + * Company: www.dtstack.com + * @author DocLi + * + * @modifyer maqi + */ + +public class CustomerCsvConsumer extends FlinkKafkaConsumer08 { + + private static final long serialVersionUID = -2265366268827807739L; + + private CustomerCsvDeserialization customerCsvDeserialization; + + public CustomerCsvConsumer(String topic, AbsDeserialization valueDeserializer, Properties props) { + super(Arrays.asList(topic.split(",")), valueDeserializer, props); + this.customerCsvDeserialization = (CustomerCsvDeserialization) valueDeserializer; + } + + public CustomerCsvConsumer(Pattern subscriptionPattern, AbsDeserialization valueDeserializer, Properties props) { + super(subscriptionPattern, valueDeserializer, props); + this.customerCsvDeserialization = (CustomerCsvDeserialization) valueDeserializer; + } + + + + + @Override + public void run(SourceFunction.SourceContext sourceContext) throws Exception { + customerCsvDeserialization.setRuntimeContext(getRuntimeContext()); + customerCsvDeserialization.initMetric(); + super.run(sourceContext); + } + +} diff --git a/kafka08/kafka08-source/src/main/java/com/dtstack/flink/sql/source/kafka/consumer/CustomerJsonConsumer.java b/kafka08/kafka08-source/src/main/java/com/dtstack/flink/sql/source/kafka/consumer/CustomerJsonConsumer.java new file mode 100644 index 000000000..b627d81c0 --- /dev/null +++ b/kafka08/kafka08-source/src/main/java/com/dtstack/flink/sql/source/kafka/consumer/CustomerJsonConsumer.java @@ -0,0 +1,64 @@ +/* + * 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 com.dtstack.flink.sql.source.kafka.consumer; + +import com.dtstack.flink.sql.source.AbsDeserialization; +import com.dtstack.flink.sql.source.kafka.deserialization.CustomerJsonDeserialization; +import org.apache.flink.streaming.api.functions.source.SourceFunction; +import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer08; +import org.apache.flink.types.Row; + +import java.util.Arrays; +import java.util.Properties; +import java.util.regex.Pattern; + +/** + * Reason: + * Date: 2018/10/19 + * Company: www.dtstack.com + * + * @author xuchao + */ + +public class CustomerJsonConsumer extends FlinkKafkaConsumer08 { + + private static final long serialVersionUID = -2265366268827807739L; + + private CustomerJsonDeserialization customerJsonDeserialization; + + public CustomerJsonConsumer(String topic, AbsDeserialization valueDeserializer, Properties props) { + super(Arrays.asList(topic.split(",")), valueDeserializer, props); + this.customerJsonDeserialization = (CustomerJsonDeserialization) valueDeserializer; + } + + public CustomerJsonConsumer(Pattern subscriptionPattern, AbsDeserialization valueDeserializer, Properties props) { + super(subscriptionPattern, valueDeserializer, props); + this.customerJsonDeserialization = (CustomerJsonDeserialization) valueDeserializer; + } + + + @Override + public void run(SourceFunction.SourceContext sourceContext) throws Exception { + customerJsonDeserialization.setRuntimeContext(getRuntimeContext()); + customerJsonDeserialization.initMetric(); + super.run(sourceContext); + } + + +} diff --git a/kafka08/kafka08-source/src/main/java/com/dtstack/flink/sql/source/kafka/deserialization/CustomerCommonDeserialization.java b/kafka08/kafka08-source/src/main/java/com/dtstack/flink/sql/source/kafka/deserialization/CustomerCommonDeserialization.java new file mode 100644 index 000000000..c92ce4aa4 --- /dev/null +++ b/kafka08/kafka08-source/src/main/java/com/dtstack/flink/sql/source/kafka/deserialization/CustomerCommonDeserialization.java @@ -0,0 +1,93 @@ +/* + * 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 com.dtstack.flink.sql.source.kafka.deserialization; + +import com.dtstack.flink.sql.source.AbsDeserialization; +import org.apache.flink.api.common.typeinfo.TypeInformation; +import org.apache.flink.api.common.typeinfo.Types; +import org.apache.flink.api.java.typeutils.RowTypeInfo; +import org.apache.flink.api.java.typeutils.TypeExtractor; +import org.apache.flink.streaming.util.serialization.KeyedDeserializationSchema; +import org.apache.flink.types.Row; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import static java.nio.charset.StandardCharsets.UTF_8; + +/** + * Date: 2018/12/18 + * Company: www.dtstack.com + * @author DocLi + * + * @modifyer maqi + */ +public class CustomerCommonDeserialization extends AbsDeserialization implements KeyedDeserializationSchema { + private static final Logger LOG = LoggerFactory.getLogger(CustomerCommonDeserialization.class); + + public static final String[] KAFKA_COLUMNS = new String[]{"_TOPIC", "_MESSAGEKEY", "_MESSAGE", "_PARTITION", "_OFFSET"}; + + private boolean firstMsg = true; + + @Override + public Row deserialize(byte[] messageKey, byte[] message, String topic, int partition, long offset) { + + //numInRecord.inc(); + //numInBytes.inc(message.length); + //numInBytes.inc(messageKey.length); + + try { + Row row = Row.of( + topic, //topic + messageKey == null ? null : new String(messageKey, UTF_8), //key + new String(message, UTF_8), //message + partition, + offset + ); + return row; + } catch (Throwable t) { + LOG.error(t.getMessage()); + // dirtyDataCounter.inc(); + return null; + } + } + + @Override + public Row deserialize(byte[] message) throws IOException { + return null; + } + + + @Override + public boolean isEndOfStream(Row nextElement) { + return false; + } + + public TypeInformation getProducedType() { + TypeInformation[] types = new TypeInformation[]{ + TypeExtractor.createTypeInfo(String.class), + TypeExtractor.createTypeInfo(String.class), //createTypeInformation[String] + TypeExtractor.createTypeInfo(String.class), + Types.INT, + Types.LONG + }; + return new RowTypeInfo(types, KAFKA_COLUMNS); + } + +} diff --git a/kafka08/kafka08-source/src/main/java/com/dtstack/flink/sql/source/kafka/deserialization/CustomerCsvDeserialization.java b/kafka08/kafka08-source/src/main/java/com/dtstack/flink/sql/source/kafka/deserialization/CustomerCsvDeserialization.java new file mode 100644 index 000000000..f9f4c897c --- /dev/null +++ b/kafka08/kafka08-source/src/main/java/com/dtstack/flink/sql/source/kafka/deserialization/CustomerCsvDeserialization.java @@ -0,0 +1,120 @@ +/* + * 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 com.dtstack.flink.sql.source.kafka.deserialization; + + +import com.dtstack.flink.sql.source.AbsDeserialization; +import com.dtstack.flink.sql.util.DtStringUtil; +import org.apache.flink.api.common.typeinfo.TypeInformation; +import org.apache.flink.api.java.typeutils.RowTypeInfo; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.flink.types.Row; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; + +/** + * Date: 2018/12/18 + * Company: www.dtstack.com + * @author DocLi + * + * @modifyer maqi + */ + +public class CustomerCsvDeserialization extends AbsDeserialization { + + private static final Logger LOG = LoggerFactory.getLogger(CustomerCsvDeserialization.class); + + private static final long serialVersionUID = -2706012724306826506L; + + private final ObjectMapper objectMapper = new ObjectMapper(); + + /** Type information describing the result type. */ + private final TypeInformation typeInfo; + + /** Field names to parse. Indices match fieldTypes indices. */ + private final String[] fieldNames; + + /** Types to parse fields as. Indices match fieldNames indices. */ + private final TypeInformation[] fieldTypes; + + /** Flag indicating whether to fail on a missing field. */ + private boolean failOnMissingField; + + private String fieldDelimiter; + + private String lengthCheckPolicy; + + public CustomerCsvDeserialization(TypeInformation typeInfo, String fieldDelimiter, String lengthCheckPolicy){ + this.typeInfo = typeInfo; + + this.fieldNames = ((RowTypeInfo) typeInfo).getFieldNames(); + + this.fieldTypes = ((RowTypeInfo) typeInfo).getFieldTypes(); + + this.fieldDelimiter = fieldDelimiter; + + this.lengthCheckPolicy = lengthCheckPolicy; + } + + @Override + public Row deserialize(byte[] message) throws IOException { + + try { + //numInRecord.inc(); + //numInBytes.inc(message.length); + String[] fieldsList = null; + if (message != null && message.length > 0){ + fieldsList = new String(message).split(fieldDelimiter); + } + if (fieldsList == null || fieldsList.length != fieldNames.length){//exception condition + if (lengthCheckPolicy.equalsIgnoreCase("SKIP")) { + return null; + }else if (lengthCheckPolicy.equalsIgnoreCase("EXCEPTION")) { + throw new RuntimeException("lengthCheckPolicy Error,message have "+fieldsList.length+" fields,sql have "+fieldNames.length); + } + } + + Row row = new Row(fieldNames.length); + for (int i = 0; i < fieldNames.length; i++) { + if (i { + + private static final Logger LOG = LoggerFactory.getLogger(CustomerJsonDeserialization.class); + + private static final long serialVersionUID = 2385115520960444192L; + + private final ObjectMapper objectMapper = new ObjectMapper(); + + /** Type information describing the result type. */ + private final TypeInformation typeInfo; + + /** Field names to parse. Indices match fieldTypes indices. */ + private final String[] fieldNames; + + /** Types to parse fields as. Indices match fieldNames indices. */ + private final TypeInformation[] fieldTypes; + + /** Flag indicating whether to fail on a missing field. */ + private boolean failOnMissingField; + + private AbstractFetcher fetcher; + + public CustomerJsonDeserialization(TypeInformation typeInfo){ + this.typeInfo = typeInfo; + + this.fieldNames = ((RowTypeInfo) typeInfo).getFieldNames(); + + this.fieldTypes = ((RowTypeInfo) typeInfo).getFieldTypes(); + } + + @Override + public Row deserialize(byte[] message) throws IOException { + + try { + // numInRecord.inc(); + // numInBytes.inc(message.length); + + JsonNode root = objectMapper.readTree(message); + Row row = new Row(fieldNames.length); + for (int i = 0; i < fieldNames.length; i++) { + JsonNode node = getIgnoreCase(root, fieldNames[i]); + + if (node == null) { + if (failOnMissingField) { + throw new IllegalStateException("Failed to find field with name '" + + fieldNames[i] + "'."); + } else { + row.setField(i, null); + } + } else { + // Read the value as specified type + Object value = objectMapper.treeToValue(node, fieldTypes[i].getTypeClass()); + row.setField(i, value); + } + } + + // numInResolveRecord.inc(); + return row; + } catch (Throwable t) { + //add metric of dirty data + LOG.error(t.getMessage()); + // dirtyDataCounter.inc(); + return null; + } + } + + public void setFailOnMissingField(boolean failOnMissingField) { + this.failOnMissingField = failOnMissingField; + } + + public JsonNode getIgnoreCase(JsonNode jsonNode, String key) { + + Iterator iter = jsonNode.fieldNames(); + while (iter.hasNext()) { + String key1 = iter.next(); + if (key1.equalsIgnoreCase(key)) { + return jsonNode.get(key1); + } + } + + return null; + + } + + public void setFetcher(AbstractFetcher fetcher) { + this.fetcher = fetcher; + } + + + private static String partitionLagMetricName(TopicPartition tp) { + return tp + ".records-lag"; + } +} diff --git a/kafka08/kafka08-source/src/main/java/com/dtstack/flink/sql/source/kafka/table/KafkaSourceParser.java b/kafka08/kafka08-source/src/main/java/com/dtstack/flink/sql/source/kafka/table/KafkaSourceParser.java new file mode 100644 index 000000000..eb085ac78 --- /dev/null +++ b/kafka08/kafka08-source/src/main/java/com/dtstack/flink/sql/source/kafka/table/KafkaSourceParser.java @@ -0,0 +1,67 @@ +/* + * 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 com.dtstack.flink.sql.source.kafka.table; + +import com.dtstack.flink.sql.table.AbsSourceParser; +import com.dtstack.flink.sql.table.TableInfo; +import com.dtstack.flink.sql.util.MathUtil; + +import java.util.Map; +/** + * + * Date: 2018/12/18 + * Company: www.dtstack.com + * @author xuchao + * + * @modifyer DocLi + */ + +public class KafkaSourceParser extends AbsSourceParser { + + @Override + public TableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { + + KafkaSourceTableInfo kafka08SourceTableInfo = new KafkaSourceTableInfo(); + kafka08SourceTableInfo.setName(tableName); + parseFieldsInfo(fieldsInfo, kafka08SourceTableInfo); + kafka08SourceTableInfo.setParallelism(MathUtil.getIntegerVal(props.get(KafkaSourceTableInfo.PARALLELISM_KEY.toLowerCase()))); + + kafka08SourceTableInfo.setPatternTopic(MathUtil.getBoolean(props.get(KafkaSourceTableInfo.PATTERNTOPIC_KEY.toLowerCase()))); + + kafka08SourceTableInfo.setTimeZone(MathUtil.getString(props.get(KafkaSourceTableInfo.TIME_ZONE_KEY.toLowerCase()))); + + if (props.get(KafkaSourceTableInfo.SOURCE_DATA_TYPE) != null) { + kafka08SourceTableInfo.setSourceDataType(props.get(KafkaSourceTableInfo.SOURCE_DATA_TYPE).toString()); + } + if (props.get(KafkaSourceTableInfo.FIELD_DELINITER) != null) { + kafka08SourceTableInfo.setFieldDelimiter(props.get(KafkaSourceTableInfo.FIELD_DELINITER).toString()); + } + if (props.get(KafkaSourceTableInfo.LENGTH_CHECK_POLICY) != null) { + kafka08SourceTableInfo.setLengthCheckPolicy(props.get(KafkaSourceTableInfo.LENGTH_CHECK_POLICY).toString()); + } + for (String key:props.keySet()) { + if (!key.isEmpty() && key.startsWith("kafka.")) { + kafka08SourceTableInfo.addKafkaParam(key.substring(6), props.get(key).toString()); + } + } + return kafka08SourceTableInfo; + } +} diff --git a/kafka08/kafka08-source/src/main/java/com/dtstack/flink/sql/source/kafka/table/KafkaSourceTableInfo.java b/kafka08/kafka08-source/src/main/java/com/dtstack/flink/sql/source/kafka/table/KafkaSourceTableInfo.java new file mode 100644 index 000000000..93e9d52f7 --- /dev/null +++ b/kafka08/kafka08-source/src/main/java/com/dtstack/flink/sql/source/kafka/table/KafkaSourceTableInfo.java @@ -0,0 +1,83 @@ +/* + * 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 com.dtstack.flink.sql.source.kafka.table; + +import com.dtstack.flink.sql.table.SourceTableInfo; +import com.google.common.base.Preconditions; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + + +public class KafkaSourceTableInfo extends SourceTableInfo { + + //version + private static final String CURR_TYPE = "kafka08"; + + public static final String PATTERNTOPIC_KEY = "patterntopic"; + + private Boolean patternTopic=false; + + public Boolean getPatternTopic() { + return patternTopic; + } + + public void setPatternTopic(Boolean patternTopic) { + if (patternTopic==null){ + return; + } + this.patternTopic = patternTopic; + } + + public KafkaSourceTableInfo(){ + super.setType(CURR_TYPE); + } + + public Map kafkaParam = new HashMap<>(); + + public void addKafkaParam(String key,String value){ + kafkaParam.put(key,value); + } + + public String getKafkaParam(String key){ + return kafkaParam.get(key); + } + + public Set getKafkaParamKeys(){ + return kafkaParam.keySet(); + } + + @Override + public boolean check() { + Preconditions.checkNotNull(kafkaParam.get("bootstrap.servers"), "kafka of bootstrapServers is required"); + Preconditions.checkNotNull(kafkaParam.get("topic"), "kafka of topic is required"); + String offset = kafkaParam.get("auto.offset.reset"); + Preconditions.checkState(offset.equalsIgnoreCase("latest") + || offset.equalsIgnoreCase("earliest"), "kafka of offsetReset set fail"); + return false; + } + + @Override + public String getType() { + return super.getType(); + } +} diff --git a/elasticsearch7/pom.xml b/kafka08/pom.xml similarity index 80% rename from elasticsearch7/pom.xml rename to kafka08/pom.xml index 8f1df341b..ced039c1c 100644 --- a/elasticsearch7/pom.xml +++ b/kafka08/pom.xml @@ -9,20 +9,15 @@ 4.0.0 - - - 7.9.2 - - - sql.elasticsearch7 + sql.kafka08 pom + - elasticsearch7-side - elasticsearch7-sink + kafka08-source + kafka08-sink - junit junit @@ -36,7 +31,6 @@ 1.0-SNAPSHOT provided - diff --git a/kafka09/kafka09-sink/pom.xml b/kafka09/kafka09-sink/pom.xml index 379c1a97e..7b16fade8 100644 --- a/kafka09/kafka09-sink/pom.xml +++ b/kafka09/kafka09-sink/pom.xml @@ -18,9 +18,9 @@ - sql.sink.kafka-base - com.dtstack.flink - 1.0-SNAPSHOT + org.apache.flink + flink-json + ${flink.version} @@ -37,7 +37,6 @@ shade - false org.slf4j @@ -71,14 +70,14 @@ - + - + diff --git a/kafka09/kafka09-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerCsvSerialization.java b/kafka09/kafka09-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerCsvSerialization.java new file mode 100644 index 000000000..bccf7ac9e --- /dev/null +++ b/kafka09/kafka09-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerCsvSerialization.java @@ -0,0 +1,120 @@ +package com.dtstack.flink.sql.sink.kafka; + +import org.apache.commons.lang3.StringEscapeUtils; +import org.apache.flink.api.common.ExecutionConfig; +import org.apache.flink.api.common.typeinfo.TypeInformation; +import org.apache.flink.api.common.typeutils.TypeSerializer; +import org.apache.flink.api.common.typeutils.TypeSerializerSnapshot; +import org.apache.flink.api.common.typeutils.base.TypeSerializerSingleton; +import org.apache.flink.core.memory.DataInputView; +import org.apache.flink.core.memory.DataOutputView; +import org.apache.flink.types.Row; +import org.apache.flink.types.StringValue; + +import java.io.IOException; + +import static org.apache.flink.api.java.typeutils.runtime.NullMaskUtils.writeNullMask; +/** + * Date: 2018/12/18 + * Company: www.dtstack.com + * @author DocLi + * + * @modifyer maqi + * + */ +public final class CustomerCsvSerialization extends TypeSerializerSingleton { + + private static final long serialVersionUID = 1L; + + private String fieldDelimiter = "\u0001"; + private TypeInformation[] fieldTypes; + private TypeSerializer[] fieldSerializers; + private static final Row EMPTY = null; + + public CustomerCsvSerialization(String fielddelimiter,TypeInformation[] fieldTypes) { + this.fieldDelimiter = fielddelimiter; + this.fieldTypes = fieldTypes; + this.fieldSerializers = (TypeSerializer[])createSerializer(new ExecutionConfig()); + } + + public TypeSerializer[] createSerializer(ExecutionConfig config) { + int len = fieldTypes.length; + TypeSerializer[] fieldSerializers = new TypeSerializer[len]; + for (int i = 0; i < len; i++) { + fieldSerializers[i] = fieldTypes[i].createSerializer(config); + } + return fieldSerializers; + } + + @Override + public boolean isImmutableType() { + return true; + } + + @Override + public Row createInstance() { + return EMPTY; + } + + @Override + public Row copy(Row from) { + return null; + } + + @Override + public Row copy(Row from, Row reuse) { + return null; + } + + @Override + public int getLength() { + return -1; + } + + @Override + public void serialize(Row record, DataOutputView target) throws IOException { + int len = fieldSerializers.length; + + if (record.getArity() != len) { + throw new RuntimeException("Row arity of from does not match serializers."); + } + + // write a null mask + writeNullMask(len, record, target); + + // serialize non-null fields + StringBuffer stringBuffer = new StringBuffer(); + for (int i = 0; i < len; i++) { + Object o = record.getField(i); + if (o != null) { + //fieldSerializers[i].serialize(o, target); + stringBuffer.append(o); + } + if(i != len-1){ + stringBuffer.append(StringEscapeUtils.unescapeJava(fieldDelimiter)); + //fieldSerializers[i].serialize(fieldDelimiter, target); + } + } + StringValue.writeString(stringBuffer.toString(), target); + } + + @Override + public Row deserialize(DataInputView source) throws IOException { + return null; + } + + @Override + public Row deserialize(Row reuse, DataInputView source) throws IOException { + return null; + } + + @Override + public void copy(DataInputView source, DataOutputView target) throws IOException { + StringValue.copyString(source, target); + } + + @Override + public TypeSerializerSnapshot snapshotConfiguration() { + return null; + } +} diff --git a/kafka09/kafka09-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerFlinkKafkaProducer09.java b/kafka09/kafka09-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerFlinkKafkaProducer09.java new file mode 100644 index 000000000..1660063c4 --- /dev/null +++ b/kafka09/kafka09-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerFlinkKafkaProducer09.java @@ -0,0 +1,58 @@ +/** + * 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 com.dtstack.flink.sql.sink.kafka; + +import com.dtstack.flink.sql.metric.MetricConstant; +import org.apache.flink.api.common.functions.RuntimeContext; +import org.apache.flink.api.common.serialization.SerializationSchema; +import org.apache.flink.configuration.Configuration; +import org.apache.flink.metrics.Counter; +import org.apache.flink.metrics.MeterView; +import org.apache.flink.streaming.connectors.kafka.FlinkKafkaProducer09; +import java.util.Properties; + +/** + * Reason: + * Date: 2019/4/24 + * Company: www.dtstack.com + * + * @author maqi + */ +public class CustomerFlinkKafkaProducer09 extends FlinkKafkaProducer09 { + + CustomerJsonRowSerializationSchema schema; + + public CustomerFlinkKafkaProducer09(String topicId, SerializationSchema serializationSchema, Properties producerConfig) { + super(topicId, serializationSchema, producerConfig); + this.schema = (CustomerJsonRowSerializationSchema) serializationSchema; + } + + @Override + public void open(Configuration configuration) { + producer = getKafkaProducer(this.producerConfig); + + RuntimeContext ctx = getRuntimeContext(); + Counter counter = ctx.getMetricGroup().counter(MetricConstant.DT_NUM_RECORDS_OUT); + MeterView meter = ctx.getMetricGroup().meter(MetricConstant.DT_NUM_RECORDS_OUT_RATE, new MeterView(counter, 20)); + + schema.setCounter(counter); + + super.open(configuration); + } + +} diff --git a/kafka-base/kafka-base-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/serialization/DTJsonRowSerializationSchema.java b/kafka09/kafka09-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerJsonRowSerializationSchema.java similarity index 81% rename from kafka-base/kafka-base-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/serialization/DTJsonRowSerializationSchema.java rename to kafka09/kafka09-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerJsonRowSerializationSchema.java index da22dcc55..be9538464 100644 --- a/kafka-base/kafka-base-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/serialization/DTJsonRowSerializationSchema.java +++ b/kafka09/kafka09-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerJsonRowSerializationSchema.java @@ -15,9 +15,8 @@ * limitations under the License. */ -package com.dtstack.flink.sql.sink.kafka.serialization; +package com.dtstack.flink.sql.sink.kafka; -import org.apache.flink.annotation.PublicEvolving; import org.apache.flink.api.common.serialization.SerializationSchema; import org.apache.flink.api.common.typeinfo.BasicArrayTypeInfo; import org.apache.flink.api.common.typeinfo.PrimitiveArrayTypeInfo; @@ -25,12 +24,14 @@ import org.apache.flink.api.common.typeinfo.Types; import org.apache.flink.api.java.typeutils.ObjectArrayTypeInfo; import org.apache.flink.api.java.typeutils.RowTypeInfo; +import org.apache.flink.formats.json.JsonRowDeserializationSchema; import org.apache.flink.formats.json.JsonRowSchemaConverter; -import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.JsonNode; -import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.ObjectMapper; -import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.node.ArrayNode; -import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.node.ContainerNode; -import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.node.ObjectNode; +import org.apache.flink.metrics.Counter; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ContainerNode; +import com.fasterxml.jackson.databind.node.ObjectNode; import org.apache.flink.types.Row; import org.apache.flink.util.Preconditions; @@ -39,7 +40,6 @@ import java.sql.Time; import java.sql.Timestamp; import java.text.SimpleDateFormat; -import java.util.Objects; /** * Serialization schema that serializes an object of Flink types into a JSON bytes. @@ -47,10 +47,9 @@ *

Serializes the input Flink object into a JSON string and * converts it into byte[]. * - *

Result byte[] messages can be deserialized using {@link DTJsonRowDeserializationSchema}. + *

Result byte[] messages can be deserialized using {@link JsonRowDeserializationSchema}. */ -@PublicEvolving -public class DTJsonRowSerializationSchema implements SerializationSchema { +public class CustomerJsonRowSerializationSchema implements SerializationSchema { private static final long serialVersionUID = -2885556750743978636L; @@ -72,12 +71,14 @@ public class DTJsonRowSerializationSchema implements SerializationSchema { /** Reusable object node. */ private transient ObjectNode node; + private Counter counter; + /** * Creates a JSON serialization schema for the given type information. * * @param typeInfo The field names of {@link Row} are used to map to JSON properties. */ - public DTJsonRowSerializationSchema(TypeInformation typeInfo) { + public CustomerJsonRowSerializationSchema(TypeInformation typeInfo) { Preconditions.checkNotNull(typeInfo, "Type information"); this.typeInfo = typeInfo; } @@ -89,7 +90,7 @@ public DTJsonRowSerializationSchema(TypeInformation typeInfo) { * * @see http://json-schema.org/ */ - public DTJsonRowSerializationSchema(String jsonSchema) { + public CustomerJsonRowSerializationSchema(String jsonSchema) { this(JsonRowSchemaConverter.convert(jsonSchema)); } @@ -101,6 +102,7 @@ public byte[] serialize(Row row) { try { convertRow(node, (RowTypeInfo) typeInfo, row); + counter.inc(); return mapper.writeValueAsBytes(node); } catch (Throwable t) { throw new RuntimeException("Could not serialize row '" + row + "'. " + @@ -108,23 +110,6 @@ public byte[] serialize(Row row) { } } - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - final DTJsonRowSerializationSchema that = (DTJsonRowSerializationSchema) o; - return Objects.equals(typeInfo, that.typeInfo); - } - - @Override - public int hashCode() { - return Objects.hash(typeInfo); - } - // -------------------------------------------------------------------------------------------- private ObjectNode convertRow(ObjectNode reuse, RowTypeInfo info, Row row) { @@ -151,34 +136,34 @@ private ObjectNode convertRow(ObjectNode reuse, RowTypeInfo info, Row row) { } private JsonNode convert(ContainerNode container, JsonNode reuse, TypeInformation info, Object object) { - if (info.equals(Types.VOID) || object == null) { + if (info == Types.VOID || object == null) { return container.nullNode(); - } else if (info.equals(Types.BOOLEAN)) { + } else if (info == Types.BOOLEAN) { return container.booleanNode((Boolean) object); - } else if (info.equals(Types.STRING)) { + } else if (info == Types.STRING) { return container.textNode((String) object); - } else if (info.equals(Types.BIG_DEC)) { + } else if (info == Types.BIG_DEC) { // convert decimal if necessary if (object instanceof BigDecimal) { return container.numberNode((BigDecimal) object); } return container.numberNode(BigDecimal.valueOf(((Number) object).doubleValue())); - } else if (info.equals(Types.BIG_INT)) { + } else if (info == Types.BIG_INT) { // convert integer if necessary if (object instanceof BigInteger) { return container.numberNode((BigInteger) object); } return container.numberNode(BigInteger.valueOf(((Number) object).longValue())); - } else if (info.equals(Types.SQL_DATE)) { + } else if (info == Types.SQL_DATE) { return container.textNode(object.toString()); - } else if (info.equals(Types.SQL_TIME)) { + } else if (info == Types.SQL_TIME) { final Time time = (Time) object; // strip milliseconds if possible if (time.getTime() % 1000 > 0) { return container.textNode(timeFormatWithMillis.format(time)); } return container.textNode(timeFormat.format(time)); - } else if (info.equals(Types.SQL_TIMESTAMP)) { + } else if (info == Types.SQL_TIMESTAMP) { return container.textNode(timestampFormat.format((Timestamp) object)); } else if (info instanceof RowTypeInfo) { if (reuse != null && reuse instanceof ObjectNode) { @@ -198,7 +183,7 @@ private JsonNode convert(ContainerNode container, JsonNode reuse, TypeInforma } else { return convertObjectArray(null, ((BasicArrayTypeInfo) info).getComponentInfo(), (Object[]) object); } - } else if (info instanceof PrimitiveArrayTypeInfo && ((PrimitiveArrayTypeInfo) info).getComponentType().equals(Types.BYTE)) { + } else if (info instanceof PrimitiveArrayTypeInfo && ((PrimitiveArrayTypeInfo) info).getComponentType() == Types.BYTE) { return container.binaryNode((byte[]) object); } else { // for types that were specified without JSON schema @@ -223,4 +208,12 @@ private ArrayNode convertObjectArray(ArrayNode reuse, TypeInformation info, O } return reuse; } + + public Counter getCounter() { + return counter; + } + + public void setCounter(Counter counter) { + this.counter = counter; + } } diff --git a/kafka09/kafka09-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerKafka09JsonTableSink.java b/kafka09/kafka09-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerKafka09JsonTableSink.java new file mode 100644 index 000000000..ffd44e9f7 --- /dev/null +++ b/kafka09/kafka09-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerKafka09JsonTableSink.java @@ -0,0 +1,70 @@ +/** + * 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 com.dtstack.flink.sql.sink.kafka; + +import org.apache.flink.api.common.serialization.SerializationSchema; +import org.apache.flink.streaming.api.datastream.DataStream; +import org.apache.flink.streaming.api.functions.sink.SinkFunction; +import org.apache.flink.streaming.connectors.kafka.FlinkKafkaProducerBase; +import org.apache.flink.streaming.connectors.kafka.Kafka09TableSink; +import org.apache.flink.streaming.connectors.kafka.partitioner.FlinkKafkaPartitioner; +import org.apache.flink.table.api.TableSchema; +import org.apache.flink.table.utils.TableConnectorUtils; +import org.apache.flink.types.Row; + +import java.util.Optional; +import java.util.Properties; + +/** + * Reason: add schema info + * Date: 2019/4/8 + * Company: www.dtstack.com + * + * @author maqi + */ +public class CustomerKafka09JsonTableSink extends Kafka09TableSink { + + + protected SerializationSchema schema; + + + + + @Deprecated + public CustomerKafka09JsonTableSink(TableSchema schema, + String topic, + Properties properties, + Optional> partitioner, + SerializationSchema serializationSchema) { + super(schema, topic, properties, partitioner, serializationSchema); + this.schema = serializationSchema; + } + + @Override + protected FlinkKafkaProducerBase createKafkaProducer(String s, Properties properties, SerializationSchema serializationSchema, Optional> optional) { + return new CustomerFlinkKafkaProducer09<>(topic, serializationSchema, properties); + } + + @Override + public void emitDataStream(DataStream dataStream) { + SinkFunction kafkaProducer = createKafkaProducer(topic, properties, schema, partitioner); + // always enable flush on checkpoint to achieve at-least-once if query runs with checkpointing enabled. + //kafkaProducer.setFlushOnCheckpoint(true); + dataStream.addSink(kafkaProducer).name(TableConnectorUtils.generateRuntimeName(this.getClass(), getFieldNames())); + } +} diff --git a/kafka09/kafka09-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/KafkaProducer09.java b/kafka09/kafka09-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/KafkaProducer09.java deleted file mode 100644 index 68cf472a8..000000000 --- a/kafka09/kafka09-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/KafkaProducer09.java +++ /dev/null @@ -1,65 +0,0 @@ -/** - * 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 com.dtstack.flink.sql.sink.kafka; - -import com.dtstack.flink.sql.format.SerializationMetricWrapper; -import com.dtstack.flink.sql.sink.kafka.serialization.CustomerKeyedSerializationSchema; -import org.apache.flink.api.common.functions.RuntimeContext; -import org.apache.flink.api.common.serialization.SerializationSchema; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.configuration.Configuration; -import org.apache.flink.streaming.connectors.kafka.FlinkKafkaProducer09; -import org.apache.flink.streaming.connectors.kafka.partitioner.FlinkKafkaPartitioner; -import org.apache.flink.types.Row; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Optional; -import java.util.Properties; - -/** - * Reason: - * Date: 2019/4/24 - * Company: www.dtstack.com - * - * @author maqi - */ -public class KafkaProducer09 extends FlinkKafkaProducer09> { - - private static final Logger LOG = LoggerFactory.getLogger(KafkaProducer09.class); - - private static final long serialVersionUID = 1L; - - private SerializationMetricWrapper serializationMetricWrapper; - - public KafkaProducer09(String topicId, SerializationSchema> serializationSchema, Properties producerConfig, - Optional>> customPartitioner, String[] partitionKeys) { - super(topicId, new CustomerKeyedSerializationSchema((SerializationMetricWrapper) serializationSchema, partitionKeys), producerConfig, customPartitioner.orElse(null)); - this.serializationMetricWrapper = (SerializationMetricWrapper) serializationSchema; - } - - @Override - public void open(Configuration configuration) { - LOG.info("----KafkaProducer09 open ---"); - RuntimeContext runtimeContext = getRuntimeContext(); - serializationMetricWrapper.setRuntimeContext(runtimeContext); - serializationMetricWrapper.initMetric(); - super.open(configuration); - } - -} \ No newline at end of file diff --git a/kafka09/kafka09-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/KafkaProducer09Factory.java b/kafka09/kafka09-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/KafkaProducer09Factory.java deleted file mode 100644 index 60f8ca81d..000000000 --- a/kafka09/kafka09-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/KafkaProducer09Factory.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.kafka; - -import com.dtstack.flink.sql.sink.kafka.table.KafkaSinkTableInfo; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.streaming.api.functions.sink.RichSinkFunction; -import org.apache.flink.streaming.connectors.kafka.partitioner.FlinkKafkaPartitioner; -import org.apache.flink.types.Row; - -import java.util.Optional; -import java.util.Properties; - -/** - * company: www.dtstack.com - * - * @author: toutian - * create: 2019/12/24 - */ -public class KafkaProducer09Factory extends AbstractKafkaProducerFactory { - - @Override - public RichSinkFunction> createKafkaProducer(KafkaSinkTableInfo kafkaSinkTableInfo, TypeInformation> typeInformation, Properties properties, - Optional>> partitioner, String[] partitionKeys) { - return new KafkaProducer09(kafkaSinkTableInfo.getTopic(), createSerializationMetricWrapper(kafkaSinkTableInfo, typeInformation), properties, partitioner, partitionKeys); - } -} diff --git a/kafka09/kafka09-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/KafkaSink.java b/kafka09/kafka09-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/KafkaSink.java index b560b4fa4..a6c3b98a4 100644 --- a/kafka09/kafka09-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/KafkaSink.java +++ b/kafka09/kafka09-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/KafkaSink.java @@ -18,8 +18,22 @@ package com.dtstack.flink.sql.sink.kafka; +import com.dtstack.flink.sql.sink.IStreamSinkGener; import com.dtstack.flink.sql.sink.kafka.table.KafkaSinkTableInfo; -import com.dtstack.flink.sql.table.AbstractTargetTableInfo; +import com.dtstack.flink.sql.table.TargetTableInfo; +import org.apache.flink.api.common.serialization.SerializationSchema; +import org.apache.flink.api.common.typeinfo.TypeInformation; +import org.apache.flink.api.java.tuple.Tuple2; +import org.apache.flink.api.java.typeutils.RowTypeInfo; +import org.apache.flink.api.java.typeutils.TupleTypeInfo; +import org.apache.flink.streaming.api.datastream.DataStream; +import org.apache.flink.streaming.connectors.kafka.KafkaTableSinkBase; +import org.apache.flink.streaming.connectors.kafka.partitioner.FlinkFixedPartitioner; +import org.apache.flink.streaming.connectors.kafka.partitioner.FlinkKafkaPartitioner; +import org.apache.flink.table.api.TableSchema; +import org.apache.flink.table.sinks.RetractStreamTableSink; +import org.apache.flink.table.sinks.TableSink; +import org.apache.flink.types.Row; import java.util.Optional; import java.util.Properties; @@ -31,23 +45,105 @@ * @author DocLi * @modifyer maqi */ -public class KafkaSink extends AbstractKafkaSink { - @Override - public KafkaSink genStreamSink(AbstractTargetTableInfo targetTableInfo) { - KafkaSinkTableInfo kafka09SinkTableInfo = (KafkaSinkTableInfo) targetTableInfo; - - Properties kafkaProperties = getKafkaProperties(kafka09SinkTableInfo); - this.tableName = kafka09SinkTableInfo.getName(); - this.updateMode = kafka09SinkTableInfo.getUpdateMode(); - this.topic = kafka09SinkTableInfo.getTopic(); - this.partitioner = Optional.of(new CustomerFlinkPartition<>()); - this.partitionKeys = getPartitionKeys(kafka09SinkTableInfo); - this.fieldNames = kafka09SinkTableInfo.getFields(); - this.fieldTypes = getTypeInformations(kafka09SinkTableInfo); - this.schema = buildTableSchema(fieldNames, fieldTypes); - this.parallelism = kafka09SinkTableInfo.getParallelism(); - this.sinkOperatorName = SINK_OPERATOR_NAME_TPL.replace("${topic}", topic).replace("${table}", tableName); - this.kafkaProducer011 = new KafkaProducer09Factory().createKafkaProducer(kafka09SinkTableInfo, getOutputType(), kafkaProperties, partitioner, partitionKeys); - return this; - } +public class KafkaSink implements RetractStreamTableSink, IStreamSinkGener { + + protected String[] fieldNames; + + protected TypeInformation[] fieldTypes; + + protected String topic; + + protected Properties properties; + + /** Serialization schema for encoding records to Kafka. */ + protected SerializationSchema serializationSchema; + + /** The schema of the table. */ + private TableSchema schema; + + /** Partitioner to select Kafka partition for each item. */ + protected Optional> partitioner; + + protected int parallelism; + + + + @Override + public KafkaSink genStreamSink(TargetTableInfo targetTableInfo) { + KafkaSinkTableInfo kafka09SinkTableInfo = (KafkaSinkTableInfo) targetTableInfo; + this.topic = kafka09SinkTableInfo.getTopic(); + + properties = new Properties(); + properties.setProperty("bootstrap.servers", kafka09SinkTableInfo.getBootstrapServers()); + for (String key : kafka09SinkTableInfo.getKafkaParamKeys()) { + properties.setProperty(key, kafka09SinkTableInfo.getKafkaParam(key)); + } + + this.partitioner = Optional.of(new FlinkFixedPartitioner<>()); + this.fieldNames = kafka09SinkTableInfo.getFields(); + TypeInformation[] types = new TypeInformation[kafka09SinkTableInfo.getFields().length]; + for (int i = 0; i < kafka09SinkTableInfo.getFieldClasses().length; i++) { + types[i] = TypeInformation.of(kafka09SinkTableInfo.getFieldClasses()[i]); + } + this.fieldTypes = types; + + TableSchema.Builder schemaBuilder = TableSchema.builder(); + for (int i=0;i getRecordType() { + return new RowTypeInfo(fieldTypes, fieldNames); + } + + @Override + public void emitDataStream(DataStream> dataStream) { + KafkaTableSinkBase kafkaTableSink = new CustomerKafka09JsonTableSink( + schema, + topic, + properties, + partitioner, + serializationSchema + ); + + DataStream ds = dataStream.map((Tuple2 record) -> { + return record.f1; + }).returns(getOutputType().getTypeAt(1)).setParallelism(parallelism); + + kafkaTableSink.emitDataStream(ds); + } + + @Override + public TupleTypeInfo> getOutputType() { + return new TupleTypeInfo(org.apache.flink.table.api.Types.BOOLEAN(), new RowTypeInfo(fieldTypes, fieldNames)); + } + + @Override + public String[] getFieldNames() { + return fieldNames; + } + + @Override + public TypeInformation[] getFieldTypes() { + return fieldTypes; + } + + @Override + public TableSink> configure(String[] fieldNames, TypeInformation[] fieldTypes) { + this.fieldNames = fieldNames; + this.fieldTypes = fieldTypes; + return this; + } + } diff --git a/kafka09/kafka09-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/table/KafkaSinkParser.java b/kafka09/kafka09-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/table/KafkaSinkParser.java new file mode 100644 index 000000000..dd4d4450f --- /dev/null +++ b/kafka09/kafka09-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/table/KafkaSinkParser.java @@ -0,0 +1,57 @@ +/* + * 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 com.dtstack.flink.sql.sink.kafka.table; + +import com.dtstack.flink.sql.table.AbsTableParser; +import com.dtstack.flink.sql.table.TableInfo; +import com.dtstack.flink.sql.util.MathUtil; + +import java.util.Map; + +/** + * Date: 2018/12/18 + * Company: www.dtstack.com + * @author DocLi + * + * @modifyer maqi + * + */ +public class KafkaSinkParser extends AbsTableParser { + @Override + public TableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { + KafkaSinkTableInfo kafka09SinkTableInfo = new KafkaSinkTableInfo(); + kafka09SinkTableInfo.setName(tableName); + parseFieldsInfo(fieldsInfo, kafka09SinkTableInfo); + + + kafka09SinkTableInfo.setBootstrapServers(MathUtil.getString(props.get(KafkaSinkTableInfo.BOOTSTRAPSERVERS_KEY.toLowerCase()))); + kafka09SinkTableInfo.setTopic(MathUtil.getString(props.get(KafkaSinkTableInfo.TOPIC_KEY.toLowerCase()))); + + Integer parallelism = MathUtil.getIntegerVal(props.get(KafkaSinkTableInfo.PARALLELISM_KEY.toLowerCase())); + kafka09SinkTableInfo.setParallelism(parallelism); + + for (String key : props.keySet()) { + if (!key.isEmpty() && key.startsWith("kafka.")) { + kafka09SinkTableInfo.addKafkaParam(key.substring(6), props.get(key).toString()); + } + } + kafka09SinkTableInfo.check(); + return kafka09SinkTableInfo; + } +} diff --git a/kafka09/kafka09-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/table/KafkaSinkTableInfo.java b/kafka09/kafka09-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/table/KafkaSinkTableInfo.java new file mode 100644 index 000000000..0e6ba70bd --- /dev/null +++ b/kafka09/kafka09-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/table/KafkaSinkTableInfo.java @@ -0,0 +1,94 @@ +/* + * 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 com.dtstack.flink.sql.sink.kafka.table; + +import com.dtstack.flink.sql.table.TargetTableInfo; +import com.google.common.base.Preconditions; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +/** + * Date: 2018/12/18 + * Company: www.dtstack.com + * + * @author DocLi + * @modifyer maqi + */ +public class KafkaSinkTableInfo extends TargetTableInfo { + //version + private static final String CURR_TYPE = "kafka09"; + + public KafkaSinkTableInfo() { + super.setType(CURR_TYPE); + } + + public static final String BOOTSTRAPSERVERS_KEY = "bootstrapServers"; + + public static final String TOPIC_KEY = "topic"; + + private String bootstrapServers; + + private String topic; + + public Map kafkaParam = new HashMap(); + + + public void addKafkaParam(String key,String value){ + kafkaParam.put(key,value); + } + + public String getKafkaParam(String key){ + return kafkaParam.get(key); + } + + public Set getKafkaParamKeys(){ + return kafkaParam.keySet(); + } + + public String getBootstrapServers() { + return bootstrapServers; + } + + public void setBootstrapServers(String bootstrapServers) { + this.bootstrapServers = bootstrapServers; + } + + public String getTopic() { + return topic; + } + + public void setTopic(String topic) { + this.topic = topic; + } + + @Override + public boolean check() { + Preconditions.checkNotNull(bootstrapServers, "kafka of bootstrapServers is required"); + Preconditions.checkNotNull(topic, "kafka of topic is required"); + return false; + } + + @Override + public String getType() { +// return super.getType() + SOURCE_SUFFIX; + return super.getType(); + } +} diff --git a/kafka09/kafka09-sink/src/test/java/com/dtstack/flink/sql/source/kafka/KafkaSinkTest.java b/kafka09/kafka09-sink/src/test/java/com/dtstack/flink/sql/source/kafka/KafkaSinkTest.java deleted file mode 100644 index dfc3c7f06..000000000 --- a/kafka09/kafka09-sink/src/test/java/com/dtstack/flink/sql/source/kafka/KafkaSinkTest.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.dtstack.flink.sql.source.kafka; - -import com.dtstack.flink.sql.sink.kafka.KafkaSink; -import com.dtstack.flink.sql.sink.kafka.table.KafkaSinkTableInfo; -import com.google.common.collect.Sets; -import org.junit.Test; - -import static org.mockito.Mockito.*; - -public class KafkaSinkTest { - - @Test - public void mockGenStreamSink(){ - KafkaSinkTableInfo kafkaSinkTableInfo = mock(KafkaSinkTableInfo.class); - when(kafkaSinkTableInfo.getName()).thenReturn("roc"); - when(kafkaSinkTableInfo.getTopic()).thenReturn("topic"); - when(kafkaSinkTableInfo.getBootstrapServers()).thenReturn("localhost"); - when(kafkaSinkTableInfo.getKafkaParamKeys()).thenReturn(Sets.newHashSet("aa")); - when(kafkaSinkTableInfo.getKafkaParam("aa")).thenReturn("xx"); - when(kafkaSinkTableInfo.getPartitionKeys()).thenReturn(null); - when(kafkaSinkTableInfo.getFields()).thenReturn(new String[]{"aa"}); - when(kafkaSinkTableInfo.getFieldClasses()).thenReturn(new Class[]{String.class}); - when(kafkaSinkTableInfo.getParallelism()).thenReturn(1); - when(kafkaSinkTableInfo.getSinkDataType()).thenReturn("json"); - when(kafkaSinkTableInfo.getUpdateMode()).thenReturn("append"); - - KafkaSink kafkaSink = new KafkaSink(); - KafkaSink kafkaSinkSpy = spy(kafkaSink); - kafkaSinkSpy.genStreamSink(kafkaSinkTableInfo); - } -} diff --git a/kafka09/kafka09-source/pom.xml b/kafka09/kafka09-source/pom.xml index 5f2ab9d2a..84e88348a 100644 --- a/kafka09/kafka09-source/pom.xml +++ b/kafka09/kafka09-source/pom.xml @@ -14,13 +14,6 @@ kafka09-source http://maven.apache.org - - - sql.source.kafka-base - com.dtstack.flink - 1.0-SNAPSHOT - - @@ -35,7 +28,6 @@ shade - false org.slf4j @@ -69,14 +61,14 @@ - + - + diff --git a/kafka09/kafka09-source/src/main/java/com/dtstack/flink/sql/source/kafka/CustomerJsonDeserialization.java b/kafka09/kafka09-source/src/main/java/com/dtstack/flink/sql/source/kafka/CustomerJsonDeserialization.java new file mode 100644 index 000000000..6353ea447 --- /dev/null +++ b/kafka09/kafka09-source/src/main/java/com/dtstack/flink/sql/source/kafka/CustomerJsonDeserialization.java @@ -0,0 +1,287 @@ +/* + * 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 com.dtstack.flink.sql.source.kafka; + + +import com.dtstack.flink.sql.source.AbsDeserialization; +import com.dtstack.flink.sql.source.kafka.metric.KafkaTopicPartitionLagMetric; +import com.dtstack.flink.sql.table.TableInfo; +import com.fasterxml.jackson.databind.node.ArrayNode; +import org.apache.flink.api.common.typeinfo.TypeInformation; +import org.apache.flink.api.common.typeinfo.Types; +import org.apache.flink.api.java.typeutils.RowTypeInfo; +import com.google.common.base.Strings; +import org.apache.flink.metrics.MetricGroup; +import com.google.common.collect.Maps; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.flink.streaming.connectors.kafka.internal.KafkaConsumerThread; +import org.apache.flink.streaming.connectors.kafka.internals.AbstractFetcher; +import org.apache.flink.types.Row; +import org.apache.kafka.clients.consumer.KafkaConsumer; +import org.apache.kafka.clients.consumer.internals.SubscriptionState; +import org.apache.kafka.common.TopicPartition; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.IOException; +import java.lang.reflect.Field; +import java.sql.Date; +import java.sql.Time; +import java.sql.Timestamp; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static com.dtstack.flink.sql.metric.MetricConstant.*; + +/** + * json string parsing custom + * Date: 2018/09/18 + * Company: www.dtstack.com + * @author sishu.yss + */ + +public class CustomerJsonDeserialization extends AbsDeserialization { + + private static final Logger LOG = LoggerFactory.getLogger(CustomerJsonDeserialization.class); + + private static final long serialVersionUID = 2385115520960444192L; + + private static int dirtyDataFrequency = 1000; + + private final ObjectMapper objectMapper = new ObjectMapper(); + + /** Type information describing the result type. */ + private final TypeInformation typeInfo; + + /** Field names to parse. Indices match fieldTypes indices. */ + private final String[] fieldNames; + + /** Types to parse fields as. Indices match fieldNames indices. */ + private final TypeInformation[] fieldTypes; + + private AbstractFetcher fetcher; + + private boolean firstMsg = true; + + private Map nodeAndJsonNodeMapping = Maps.newHashMap(); + + private Map rowAndFieldMapping; + + private List fieldExtraInfos; + + public CustomerJsonDeserialization(TypeInformation typeInfo, Map rowAndFieldMapping, List fieldExtraInfos){ + this.typeInfo = typeInfo; + this.fieldNames = ((RowTypeInfo) typeInfo).getFieldNames(); + this.fieldTypes = ((RowTypeInfo) typeInfo).getFieldTypes(); + this.rowAndFieldMapping= rowAndFieldMapping; + this.fieldExtraInfos = fieldExtraInfos; + } + + @Override + public Row deserialize(byte[] message) throws IOException { + + if(firstMsg){ + try { + registerPtMetric(fetcher); + } catch (Exception e) { + LOG.error("register topic partition metric error.", e); + } + + firstMsg = false; + } + + try { + JsonNode root = objectMapper.readTree(message); + if (numInRecord.getCount() % dirtyDataFrequency == 0) { + LOG.info(root.toString()); + } + + numInRecord.inc(); + numInBytes.inc(message.length); + + parseTree(root, null); + Row row = new Row(fieldNames.length); + + for (int i = 0; i < fieldNames.length; i++) { + JsonNode node = getIgnoreCase(fieldNames[i]); + TableInfo.FieldExtraInfo fieldExtraInfo = fieldExtraInfos.get(i); + + if (node == null) { + if (fieldExtraInfo != null && fieldExtraInfo.getNotNull()) { + throw new IllegalStateException("Failed to find field with name '" + + fieldNames[i] + "'."); + } else { + row.setField(i, null); + } + } else { + // Read the value as specified type + Object value = convert(node, fieldTypes[i]); + row.setField(i, value); + } + } + + numInResolveRecord.inc(); + return row; + } catch (Exception e) { + //add metric of dirty data + if (dirtyDataCounter.getCount() % dirtyDataFrequency == 0) { + LOG.info("dirtyData: " + new String(message)); + LOG.info(" " ,e); + } + dirtyDataCounter.inc(); + return null; + }finally { + nodeAndJsonNodeMapping.clear(); + } + } + + public JsonNode getIgnoreCase(String key) { + String nodeMappingKey = rowAndFieldMapping.getOrDefault(key, key); + return nodeAndJsonNodeMapping.get(nodeMappingKey); + } + + + private void parseTree(JsonNode jsonNode, String prefix){ + + if (jsonNode.isArray()) { + ArrayNode array = (ArrayNode) jsonNode; + for (int i = 0; i < array.size(); i++) { + JsonNode child = array.get(i); + String nodeKey = getNodeKey(prefix, i); + + if (child.isValueNode()) { + nodeAndJsonNodeMapping.put(nodeKey, child); + } else { + if (rowAndFieldMapping.containsValue(nodeKey)) { + nodeAndJsonNodeMapping.put(nodeKey, child); + } + parseTree(child, nodeKey); + } + } + return; + } + + Iterator iterator = jsonNode.fieldNames(); + while (iterator.hasNext()){ + String next = iterator.next(); + JsonNode child = jsonNode.get(next); + String nodeKey = getNodeKey(prefix, next); + + if (child.isValueNode()){ + nodeAndJsonNodeMapping.put(nodeKey, child); + } else if(child.isArray()){ + parseTree(child, nodeKey); + }else { + parseTree(child, nodeKey); + } + } + } + + private String getNodeKey(String prefix, String nodeName){ + if(Strings.isNullOrEmpty(prefix)){ + return nodeName; + } + + return prefix + "." + nodeName; + } + + private String getNodeKey(String prefix, int i) { + if (Strings.isNullOrEmpty(prefix)) { + return "[" + i + "]"; + } + + return prefix + "[" + i + "]"; + } + + public void setFetcher(AbstractFetcher fetcher) { + this.fetcher = fetcher; + } + + + protected void registerPtMetric(AbstractFetcher fetcher) throws Exception { + + Field consumerThreadField = fetcher.getClass().getSuperclass().getDeclaredField("consumerThread"); + consumerThreadField.setAccessible(true); + KafkaConsumerThread consumerThread = (KafkaConsumerThread) consumerThreadField.get(fetcher); + + Field hasAssignedPartitionsField = consumerThread.getClass().getDeclaredField("hasAssignedPartitions"); + hasAssignedPartitionsField.setAccessible(true); + + //wait until assignedPartitions + + boolean hasAssignedPartitions = (boolean) hasAssignedPartitionsField.get(consumerThread); + + if(!hasAssignedPartitions){ + throw new RuntimeException("wait 50 secs, but not assignedPartitions"); + } + + Field consumerField = consumerThread.getClass().getDeclaredField("consumer"); + consumerField.setAccessible(true); + + KafkaConsumer kafkaConsumer = (KafkaConsumer) consumerField.get(consumerThread); + Field subscriptionStateField = kafkaConsumer.getClass().getDeclaredField("subscriptions"); + subscriptionStateField.setAccessible(true); + + //topic partitions lag + SubscriptionState subscriptionState = (SubscriptionState) subscriptionStateField.get(kafkaConsumer); + Set assignedPartitions = subscriptionState.assignedPartitions(); + for(TopicPartition topicPartition : assignedPartitions){ + MetricGroup metricGroup = getRuntimeContext().getMetricGroup().addGroup(DT_TOPIC_GROUP, topicPartition.topic()) + .addGroup(DT_PARTITION_GROUP, topicPartition.partition() + ""); + metricGroup.gauge(DT_TOPIC_PARTITION_LAG_GAUGE, new KafkaTopicPartitionLagMetric(subscriptionState, topicPartition)); + } + + } + + private static String partitionLagMetricName(TopicPartition tp) { + return tp + ".records-lag"; + } + + private Object convert(JsonNode node, TypeInformation info) { + if (info.getTypeClass().equals(Types.BOOLEAN.getTypeClass())) { + return node.asBoolean(); + } else if (info.getTypeClass().equals(Types.STRING.getTypeClass())) { + return node.asText(); + } else if (info.getTypeClass().equals(Types.SQL_DATE.getTypeClass())) { + return Date.valueOf(node.asText()); + } else if (info.getTypeClass().equals(Types.SQL_TIME.getTypeClass())) { + // local zone + return Time.valueOf(node.asText()); + } else if (info.getTypeClass().equals(Types.SQL_TIMESTAMP.getTypeClass())) { + // local zone + return Timestamp.valueOf(node.asText()); + } else { + // for types that were specified without JSON schema + // e.g. POJOs + try { + return objectMapper.treeToValue(node, info.getTypeClass()); + } catch (JsonProcessingException e) { + throw new IllegalStateException("Unsupported type information '" + info + "' for node: " + node); + } + } + } + + + +} diff --git a/kafka09/kafka09-source/src/main/java/com/dtstack/flink/sql/source/kafka/CustomerKafka09Consumer.java b/kafka09/kafka09-source/src/main/java/com/dtstack/flink/sql/source/kafka/CustomerKafka09Consumer.java new file mode 100644 index 000000000..68d9c4958 --- /dev/null +++ b/kafka09/kafka09-source/src/main/java/com/dtstack/flink/sql/source/kafka/CustomerKafka09Consumer.java @@ -0,0 +1,73 @@ +/* + * 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 com.dtstack.flink.sql.source.kafka; + +import com.dtstack.flink.sql.source.AbsDeserialization; +import org.apache.flink.metrics.MetricGroup; +import org.apache.flink.streaming.api.functions.AssignerWithPeriodicWatermarks; +import org.apache.flink.streaming.api.functions.AssignerWithPunctuatedWatermarks; +import org.apache.flink.streaming.api.operators.StreamingRuntimeContext; +import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer09; +import org.apache.flink.streaming.connectors.kafka.config.OffsetCommitMode; +import org.apache.flink.streaming.connectors.kafka.internals.AbstractFetcher; +import org.apache.flink.streaming.connectors.kafka.internals.KafkaTopicPartition; +import org.apache.flink.types.Row; +import org.apache.flink.util.SerializedValue; + +import java.util.Arrays; +import java.util.Map; +import java.util.Properties; +import java.util.regex.Pattern; + +/** + * Reason: + * Date: 2018/10/12 + * Company: www.dtstack.com + * @author xuchao + */ + +public class CustomerKafka09Consumer extends FlinkKafkaConsumer09 { + + private static final long serialVersionUID = 4451177393982291909L; + + private CustomerJsonDeserialization customerJsonDeserialization; + + public CustomerKafka09Consumer(String topic, AbsDeserialization valueDeserializer, Properties props) { + super(Arrays.asList(topic.split(",")), valueDeserializer, props); + this.customerJsonDeserialization = (CustomerJsonDeserialization) valueDeserializer; + } + public CustomerKafka09Consumer(Pattern subscriptionPattern, AbsDeserialization valueDeserializer, Properties props) { + super(subscriptionPattern, valueDeserializer, props); + this.customerJsonDeserialization = (CustomerJsonDeserialization) valueDeserializer; + } + + @Override + public void run(SourceContext sourceContext) throws Exception { + customerJsonDeserialization.setRuntimeContext(getRuntimeContext()); + customerJsonDeserialization.initMetric(); + super.run(sourceContext); + } + + @Override + protected AbstractFetcher createFetcher(SourceContext sourceContext, Map assignedPartitionsWithInitialOffsets, SerializedValue> watermarksPeriodic, SerializedValue> watermarksPunctuated, StreamingRuntimeContext runtimeContext, OffsetCommitMode offsetCommitMode, MetricGroup consumerMetricGroup, boolean useMetrics) throws Exception { + AbstractFetcher fetcher = super.createFetcher(sourceContext, assignedPartitionsWithInitialOffsets, watermarksPeriodic, watermarksPunctuated, runtimeContext, offsetCommitMode, consumerMetricGroup, useMetrics); + customerJsonDeserialization.setFetcher(fetcher); + return fetcher; + } +} \ No newline at end of file diff --git a/kafka09/kafka09-source/src/main/java/com/dtstack/flink/sql/source/kafka/KafkaConsumer09.java b/kafka09/kafka09-source/src/main/java/com/dtstack/flink/sql/source/kafka/KafkaConsumer09.java deleted file mode 100644 index 3b76e8c4a..000000000 --- a/kafka09/kafka09-source/src/main/java/com/dtstack/flink/sql/source/kafka/KafkaConsumer09.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.source.kafka; - -import com.dtstack.flink.sql.format.DeserializationMetricWrapper; -import com.dtstack.flink.sql.source.kafka.deserialization.DtKafkaDeserializationSchemaWrapper; -import com.dtstack.flink.sql.source.kafka.deserialization.KafkaDeserializationMetricWrapper; -import com.dtstack.flink.sql.source.kafka.sample.OffsetFetcher; -import com.dtstack.flink.sql.source.kafka.sample.OffsetMap; -import com.dtstack.flink.sql.source.kafka.sample.SampleCalculateHelper; -import org.apache.commons.lang3.StringUtils; -import org.apache.flink.api.common.serialization.DeserializationSchema; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.metrics.MetricGroup; -import org.apache.flink.streaming.api.functions.AssignerWithPeriodicWatermarks; -import org.apache.flink.streaming.api.functions.AssignerWithPunctuatedWatermarks; -import org.apache.flink.streaming.api.functions.source.SourceFunction; -import org.apache.flink.streaming.api.operators.StreamingRuntimeContext; -import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer09; -import org.apache.flink.streaming.connectors.kafka.config.OffsetCommitMode; -import org.apache.flink.streaming.connectors.kafka.internals.AbstractFetcher; -import org.apache.flink.streaming.connectors.kafka.internals.KafkaTopicPartition; -import org.apache.flink.types.Row; -import org.apache.flink.util.SerializedValue; -import org.apache.kafka.clients.consumer.KafkaConsumer; -import org.apache.kafka.common.PartitionInfo; -import org.apache.kafka.common.TopicPartition; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.regex.Pattern; - - -/** - * Reason: - * Date: 2018/10/19 - * Company: www.dtstack.com - * - * @author xuchao - */ -public class KafkaConsumer09 extends FlinkKafkaConsumer09 implements OffsetFetcher { - - private final DeserializationMetricWrapper deserializationMetricWrapper; - - private String topic; - - private final Properties props; - - private final Long sampleSize; - - public KafkaConsumer09( - String topic, - Long sampleSize, - DeserializationMetricWrapper deserializationMetricWrapper, - Properties props) { - super( - Arrays.asList(StringUtils.split(topic, ",")), - new DtKafkaDeserializationSchemaWrapper<>(deserializationMetricWrapper), - props); - this.topic = topic; - this.props = props; - this.sampleSize = sampleSize; - this.deserializationMetricWrapper = deserializationMetricWrapper; - } - - public KafkaConsumer09( - Pattern subscriptionPattern, - Long sampleSize, - DeserializationMetricWrapper deserializationMetricWrapper, - Properties props) { - super( - subscriptionPattern, - new DtKafkaDeserializationSchemaWrapper<>(deserializationMetricWrapper), - props); - this.sampleSize = sampleSize; - this.props = props; - this.deserializationMetricWrapper = deserializationMetricWrapper; - } - - @Override - public void run(SourceFunction.SourceContext sourceContext) throws Exception { - deserializationMetricWrapper.setRuntimeContext(getRuntimeContext()); - deserializationMetricWrapper.initMetric(); - super.run(sourceContext); - } - - @Override - protected AbstractFetcher createFetcher(SourceFunction.SourceContext sourceContext, - Map assignedPartitionsWithInitialOffsets, - SerializedValue> watermarksPeriodic, - SerializedValue> watermarksPunctuated, - StreamingRuntimeContext runtimeContext, - OffsetCommitMode offsetCommitMode, - MetricGroup consumerMetricGroup, - boolean useMetrics) throws Exception { - - final OffsetMap offsetMap = sampleSize > 0 ? seekOffset(props, topic) : new OffsetMap(); - Map rebuild; - - rebuild = - sampleSize > 0 - ? SampleCalculateHelper.rebuildAssignedPartitionsWithInitialOffsets( - offsetMap, sampleSize, assignedPartitionsWithInitialOffsets) - : assignedPartitionsWithInitialOffsets; - - AbstractFetcher fetcher = - super.createFetcher( - sourceContext, - rebuild, - watermarksPeriodic, - watermarksPunctuated, - runtimeContext, - offsetCommitMode, - consumerMetricGroup, - useMetrics); - ((KafkaDeserializationMetricWrapper) deserializationMetricWrapper).setFetcher(fetcher); - ((DtKafkaDeserializationSchemaWrapper) deserializer).setSpecificEndOffsets(offsetMap); - return fetcher; - } - - @Override - public TypeInformation getProducedType() { - DeserializationSchema deserializationSchema = deserializationMetricWrapper.getDeserializationSchema(); - return deserializationSchema.getProducedType(); - } - - @Override - public OffsetMap fetchOffset(KafkaConsumer consumer, String topic) { - OffsetMap offsetMap = new OffsetMap(); - List topicPartitions = new ArrayList<>(); - - List partitionInfos = consumer.partitionsFor(topic); - - partitionInfos.forEach( - item -> topicPartitions.add(new TopicPartition(topic, item.partition()))); - - consumer.seekToEnd(topicPartitions.toArray(new TopicPartition[0])); - topicPartitions.forEach( - item -> - offsetMap.setLatest( - new KafkaTopicPartition(topic, item.partition()), - consumer.position(item))); - - consumer.seekToBeginning(topicPartitions.toArray(new TopicPartition[0])); - topicPartitions.forEach( - item -> - offsetMap.setEarliest( - new KafkaTopicPartition(topic, item.partition()), - consumer.position(item))); - - return offsetMap; - } -} \ No newline at end of file diff --git a/kafka09/kafka09-source/src/main/java/com/dtstack/flink/sql/source/kafka/KafkaConsumer09Factory.java b/kafka09/kafka09-source/src/main/java/com/dtstack/flink/sql/source/kafka/KafkaConsumer09Factory.java deleted file mode 100644 index fd8107c2e..000000000 --- a/kafka09/kafka09-source/src/main/java/com/dtstack/flink/sql/source/kafka/KafkaConsumer09Factory.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.source.kafka; - -import com.dtstack.flink.sql.format.DeserializationMetricWrapper; -import com.dtstack.flink.sql.source.kafka.table.KafkaSourceTableInfo; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumerBase; -import org.apache.flink.types.Row; - -import java.io.Serializable; -import java.util.Properties; -import java.util.regex.Pattern; - -/** - * company: www.dtstack.com - * - * @author: toutian - * create: 2019/12/24 - */ -public class KafkaConsumer09Factory extends AbstractKafkaConsumerFactory { - - @Override - public FlinkKafkaConsumerBase createKafkaTableSource(KafkaSourceTableInfo kafkaSourceTableInfo, TypeInformation typeInformation, Properties props) { - KafkaConsumer09 kafkaSrc; - if (kafkaSourceTableInfo.getTopicIsPattern()) { - DeserializationMetricWrapper deserMetricWrapper = createDeserializationMetricWrapper(kafkaSourceTableInfo, typeInformation, (Calculate & Serializable) (subscriptionState, tp) -> 0L); - kafkaSrc = - new KafkaConsumer09( - Pattern.compile(kafkaSourceTableInfo.getTopic()), - kafkaSourceTableInfo.getSampleSize(), - deserMetricWrapper, - props); - } else { - DeserializationMetricWrapper deserMetricWrapper = createDeserializationMetricWrapper(kafkaSourceTableInfo, typeInformation, (Calculate & Serializable) (subscriptionState, tp) -> 0L); - kafkaSrc = - new KafkaConsumer09( - kafkaSourceTableInfo.getTopic(), - kafkaSourceTableInfo.getSampleSize(), - deserMetricWrapper, - props); - } - return kafkaSrc; - } - -} diff --git a/kafka09/kafka09-source/src/main/java/com/dtstack/flink/sql/source/kafka/KafkaSource.java b/kafka09/kafka09-source/src/main/java/com/dtstack/flink/sql/source/kafka/KafkaSource.java index 3992c180a..8de9ce703 100644 --- a/kafka09/kafka09-source/src/main/java/com/dtstack/flink/sql/source/kafka/KafkaSource.java +++ b/kafka09/kafka09-source/src/main/java/com/dtstack/flink/sql/source/kafka/KafkaSource.java @@ -17,19 +17,30 @@ */ + package com.dtstack.flink.sql.source.kafka; +import com.dtstack.flink.sql.source.IStreamSourceGener; import com.dtstack.flink.sql.source.kafka.table.KafkaSourceTableInfo; -import com.dtstack.flink.sql.table.AbstractSourceTableInfo; +import com.dtstack.flink.sql.table.SourceTableInfo; +import com.dtstack.flink.sql.util.DtStringUtil; +import com.dtstack.flink.sql.util.PluginUtil; +import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; import org.apache.flink.api.common.typeinfo.TypeInformation; +import org.apache.flink.api.java.typeutils.RowTypeInfo; import org.apache.flink.streaming.api.datastream.DataStreamSource; import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer09; +import org.apache.flink.streaming.connectors.kafka.internals.KafkaTopicPartition; import org.apache.flink.table.api.Table; import org.apache.flink.table.api.java.StreamTableEnvironment; import org.apache.flink.types.Row; + +import java.util.HashMap; +import java.util.Map; import java.util.Properties; +import java.util.regex.Pattern; /** * If eventtime field is specified, the default time field rowtime @@ -38,25 +49,78 @@ * @author xuchao */ -public class KafkaSource extends AbstractKafkaSource { +public class KafkaSource implements IStreamSourceGener

{ + + private static final String SOURCE_OPERATOR_NAME_TPL = "${topic}_${table}"; + + /** + * Get kafka data source, you need to provide the data field names, data types + * If you do not specify auto.offset.reset, the default use groupoffset + * @param sourceTableInfo + * @return + */ + @SuppressWarnings("rawtypes") @Override - public Table genStreamSource(AbstractSourceTableInfo sourceTableInfo, StreamExecutionEnvironment env, StreamTableEnvironment tableEnv) { - KafkaSourceTableInfo kafkaSourceTableInfo = (KafkaSourceTableInfo) sourceTableInfo; - String topicName = kafkaSourceTableInfo.getTopic(); + public Table genStreamSource(SourceTableInfo sourceTableInfo, StreamExecutionEnvironment env, StreamTableEnvironment tableEnv) { - Properties kafkaProperties = getKafkaProperties(kafkaSourceTableInfo); - TypeInformation typeInformation = getRowTypeInformation(kafkaSourceTableInfo); - FlinkKafkaConsumer09 kafkaSrc = (FlinkKafkaConsumer09) new KafkaConsumer09Factory().createKafkaTableSource(kafkaSourceTableInfo, typeInformation, kafkaProperties); + KafkaSourceTableInfo kafka09SourceTableInfo = (KafkaSourceTableInfo) sourceTableInfo; + String topicName = kafka09SourceTableInfo.getTopic(); - String sourceOperatorName = generateOperatorName(sourceTableInfo.getName(), topicName); - DataStreamSource kafkaSource = env.addSource(kafkaSrc, sourceOperatorName, typeInformation); + Properties props = new Properties(); + props.setProperty("bootstrap.servers", kafka09SourceTableInfo.getBootstrapServers()); + if (DtStringUtil.isJosn(kafka09SourceTableInfo.getOffsetReset())){ + props.setProperty("auto.offset.reset", "none"); + } else { + props.setProperty("auto.offset.reset", kafka09SourceTableInfo.getOffsetReset()); + } + if (StringUtils.isNotBlank(kafka09SourceTableInfo.getGroupId())){ + props.setProperty("group.id", kafka09SourceTableInfo.getGroupId()); + } + // only required for Kafka 0.8 + //TODO props.setProperty("zookeeper.connect", kafka09SourceTableInfo.) - setParallelism(kafkaSourceTableInfo.getParallelism(), kafkaSource); - setStartPosition(kafkaSourceTableInfo.getOffsetReset(), topicName, kafkaSrc, () -> kafkaSrc.setStartFromLatest()); - String fields = StringUtils.join(kafkaSourceTableInfo.getFields(), ","); + TypeInformation[] types = new TypeInformation[kafka09SourceTableInfo.getFields().length]; + for(int i = 0; i< kafka09SourceTableInfo.getFieldClasses().length; i++){ + types[i] = TypeInformation.of(kafka09SourceTableInfo.getFieldClasses()[i]); + } - return tableEnv.fromDataStream(kafkaSource, fields); - } + TypeInformation typeInformation = new RowTypeInfo(types, kafka09SourceTableInfo.getFields()); + FlinkKafkaConsumer09 kafkaSrc; + if (BooleanUtils.isTrue(kafka09SourceTableInfo.getTopicIsPattern())) { + kafkaSrc = new CustomerKafka09Consumer(Pattern.compile(topicName), + new CustomerJsonDeserialization(typeInformation, kafka09SourceTableInfo.getPhysicalFields(), kafka09SourceTableInfo.getFieldExtraInfoList()), props); + } else { + kafkaSrc = new CustomerKafka09Consumer(topicName, + new CustomerJsonDeserialization(typeInformation, kafka09SourceTableInfo.getPhysicalFields(), kafka09SourceTableInfo.getFieldExtraInfoList()), props); + } + + //earliest,latest + if("earliest".equalsIgnoreCase(kafka09SourceTableInfo.getOffsetReset())){ + kafkaSrc.setStartFromEarliest(); + }else if(DtStringUtil.isJosn(kafka09SourceTableInfo.getOffsetReset())){// {"0":12312,"1":12321,"2":12312} + try { + Properties properties = PluginUtil.jsonStrToObject(kafka09SourceTableInfo.getOffsetReset(), Properties.class); + Map offsetMap = PluginUtil.ObjectToMap(properties); + Map specificStartupOffsets = new HashMap<>(); + for(Map.Entry entry:offsetMap.entrySet()){ + specificStartupOffsets.put(new KafkaTopicPartition(topicName,Integer.valueOf(entry.getKey())),Long.valueOf(entry.getValue().toString())); + } + kafkaSrc.setStartFromSpecificOffsets(specificStartupOffsets); + } catch (Exception e) { + throw new RuntimeException("not support offsetReset type:" + kafka09SourceTableInfo.getOffsetReset()); + } + }else { + kafkaSrc.setStartFromLatest(); + } + String fields = StringUtils.join(kafka09SourceTableInfo.getFields(), ","); + String sourceOperatorName = SOURCE_OPERATOR_NAME_TPL.replace("${topic}", topicName).replace("${table}", sourceTableInfo.getName()); + DataStreamSource kafkaSource = env.addSource(kafkaSrc, sourceOperatorName, typeInformation); + Integer parallelism = kafka09SourceTableInfo.getParallelism(); + if (parallelism != null) { + kafkaSource.setParallelism(parallelism); + } + return tableEnv.fromDataStream(kafkaSource, fields); + } } \ No newline at end of file diff --git a/kafka09/kafka09-source/src/main/java/com/dtstack/flink/sql/source/kafka/metric/KafkaTopicPartitionLagMetric.java b/kafka09/kafka09-source/src/main/java/com/dtstack/flink/sql/source/kafka/metric/KafkaTopicPartitionLagMetric.java new file mode 100644 index 000000000..2519b4ad6 --- /dev/null +++ b/kafka09/kafka09-source/src/main/java/com/dtstack/flink/sql/source/kafka/metric/KafkaTopicPartitionLagMetric.java @@ -0,0 +1,30 @@ +package com.dtstack.flink.sql.source.kafka.metric; + +import org.apache.flink.metrics.Gauge; +import org.apache.kafka.clients.consumer.internals.SubscriptionState; +import org.apache.kafka.common.TopicPartition; + +/** + * Reason: + * Date: 2018/10/24 + * Company: www.dtstack.com + * @author xuchao + */ + +public class KafkaTopicPartitionLagMetric implements Gauge { + + private SubscriptionState subscriptionState; + + private TopicPartition tp; + + public KafkaTopicPartitionLagMetric(SubscriptionState subscriptionState, TopicPartition tp){ + this.subscriptionState = subscriptionState; + this.tp = tp; + } + + @Override + public Long getValue() { + //return subscriptionState.partitionLag(tp); + return 0L; + } +} diff --git a/kafka09/kafka09-source/src/main/java/com/dtstack/flink/sql/source/kafka/table/KafkaSourceParser.java b/kafka09/kafka09-source/src/main/java/com/dtstack/flink/sql/source/kafka/table/KafkaSourceParser.java new file mode 100644 index 000000000..106d2aeb9 --- /dev/null +++ b/kafka09/kafka09-source/src/main/java/com/dtstack/flink/sql/source/kafka/table/KafkaSourceParser.java @@ -0,0 +1,96 @@ +/* + * 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 com.dtstack.flink.sql.source.kafka.table; + +import com.dtstack.flink.sql.table.AbsSourceParser; +import com.dtstack.flink.sql.table.TableInfo; +import com.dtstack.flink.sql.util.ClassUtil; +import com.dtstack.flink.sql.util.MathUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Reason: + * Date: 2018/7/4 + * Company: www.dtstack.com + * @author xuchao + */ + +public class KafkaSourceParser extends AbsSourceParser { + + private static final Logger LOG = LoggerFactory.getLogger(KafkaSourceParser.class); + + private static final String KAFKA_NEST_FIELD_KEY = "nestFieldKey"; + + private static Pattern kafkaNestFieldKeyPattern = Pattern.compile("(?i)((@*\\S+\\.)*\\S+)\\s+(\\w+)\\s+AS\\s+(\\w+)(\\s+NOT\\s+NULL)?$"); + + static { + keyPatternMap.put(KAFKA_NEST_FIELD_KEY, kafkaNestFieldKeyPattern); + + keyHandlerMap.put(KAFKA_NEST_FIELD_KEY, KafkaSourceParser::dealNestField); + } + + static void dealNestField(Matcher matcher, TableInfo tableInfo) { + String physicalField = matcher.group(1); + String fieldType = matcher.group(3); + String mappingField = matcher.group(4); + Class fieldClass= ClassUtil.stringConvertClass(fieldType); + boolean notNull = matcher.group(5) != null; + TableInfo.FieldExtraInfo fieldExtraInfo = new TableInfo.FieldExtraInfo(); + fieldExtraInfo.setNotNull(notNull); + + tableInfo.addPhysicalMappings(mappingField, physicalField); + tableInfo.addField(mappingField); + tableInfo.addFieldClass(fieldClass); + tableInfo.addFieldType(fieldType); + tableInfo.addFieldExtraInfo(fieldExtraInfo); + if(LOG.isInfoEnabled()){ + LOG.info(physicalField + "--->" + mappingField + " Class: " + fieldClass.toString()); + } + } + + @Override + public TableInfo getTableInfo(String tableName, String fieldsInfo, Map props) throws Exception { + + KafkaSourceTableInfo kafka09SourceTableInfo = new KafkaSourceTableInfo(); + kafka09SourceTableInfo.setName(tableName); + parseFieldsInfo(fieldsInfo, kafka09SourceTableInfo); + + kafka09SourceTableInfo.setParallelism(MathUtil.getIntegerVal(props.get(KafkaSourceTableInfo.PARALLELISM_KEY.toLowerCase()))); + String bootstrapServer = MathUtil.getString(props.get(KafkaSourceTableInfo.BOOTSTRAPSERVERS_KEY.toLowerCase())); + if (bootstrapServer == null || bootstrapServer.trim().equals("")){ + throw new Exception("BootstrapServers can not be empty!"); + } else { + kafka09SourceTableInfo.setBootstrapServers(bootstrapServer); + } + kafka09SourceTableInfo.setGroupId(MathUtil.getString(props.get(KafkaSourceTableInfo.GROUPID_KEY.toLowerCase()))); + kafka09SourceTableInfo.setTopic(MathUtil.getString(props.get(KafkaSourceTableInfo.TOPIC_KEY.toLowerCase()))); + kafka09SourceTableInfo.setOffsetReset(MathUtil.getString(props.get(KafkaSourceTableInfo.OFFSETRESET_KEY.toLowerCase()))); + kafka09SourceTableInfo.setTopicIsPattern(MathUtil.getBoolean(props.get(KafkaSourceTableInfo.TOPICISPATTERN_KEY.toLowerCase()))); + kafka09SourceTableInfo.setTimeZone(MathUtil.getString(props.get(KafkaSourceTableInfo.TIME_ZONE_KEY.toLowerCase()))); + kafka09SourceTableInfo.check(); + return kafka09SourceTableInfo; + } +} diff --git a/kafka09/kafka09-source/src/main/java/com/dtstack/flink/sql/source/kafka/table/KafkaSourceTableInfo.java b/kafka09/kafka09-source/src/main/java/com/dtstack/flink/sql/source/kafka/table/KafkaSourceTableInfo.java new file mode 100644 index 000000000..e6098fb3c --- /dev/null +++ b/kafka09/kafka09-source/src/main/java/com/dtstack/flink/sql/source/kafka/table/KafkaSourceTableInfo.java @@ -0,0 +1,132 @@ +/* + * 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 com.dtstack.flink.sql.source.kafka.table; + +import com.dtstack.flink.sql.table.SourceTableInfo; +import com.google.common.base.Preconditions; + +/** + * Reason: + * Date: 2018/6/22 + * Company: www.dtstack.com + * + * @author xuchao + */ + +public class KafkaSourceTableInfo extends SourceTableInfo { + + //version + private static final String CURR_TYPE = "kafka09"; + + public static final String BOOTSTRAPSERVERS_KEY = "bootstrapServers"; + + public static final String TOPIC_KEY = "topic"; + + public static final String GROUPID_KEY = "groupId"; + + public static final String OFFSETRESET_KEY = "offsetReset"; + + public static final String TOPICISPATTERN_KEY = "topicIsPattern"; + + private String bootstrapServers; + + private String topic; + + private String groupId; + + //latest, earliest + private String offsetReset = "latest"; + + private String offset; + + private Boolean topicIsPattern = false; + + public Boolean getTopicIsPattern() { + return topicIsPattern; + } + + public void setTopicIsPattern(Boolean topicIsPattern) { + if (topicIsPattern == null) return; + + this.topicIsPattern = topicIsPattern; + } + + public KafkaSourceTableInfo() { + super.setType(CURR_TYPE); + } + + + public String getBootstrapServers() { + return bootstrapServers; + } + + public void setBootstrapServers(String bootstrapServers) { + this.bootstrapServers = bootstrapServers; + } + + public String getTopic() { + return topic; + } + + public void setTopic(String topic) { + this.topic = topic; + } + + public String getGroupId() { + return groupId; + } + + public void setGroupId(String groupId) { + this.groupId = groupId; + } + + public String getOffsetReset() { + return offsetReset; + } + + public void setOffsetReset(String offsetReset) { + if (offsetReset == null) { + return; + } + + this.offsetReset = offsetReset; + } + + public String getOffset() { + return offset; + } + + public void setOffset(String offset) { + this.offset = offset; + } + + @Override + public boolean check() { + Preconditions.checkNotNull(bootstrapServers, "kafka of bootstrapServers is required"); + Preconditions.checkNotNull(topic, "kafka of topic is required"); + return false; + } + + @Override + public String getType() { +// return super.getType() + SOURCE_SUFFIX; + return super.getType(); + } +} diff --git a/kafka09/kafka09-source/src/test/java/com/dtstack/flink/sql/source/kafka/KafkaSourceTest.java b/kafka09/kafka09-source/src/test/java/com/dtstack/flink/sql/source/kafka/KafkaSourceTest.java deleted file mode 100644 index 396b69550..000000000 --- a/kafka09/kafka09-source/src/test/java/com/dtstack/flink/sql/source/kafka/KafkaSourceTest.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.dtstack.flink.sql.source.kafka; - -import com.dtstack.flink.sql.source.kafka.table.KafkaSourceTableInfo; -import com.google.common.collect.Sets; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.streaming.api.datastream.DataStreamSource; -import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; -import org.apache.flink.streaming.api.functions.source.SourceFunction; -import org.apache.flink.table.api.java.StreamTableEnvironment; -import org.junit.Test; -import org.mockito.ArgumentMatcher; - -import static org.mockito.Mockito.*; - -public class KafkaSourceTest { - - @Test - public void mockGenStreamSource(){ - KafkaSourceTableInfo kafkaSourceTableInfo = mock(KafkaSourceTableInfo.class); - when(kafkaSourceTableInfo.getTopic()).thenReturn("topic"); - when(kafkaSourceTableInfo.getGroupId()).thenReturn("groupId"); - when(kafkaSourceTableInfo.getBootstrapServers()).thenReturn("localhost"); - when(kafkaSourceTableInfo.getKafkaParamKeys()).thenReturn(Sets.newHashSet("aa")); - when(kafkaSourceTableInfo.getKafkaParam("aa")).thenReturn("xx"); - when(kafkaSourceTableInfo.getFields()).thenReturn(new String[]{"aa"}); - when(kafkaSourceTableInfo.getFieldClasses()).thenReturn(new Class[]{String.class}); - when(kafkaSourceTableInfo.getParallelism()).thenReturn(1); - when(kafkaSourceTableInfo.getName()).thenReturn("roc"); - when(kafkaSourceTableInfo.getOffsetReset()).thenReturn("1"); - when(kafkaSourceTableInfo.getSourceDataType()).thenReturn("json"); - - DataStreamSource dataStreamSource = mock(DataStreamSource.class); - - StreamExecutionEnvironment env = mock(StreamExecutionEnvironment.class); - when(env.addSource(argThat(new ArgumentMatcher>() { - @Override - public boolean matches(SourceFunction sourceFunction) { - return true; - } - }), argThat(new ArgumentMatcher() { - @Override - public boolean matches(String s) { - return true; - } - }), argThat(new ArgumentMatcher() { - @Override - public boolean matches(TypeInformation typeInformation) { - return true; - } - }))).thenReturn(dataStreamSource); - - StreamTableEnvironment tableEnv = mock(StreamTableEnvironment.class); - - KafkaSource kafkaSource = new KafkaSource(); - KafkaSource kafkaSourceSpy = spy(kafkaSource); -// kafkaSourceSpy.genStreamSource(kafkaSourceTableInfo, env, tableEnv); - } - -} - diff --git a/hbase/hbase-sink/src/main/java/com/dtstack/flink/sql/sink/hbase/enums/EReplaceOpType.java b/kafka09/kafka09-source/src/test/java/com/dtstack/flinkx/AppTest.java similarity index 58% rename from hbase/hbase-sink/src/main/java/com/dtstack/flink/sql/sink/hbase/enums/EReplaceOpType.java rename to kafka09/kafka09-source/src/test/java/com/dtstack/flinkx/AppTest.java index 8621f352d..33a0233ac 100644 --- a/hbase/hbase-sink/src/main/java/com/dtstack/flink/sql/sink/hbase/enums/EReplaceOpType.java +++ b/kafka09/kafka09-source/src/test/java/com/dtstack/flinkx/AppTest.java @@ -18,22 +18,41 @@ -package com.dtstack.flink.sql.sink.hbase.enums; +package com.dtstack.flinkx; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; /** - * Reason: - * Date: 2018/8/23 - * Company: www.dtstack.com - * @author xuchao + * Unit test for simple App. */ +public class AppTest + extends TestCase +{ + /** + * Create the test case + * + * @param testName name of the test case + */ + public AppTest( String testName ) + { + super( testName ); + } -public enum EReplaceOpType { /** - * 没有func + * @return the suite of tests being tested */ - NO_FUNC, + public static Test suite() + { + return new TestSuite( AppTest.class ); + } + /** - * md5 func + * Rigourous Test :-) */ - MD5_FUNC; + public void testApp() + { + assertTrue( true ); + } } diff --git a/kafka09/pom.xml b/kafka09/pom.xml index 939c2f6fd..86613de70 100644 --- a/kafka09/pom.xml +++ b/kafka09/pom.xml @@ -26,6 +26,13 @@ ${flink.version} + + junit + junit + 3.8.1 + test + + com.dtstack.flink sql.core diff --git a/kafka10/kafka10-sink/pom.xml b/kafka10/kafka10-sink/pom.xml index e32033d68..9893d386f 100644 --- a/kafka10/kafka10-sink/pom.xml +++ b/kafka10/kafka10-sink/pom.xml @@ -18,9 +18,9 @@ - sql.sink.kafka-base - com.dtstack.flink - 1.0-SNAPSHOT + org.apache.flink + flink-json + ${flink.version} @@ -37,7 +37,6 @@ shade - false org.slf4j @@ -71,14 +70,14 @@ - + - + diff --git a/kafka10/kafka10-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerCsvSerialization.java b/kafka10/kafka10-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerCsvSerialization.java new file mode 100644 index 000000000..e39a2d3b6 --- /dev/null +++ b/kafka10/kafka10-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerCsvSerialization.java @@ -0,0 +1,122 @@ +package com.dtstack.flink.sql.sink.kafka; + +import org.apache.commons.lang3.StringEscapeUtils; +import org.apache.flink.api.common.ExecutionConfig; +import org.apache.flink.api.common.typeinfo.TypeInformation; +import org.apache.flink.api.common.typeutils.TypeSerializer; +import org.apache.flink.api.common.typeutils.TypeSerializerSnapshot; +import org.apache.flink.api.common.typeutils.base.TypeSerializerSingleton; +import org.apache.flink.core.memory.DataInputView; +import org.apache.flink.core.memory.DataOutputView; +import org.apache.flink.types.Row; +import org.apache.flink.types.StringValue; + +import java.io.IOException; + +import static org.apache.flink.api.java.typeutils.runtime.NullMaskUtils.writeNullMask; +/** + * + * Date: 2018/12/18 + * Company: www.dtstack.com + * + * @author DocLi + * + * @modifyer maqi + * + */ +public final class CustomerCsvSerialization extends TypeSerializerSingleton { + + private static final long serialVersionUID = 1L; + + private String fieldDelimiter = "\u0001"; + private TypeInformation[] fieldTypes; + private TypeSerializer[] fieldSerializers; + private static final Row EMPTY = null; + + public CustomerCsvSerialization(String fielddelimiter,TypeInformation[] fieldTypes) { + this.fieldDelimiter = fielddelimiter; + this.fieldTypes = fieldTypes; + this.fieldSerializers = (TypeSerializer[])createSerializer(new ExecutionConfig()); + } + + public TypeSerializer[] createSerializer(ExecutionConfig config) { + int len = fieldTypes.length; + TypeSerializer[] fieldSerializers = new TypeSerializer[len]; + for (int i = 0; i < len; i++) { + fieldSerializers[i] = fieldTypes[i].createSerializer(config); + } + return fieldSerializers; + } + + @Override + public boolean isImmutableType() { + return true; + } + + @Override + public Row createInstance() { + return EMPTY; + } + + @Override + public Row copy(Row from) { + return null; + } + + @Override + public Row copy(Row from, Row reuse) { + return null; + } + + @Override + public int getLength() { + return -1; + } + + @Override + public void serialize(Row record, DataOutputView target) throws IOException { + int len = fieldSerializers.length; + + if (record.getArity() != len) { + throw new RuntimeException("Row arity of from does not match serializers."); + } + + // write a null mask + writeNullMask(len, record, target); + + // serialize non-null fields + StringBuffer stringBuffer = new StringBuffer(); + for (int i = 0; i < len; i++) { + Object o = record.getField(i); + if (o != null) { + //fieldSerializers[i].serialize(o, target); + stringBuffer.append(o); + } + if(i != len-1){ + stringBuffer.append(StringEscapeUtils.unescapeJava(fieldDelimiter)); + //fieldSerializers[i].serialize(fieldDelimiter, target); + } + } + StringValue.writeString(stringBuffer.toString(), target); + } + + @Override + public Row deserialize(DataInputView source) throws IOException { + return null; + } + + @Override + public Row deserialize(Row reuse, DataInputView source) throws IOException { + return null; + } + + @Override + public void copy(DataInputView source, DataOutputView target) throws IOException { + StringValue.copyString(source, target); + } + + @Override + public TypeSerializerSnapshot snapshotConfiguration() { + return null; + } +} diff --git a/kafka10/kafka10-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerFlinkKafkaProducer010.java b/kafka10/kafka10-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerFlinkKafkaProducer010.java new file mode 100644 index 000000000..2f11c355d --- /dev/null +++ b/kafka10/kafka10-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerFlinkKafkaProducer010.java @@ -0,0 +1,61 @@ +/** + * 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 com.dtstack.flink.sql.sink.kafka; + +import com.dtstack.flink.sql.metric.MetricConstant; +import org.apache.flink.api.common.functions.RuntimeContext; +import org.apache.flink.api.common.serialization.SerializationSchema; +import org.apache.flink.configuration.Configuration; +import org.apache.flink.metrics.Counter; +import org.apache.flink.metrics.MeterView; +import org.apache.flink.streaming.connectors.kafka.FlinkKafkaProducer010; + +import java.util.Map; +import java.util.Properties; + +/** + * Reason: + * Date: 2019/4/24 + * Company: www.dtstack.com + * + * @author maqi + */ +public class CustomerFlinkKafkaProducer010 extends FlinkKafkaProducer010 { + + CustomerJsonRowSerializationSchema schema; + + public CustomerFlinkKafkaProducer010(String topicId, SerializationSchema serializationSchema, Properties producerConfig) { + super(topicId, serializationSchema, producerConfig); + this.schema = (CustomerJsonRowSerializationSchema) serializationSchema; + } + + @Override + public void open(Configuration configuration) { + producer = getKafkaProducer(this.producerConfig); + + RuntimeContext ctx = getRuntimeContext(); + Counter counter = ctx.getMetricGroup().counter(MetricConstant.DT_NUM_RECORDS_OUT); + MeterView meter = ctx.getMetricGroup().meter(MetricConstant.DT_NUM_RECORDS_OUT_RATE, new MeterView(counter, 20)); + + schema.setCounter(counter); + + super.open(configuration); + } + + +} diff --git a/kafka10/kafka10-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerJsonRowSerializationSchema.java b/kafka10/kafka10-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerJsonRowSerializationSchema.java new file mode 100644 index 000000000..8033c851e --- /dev/null +++ b/kafka10/kafka10-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerJsonRowSerializationSchema.java @@ -0,0 +1,219 @@ +/* + * 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 com.dtstack.flink.sql.sink.kafka; + +import org.apache.flink.api.common.serialization.SerializationSchema; +import org.apache.flink.api.common.typeinfo.BasicArrayTypeInfo; +import org.apache.flink.api.common.typeinfo.PrimitiveArrayTypeInfo; +import org.apache.flink.api.common.typeinfo.TypeInformation; +import org.apache.flink.api.common.typeinfo.Types; +import org.apache.flink.api.java.typeutils.ObjectArrayTypeInfo; +import org.apache.flink.api.java.typeutils.RowTypeInfo; +import org.apache.flink.formats.json.JsonRowDeserializationSchema; +import org.apache.flink.formats.json.JsonRowSchemaConverter; +import org.apache.flink.metrics.Counter; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ContainerNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.apache.flink.types.Row; +import org.apache.flink.util.Preconditions; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.sql.Time; +import java.sql.Timestamp; +import java.text.SimpleDateFormat; + +/** + * Serialization schema that serializes an object of Flink types into a JSON bytes. + * + *

Serializes the input Flink object into a JSON string and + * converts it into byte[]. + * + *

Result byte[] messages can be deserialized using {@link JsonRowDeserializationSchema}. + */ +public class CustomerJsonRowSerializationSchema implements SerializationSchema { + + private static final long serialVersionUID = -2885556750743978636L; + + /** Type information describing the input type. */ + private final TypeInformation typeInfo; + + /** Object mapper that is used to create output JSON objects. */ + private final ObjectMapper mapper = new ObjectMapper(); + + /** Formatter for RFC 3339-compliant string representation of a time value (with UTC timezone, without milliseconds). */ + private SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss'Z'"); + + /** Formatter for RFC 3339-compliant string representation of a time value (with UTC timezone). */ + private SimpleDateFormat timeFormatWithMillis = new SimpleDateFormat("HH:mm:ss.SSS'Z'"); + + /** Formatter for RFC 3339-compliant string representation of a timestamp value (with UTC timezone). */ + private SimpleDateFormat timestampFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); + + /** Reusable object node. */ + private transient ObjectNode node; + + private Counter counter; + + /** + * Creates a JSON serialization schema for the given type information. + * + * @param typeInfo The field names of {@link Row} are used to map to JSON properties. + */ + public CustomerJsonRowSerializationSchema(TypeInformation typeInfo) { + Preconditions.checkNotNull(typeInfo, "Type information"); + this.typeInfo = typeInfo; + } + + /** + * Creates a JSON serialization schema for the given JSON schema. + * + * @param jsonSchema JSON schema describing the result type + * + * @see http://json-schema.org/ + */ + public CustomerJsonRowSerializationSchema(String jsonSchema) { + this(JsonRowSchemaConverter.convert(jsonSchema)); + } + + @Override + public byte[] serialize(Row row) { + if (node == null) { + node = mapper.createObjectNode(); + } + + try { + convertRow(node, (RowTypeInfo) typeInfo, row); + counter.inc(); + return mapper.writeValueAsBytes(node); + } catch (Throwable t) { + throw new RuntimeException("Could not serialize row '" + row + "'. " + + "Make sure that the schema matches the input.", t); + } + } + + // -------------------------------------------------------------------------------------------- + + private ObjectNode convertRow(ObjectNode reuse, RowTypeInfo info, Row row) { + if (reuse == null) { + reuse = mapper.createObjectNode(); + } + final String[] fieldNames = info.getFieldNames(); + final TypeInformation[] fieldTypes = info.getFieldTypes(); + + // validate the row + if (row.getArity() != fieldNames.length) { + throw new IllegalStateException(String.format( + "Number of elements in the row '%s' is different from number of field names: %d", row, fieldNames.length)); + } + + for (int i = 0; i < fieldNames.length; i++) { + final String name = fieldNames[i]; + + final JsonNode fieldConverted = convert(reuse, reuse.get(name), fieldTypes[i], row.getField(i)); + reuse.set(name, fieldConverted); + } + + return reuse; + } + + private JsonNode convert(ContainerNode container, JsonNode reuse, TypeInformation info, Object object) { + if (info == Types.VOID || object == null) { + return container.nullNode(); + } else if (info == Types.BOOLEAN) { + return container.booleanNode((Boolean) object); + } else if (info == Types.STRING) { + return container.textNode((String) object); + } else if (info == Types.BIG_DEC) { + // convert decimal if necessary + if (object instanceof BigDecimal) { + return container.numberNode((BigDecimal) object); + } + return container.numberNode(BigDecimal.valueOf(((Number) object).doubleValue())); + } else if (info == Types.BIG_INT) { + // convert integer if necessary + if (object instanceof BigInteger) { + return container.numberNode((BigInteger) object); + } + return container.numberNode(BigInteger.valueOf(((Number) object).longValue())); + } else if (info == Types.SQL_DATE) { + return container.textNode(object.toString()); + } else if (info == Types.SQL_TIME) { + final Time time = (Time) object; + // strip milliseconds if possible + if (time.getTime() % 1000 > 0) { + return container.textNode(timeFormatWithMillis.format(time)); + } + return container.textNode(timeFormat.format(time)); + } else if (info == Types.SQL_TIMESTAMP) { + return container.textNode(timestampFormat.format((Timestamp) object)); + } else if (info instanceof RowTypeInfo) { + if (reuse != null && reuse instanceof ObjectNode) { + return convertRow((ObjectNode) reuse, (RowTypeInfo) info, (Row) object); + } else { + return convertRow(null, (RowTypeInfo) info, (Row) object); + } + } else if (info instanceof ObjectArrayTypeInfo) { + if (reuse != null && reuse instanceof ArrayNode) { + return convertObjectArray((ArrayNode) reuse, ((ObjectArrayTypeInfo) info).getComponentInfo(), (Object[]) object); + } else { + return convertObjectArray(null, ((ObjectArrayTypeInfo) info).getComponentInfo(), (Object[]) object); + } + } else if (info instanceof BasicArrayTypeInfo) { + if (reuse != null && reuse instanceof ArrayNode) { + return convertObjectArray((ArrayNode) reuse, ((BasicArrayTypeInfo) info).getComponentInfo(), (Object[]) object); + } else { + return convertObjectArray(null, ((BasicArrayTypeInfo) info).getComponentInfo(), (Object[]) object); + } + } else if (info instanceof PrimitiveArrayTypeInfo && ((PrimitiveArrayTypeInfo) info).getComponentType() == Types.BYTE) { + return container.binaryNode((byte[]) object); + } else { + // for types that were specified without JSON schema + // e.g. POJOs + try { + return mapper.valueToTree(object); + } catch (IllegalArgumentException e) { + throw new IllegalStateException("Unsupported type information '" + info + "' for object: " + object, e); + } + } + } + + private ArrayNode convertObjectArray(ArrayNode reuse, TypeInformation info, Object[] array) { + if (reuse == null) { + reuse = mapper.createArrayNode(); + } else { + reuse.removeAll(); + } + + for (Object object : array) { + reuse.add(convert(reuse, null, info, object)); + } + return reuse; + } + + public Counter getCounter() { + return counter; + } + + public void setCounter(Counter counter) { + this.counter = counter; + } +} diff --git a/kafka10/kafka10-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerKafka10JsonTableSink.java b/kafka10/kafka10-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerKafka10JsonTableSink.java new file mode 100644 index 000000000..d3edc2d86 --- /dev/null +++ b/kafka10/kafka10-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerKafka10JsonTableSink.java @@ -0,0 +1,74 @@ +/** + * 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 com.dtstack.flink.sql.sink.kafka; + +import org.apache.flink.api.common.serialization.SerializationSchema; +import org.apache.flink.streaming.api.datastream.DataStream; +import org.apache.flink.streaming.api.functions.sink.SinkFunction; +import org.apache.flink.streaming.connectors.kafka.FlinkKafkaProducerBase; +import org.apache.flink.streaming.connectors.kafka.Kafka010TableSink; +import org.apache.flink.streaming.connectors.kafka.partitioner.FlinkKafkaPartitioner; +import org.apache.flink.table.api.TableSchema; +import org.apache.flink.table.utils.TableConnectorUtils; +import org.apache.flink.types.Row; + +import java.util.Optional; +import java.util.Properties; + +/** + * Reason: add schema info + * Date: 2019/4/8 + * Company: www.dtstack.com + * + * @author maqi + */ +public class CustomerKafka10JsonTableSink extends Kafka010TableSink { + + + protected SerializationSchema schema; + + public CustomerKafka10JsonTableSink(TableSchema schema, + String topic, + Properties properties, + Optional> partitioner, + SerializationSchema serializationSchema) { + super(schema, topic, properties, partitioner, serializationSchema); + this.schema = serializationSchema; + } + + + + @Override + protected FlinkKafkaProducerBase createKafkaProducer( + String topic, + Properties properties, + SerializationSchema serializationSchema, + Optional> partitioner) { + return new CustomerFlinkKafkaProducer010(topic, serializationSchema, properties); + } + + + @Override + public void emitDataStream(DataStream dataStream) { + SinkFunction kafkaProducer = createKafkaProducer(topic, properties, schema, partitioner); + // always enable flush on checkpoint to achieve at-least-once if query runs with checkpointing enabled. + //kafkaProducer.setFlushOnCheckpoint(true); + dataStream.addSink(kafkaProducer).name(TableConnectorUtils.generateRuntimeName(this.getClass(), getFieldNames())); + + } +} diff --git a/kafka10/kafka10-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/KafkaProducer010.java b/kafka10/kafka10-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/KafkaProducer010.java deleted file mode 100644 index 2b6319cd3..000000000 --- a/kafka10/kafka10-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/KafkaProducer010.java +++ /dev/null @@ -1,65 +0,0 @@ -/** - * 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 com.dtstack.flink.sql.sink.kafka; - -import com.dtstack.flink.sql.format.SerializationMetricWrapper; -import com.dtstack.flink.sql.sink.kafka.serialization.CustomerKeyedSerializationSchema; -import org.apache.flink.api.common.functions.RuntimeContext; -import org.apache.flink.api.common.serialization.SerializationSchema; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.configuration.Configuration; -import org.apache.flink.streaming.connectors.kafka.FlinkKafkaProducer010; -import org.apache.flink.streaming.connectors.kafka.partitioner.FlinkKafkaPartitioner; -import org.apache.flink.types.Row; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Optional; -import java.util.Properties; - -/** - * Reason: - * Date: 2019/4/24 - * Company: www.dtstack.com - * - * @author maqi - */ -public class KafkaProducer010 extends FlinkKafkaProducer010> { - - private static final Logger LOG = LoggerFactory.getLogger(KafkaProducer010.class); - - private static final long serialVersionUID = 1L; - - private SerializationMetricWrapper serializationMetricWrapper; - - public KafkaProducer010(String topicId, SerializationSchema> serializationSchema, Properties producerConfig, - Optional>> customPartitioner, String[] partitionKeys) { - super(topicId, new CustomerKeyedSerializationSchema((SerializationMetricWrapper)serializationSchema, partitionKeys), producerConfig, customPartitioner.get()); - this.serializationMetricWrapper = (SerializationMetricWrapper) serializationSchema; - } - - @Override - public void open(Configuration configuration) { - LOG.info("----open KafkaProducer010 --"); - RuntimeContext runtimeContext = getRuntimeContext(); - serializationMetricWrapper.setRuntimeContext(runtimeContext); - serializationMetricWrapper.initMetric(); - super.open(configuration); - } - -} \ No newline at end of file diff --git a/kafka10/kafka10-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/KafkaProducer010Factory.java b/kafka10/kafka10-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/KafkaProducer010Factory.java deleted file mode 100644 index 1e904b1e7..000000000 --- a/kafka10/kafka10-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/KafkaProducer010Factory.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.kafka; - -import com.dtstack.flink.sql.sink.kafka.table.KafkaSinkTableInfo; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.streaming.api.functions.sink.RichSinkFunction; -import org.apache.flink.streaming.connectors.kafka.partitioner.FlinkKafkaPartitioner; -import org.apache.flink.types.Row; - -import java.util.Optional; -import java.util.Properties; - -/** - * company: www.dtstack.com - * - * @author: toutian - * create: 2019/12/24 - */ -public class KafkaProducer010Factory extends AbstractKafkaProducerFactory { - - @Override - public RichSinkFunction> createKafkaProducer(KafkaSinkTableInfo kafkaSinkTableInfo, TypeInformation> typeInformation, - Properties properties, Optional>> partitioner, String[] partitionKeys) { - return new KafkaProducer010(kafkaSinkTableInfo.getTopic(), createSerializationMetricWrapper(kafkaSinkTableInfo, typeInformation), properties, partitioner, partitionKeys); - } -} diff --git a/kafka10/kafka10-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/KafkaSink.java b/kafka10/kafka10-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/KafkaSink.java index 2a2849034..8c757ce4a 100644 --- a/kafka10/kafka10-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/KafkaSink.java +++ b/kafka10/kafka10-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/KafkaSink.java @@ -18,12 +18,25 @@ package com.dtstack.flink.sql.sink.kafka; +import com.dtstack.flink.sql.sink.IStreamSinkGener; import com.dtstack.flink.sql.sink.kafka.table.KafkaSinkTableInfo; -import com.dtstack.flink.sql.table.AbstractTargetTableInfo; +import com.dtstack.flink.sql.table.TargetTableInfo; +import org.apache.flink.api.common.serialization.SerializationSchema; +import org.apache.flink.api.common.typeinfo.TypeInformation; +import org.apache.flink.api.java.tuple.Tuple2; +import org.apache.flink.api.java.typeutils.RowTypeInfo; +import org.apache.flink.api.java.typeutils.TupleTypeInfo; +import org.apache.flink.streaming.api.datastream.DataStream; +import org.apache.flink.streaming.connectors.kafka.KafkaTableSinkBase; +import org.apache.flink.streaming.connectors.kafka.partitioner.FlinkFixedPartitioner; +import org.apache.flink.streaming.connectors.kafka.partitioner.FlinkKafkaPartitioner; +import org.apache.flink.table.api.TableSchema; +import org.apache.flink.table.sinks.RetractStreamTableSink; +import org.apache.flink.table.sinks.TableSink; +import org.apache.flink.types.Row; import java.util.Optional; import java.util.Properties; - /** * * Date: 2018/12/18 @@ -34,24 +47,105 @@ * @modifyer maqi * */ -public class KafkaSink extends AbstractKafkaSink { +public class KafkaSink implements RetractStreamTableSink, IStreamSinkGener { + + + protected String[] fieldNames; + + protected TypeInformation[] fieldTypes; + + protected String topic; + + protected Properties properties; + + protected int parallelism; + + /** Serialization schema for encoding records to Kafka. */ + protected SerializationSchema serializationSchema; + + /** The schema of the table. */ + private TableSchema schema; + + /** Partitioner to select Kafka partition for each item. */ + protected Optional> partitioner; @Override - public KafkaSink genStreamSink(AbstractTargetTableInfo targetTableInfo) { + public KafkaSink genStreamSink(TargetTableInfo targetTableInfo) { KafkaSinkTableInfo kafka10SinkTableInfo = (KafkaSinkTableInfo) targetTableInfo; - - Properties kafkaProperties = getKafkaProperties(kafka10SinkTableInfo); - this.tableName = kafka10SinkTableInfo.getName(); - this.updateMode = kafka10SinkTableInfo.getUpdateMode(); this.topic = kafka10SinkTableInfo.getTopic(); - this.partitioner = Optional.of(new CustomerFlinkPartition<>()); - this.partitionKeys = getPartitionKeys(kafka10SinkTableInfo); + + properties = new Properties(); + properties.setProperty("bootstrap.servers", kafka10SinkTableInfo.getBootstrapServers()); + + for (String key : kafka10SinkTableInfo.getKafkaParamKeys()) { + properties.setProperty(key, kafka10SinkTableInfo.getKafkaParam(key)); + } + + this.partitioner = Optional.of(new FlinkFixedPartitioner<>()); this.fieldNames = kafka10SinkTableInfo.getFields(); - this.fieldTypes = getTypeInformations(kafka10SinkTableInfo); - this.schema = buildTableSchema(fieldNames, fieldTypes); - this.parallelism = kafka10SinkTableInfo.getParallelism(); - this.sinkOperatorName = SINK_OPERATOR_NAME_TPL.replace("${topic}", topic).replace("${table}", tableName); - this.kafkaProducer011 = new KafkaProducer010Factory().createKafkaProducer(kafka10SinkTableInfo, getOutputType(), kafkaProperties, partitioner, partitionKeys); + TypeInformation[] types = new TypeInformation[kafka10SinkTableInfo.getFields().length]; + for (int i = 0; i < kafka10SinkTableInfo.getFieldClasses().length; i++) { + types[i] = TypeInformation.of(kafka10SinkTableInfo.getFieldClasses()[i]); + } + this.fieldTypes = types; + + + TableSchema.Builder schemaBuilder = TableSchema.builder(); + for (int i=0;i getRecordType() { + return new RowTypeInfo(fieldTypes, fieldNames); + } + + @Override + public void emitDataStream(DataStream> dataStream) { + KafkaTableSinkBase kafkaTableSink = new CustomerKafka10JsonTableSink( + schema, + topic, + properties, + partitioner, + serializationSchema + ); + + DataStream ds = dataStream.map((Tuple2 record) -> { + return record.f1; + }).returns(getOutputType().getTypeAt(1)).setParallelism(parallelism); + + kafkaTableSink.emitDataStream(ds); + } + + @Override + public TupleTypeInfo> getOutputType() { + return new TupleTypeInfo(org.apache.flink.table.api.Types.BOOLEAN(), new RowTypeInfo(fieldTypes, fieldNames)); + } + + @Override + public String[] getFieldNames() { + return fieldNames; + } + + @Override + public TypeInformation[] getFieldTypes() { + return fieldTypes; + } + + @Override + public TableSink> configure(String[] fieldNames, TypeInformation[] fieldTypes) { + this.fieldNames = fieldNames; + this.fieldTypes = fieldTypes; return this; } } diff --git a/kafka10/kafka10-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/table/KafkaSinkParser.java b/kafka10/kafka10-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/table/KafkaSinkParser.java new file mode 100644 index 000000000..073fe9111 --- /dev/null +++ b/kafka10/kafka10-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/table/KafkaSinkParser.java @@ -0,0 +1,57 @@ +/* + * 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 com.dtstack.flink.sql.sink.kafka.table; + +import com.dtstack.flink.sql.table.AbsTableParser; +import com.dtstack.flink.sql.table.TableInfo; +import com.dtstack.flink.sql.util.MathUtil; + +import java.util.Map; + +/** + * Date: 2018/12/18 + * Company: www.dtstack.com + * @author DocLi + * + * @modifyer maqi + * + */ +public class KafkaSinkParser extends AbsTableParser { + @Override + public TableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { + KafkaSinkTableInfo kafka10SinkTableInfo = new KafkaSinkTableInfo(); + kafka10SinkTableInfo.setName(tableName); + parseFieldsInfo(fieldsInfo, kafka10SinkTableInfo); + + + kafka10SinkTableInfo.setBootstrapServers(MathUtil.getString(props.get(KafkaSinkTableInfo.BOOTSTRAPSERVERS_KEY.toLowerCase()))); + kafka10SinkTableInfo.setTopic(MathUtil.getString(props.get(KafkaSinkTableInfo.TOPIC_KEY.toLowerCase()))); + + Integer parallelism = MathUtil.getIntegerVal(props.get(KafkaSinkTableInfo.PARALLELISM_KEY.toLowerCase())); + kafka10SinkTableInfo.setParallelism(parallelism); + + for (String key : props.keySet()) { + if (!key.isEmpty() && key.startsWith("kafka.")) { + kafka10SinkTableInfo.addKafkaParam(key.substring(6), props.get(key).toString()); + } + } + kafka10SinkTableInfo.check(); + return kafka10SinkTableInfo; + } +} diff --git a/kafka10/kafka10-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/table/KafkaSinkTableInfo.java b/kafka10/kafka10-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/table/KafkaSinkTableInfo.java new file mode 100644 index 000000000..b4fd0a76c --- /dev/null +++ b/kafka10/kafka10-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/table/KafkaSinkTableInfo.java @@ -0,0 +1,98 @@ +/* + * 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 com.dtstack.flink.sql.sink.kafka.table; + +import com.dtstack.flink.sql.table.TargetTableInfo; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +/** + * + * Date: 2018/12/18 + * Company: www.dtstack.com + * + * @author DocLi + * + * @modifyer maqi + * + */ +public class KafkaSinkTableInfo extends TargetTableInfo { + //version + private static final String CURR_TYPE = "kafka10"; + + public KafkaSinkTableInfo() { + super.setType(CURR_TYPE); + } + + public static final String BOOTSTRAPSERVERS_KEY = "bootstrapServers"; + + public static final String TOPIC_KEY = "topic"; + + private String bootstrapServers; + + public Map kafkaParam = new HashMap(); + + private String topic; + + + public void addKafkaParam(String key,String value){ + kafkaParam.put(key,value); + } + + public String getKafkaParam(String key){ + return kafkaParam.get(key); + } + + public Set getKafkaParamKeys(){ + return kafkaParam.keySet(); + } + + + public String getBootstrapServers() { + return bootstrapServers; + } + + public void setBootstrapServers(String bootstrapServers) { + this.bootstrapServers = bootstrapServers; + } + + public String getTopic() { + return topic; + } + + public void setTopic(String topic) { + this.topic = topic; + } + + + @Override + public boolean check() { + com.google.common.base.Preconditions.checkNotNull(bootstrapServers, "kafka of bootstrapServers is required"); + com.google.common.base.Preconditions.checkNotNull(topic, "kafka of topic is required"); + //Preconditions.checkNotNull(kafkaParam.get("groupId"), "kafka of groupId is required"); + return false; + } + + @Override + public String getType() { + return super.getType(); + } + +} diff --git a/kafka10/kafka10-sink/src/test/java/com/dtstack/flink/sql/source/kafka/KafkaSinkTest.java b/kafka10/kafka10-sink/src/test/java/com/dtstack/flink/sql/source/kafka/KafkaSinkTest.java deleted file mode 100644 index dfc3c7f06..000000000 --- a/kafka10/kafka10-sink/src/test/java/com/dtstack/flink/sql/source/kafka/KafkaSinkTest.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.dtstack.flink.sql.source.kafka; - -import com.dtstack.flink.sql.sink.kafka.KafkaSink; -import com.dtstack.flink.sql.sink.kafka.table.KafkaSinkTableInfo; -import com.google.common.collect.Sets; -import org.junit.Test; - -import static org.mockito.Mockito.*; - -public class KafkaSinkTest { - - @Test - public void mockGenStreamSink(){ - KafkaSinkTableInfo kafkaSinkTableInfo = mock(KafkaSinkTableInfo.class); - when(kafkaSinkTableInfo.getName()).thenReturn("roc"); - when(kafkaSinkTableInfo.getTopic()).thenReturn("topic"); - when(kafkaSinkTableInfo.getBootstrapServers()).thenReturn("localhost"); - when(kafkaSinkTableInfo.getKafkaParamKeys()).thenReturn(Sets.newHashSet("aa")); - when(kafkaSinkTableInfo.getKafkaParam("aa")).thenReturn("xx"); - when(kafkaSinkTableInfo.getPartitionKeys()).thenReturn(null); - when(kafkaSinkTableInfo.getFields()).thenReturn(new String[]{"aa"}); - when(kafkaSinkTableInfo.getFieldClasses()).thenReturn(new Class[]{String.class}); - when(kafkaSinkTableInfo.getParallelism()).thenReturn(1); - when(kafkaSinkTableInfo.getSinkDataType()).thenReturn("json"); - when(kafkaSinkTableInfo.getUpdateMode()).thenReturn("append"); - - KafkaSink kafkaSink = new KafkaSink(); - KafkaSink kafkaSinkSpy = spy(kafkaSink); - kafkaSinkSpy.genStreamSink(kafkaSinkTableInfo); - } -} diff --git a/kafka10/kafka10-source/pom.xml b/kafka10/kafka10-source/pom.xml index 04ee2696a..2d1981253 100644 --- a/kafka10/kafka10-source/pom.xml +++ b/kafka10/kafka10-source/pom.xml @@ -14,14 +14,6 @@ kafka10-source http://maven.apache.org - - - sql.source.kafka-base - com.dtstack.flink - 1.0-SNAPSHOT - - - @@ -35,7 +27,6 @@ shade - false org.slf4j @@ -69,14 +60,14 @@ - + - + diff --git a/kafka10/kafka10-source/src/main/java/com/dtstack/flink/sql/source/kafka/CustomerJsonDeserialization.java b/kafka10/kafka10-source/src/main/java/com/dtstack/flink/sql/source/kafka/CustomerJsonDeserialization.java new file mode 100644 index 000000000..87482a392 --- /dev/null +++ b/kafka10/kafka10-source/src/main/java/com/dtstack/flink/sql/source/kafka/CustomerJsonDeserialization.java @@ -0,0 +1,286 @@ +/* + * 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 com.dtstack.flink.sql.source.kafka; + + +import com.dtstack.flink.sql.source.AbsDeserialization; +import com.dtstack.flink.sql.source.kafka.metric.KafkaTopicPartitionLagMetric; +import com.dtstack.flink.sql.table.TableInfo; +import org.apache.flink.api.common.typeinfo.TypeInformation; +import org.apache.flink.api.common.typeinfo.Types; +import org.apache.flink.api.java.typeutils.RowTypeInfo; +import com.google.common.base.Strings; +import org.apache.flink.metrics.MetricGroup; +import com.google.common.collect.Maps; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import org.apache.flink.streaming.connectors.kafka.internal.KafkaConsumerThread; +import org.apache.flink.streaming.connectors.kafka.internals.AbstractFetcher; +import org.apache.flink.types.Row; +import org.apache.kafka.clients.consumer.KafkaConsumer; +import org.apache.kafka.clients.consumer.internals.SubscriptionState; +import org.apache.kafka.common.TopicPartition; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.lang.reflect.Field; +import java.sql.Date; +import java.sql.Time; +import java.sql.Timestamp; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static com.dtstack.flink.sql.metric.MetricConstant.*; + +/** + * json string parsing custom + * Date: 2018/09/18 + * Company: www.dtstack.com + * @author sishu.yss + */ + +public class CustomerJsonDeserialization extends AbsDeserialization { + + private static final Logger LOG = LoggerFactory.getLogger(CustomerJsonDeserialization.class); + + private static final long serialVersionUID = 2385115520960444192L; + + private static int dirtyDataFrequency = 1000; + + private final ObjectMapper objectMapper = new ObjectMapper(); + + /** Type information describing the result type. */ + private final TypeInformation typeInfo; + + /** Field names to parse. Indices match fieldTypes indices. */ + private final String[] fieldNames; + + /** Types to parse fields as. Indices match fieldNames indices. */ + private final TypeInformation[] fieldTypes; + + private AbstractFetcher fetcher; + + private boolean firstMsg = true; + + private Map nodeAndJsonNodeMapping = Maps.newHashMap(); + + private Map rowAndFieldMapping; + + private List fieldExtraInfos; + + public CustomerJsonDeserialization(TypeInformation typeInfo, Map rowAndFieldMapping, List fieldExtraInfos){ + this.typeInfo = typeInfo; + this.fieldNames = ((RowTypeInfo) typeInfo).getFieldNames(); + this.fieldTypes = ((RowTypeInfo) typeInfo).getFieldTypes(); + this.rowAndFieldMapping= rowAndFieldMapping; + this.fieldExtraInfos = fieldExtraInfos; + } + + @Override + public Row deserialize(byte[] message) throws IOException { + + if(firstMsg){ + try { + registerPtMetric(fetcher); + } catch (Exception e) { + LOG.error("register topic partition metric error.", e); + } + + firstMsg = false; + } + + try { + JsonNode root = objectMapper.readTree(message); + + if (numInRecord.getCount() % dirtyDataFrequency == 0) { + LOG.info(root.toString()); + } + + numInRecord.inc(); + numInBytes.inc(message.length); + + parseTree(root, null); + Row row = new Row(fieldNames.length); + + for (int i = 0; i < fieldNames.length; i++) { + JsonNode node = getIgnoreCase(fieldNames[i]); + TableInfo.FieldExtraInfo fieldExtraInfo = fieldExtraInfos.get(i); + + if (node == null) { + if (fieldExtraInfo != null && fieldExtraInfo.getNotNull()) { + throw new IllegalStateException("Failed to find field with name '" + + fieldNames[i] + "'."); + } else { + row.setField(i, null); + } + } else { + // Read the value as specified type + Object value = convert(node, fieldTypes[i]); + row.setField(i, value); + } + } + + numInResolveRecord.inc(); + return row; + } catch (Exception e) { + //add metric of dirty data + if (dirtyDataCounter.getCount() % dirtyDataFrequency == 0 || LOG.isDebugEnabled()) { + LOG.info("dirtyData: " + new String(message)); + LOG.error(" ", e); + } + dirtyDataCounter.inc(); + return null; + }finally { + nodeAndJsonNodeMapping.clear(); + } + } + + public JsonNode getIgnoreCase(String key) { + String nodeMappingKey = rowAndFieldMapping.getOrDefault(key, key); + + return nodeAndJsonNodeMapping.get(nodeMappingKey); + } + + private void parseTree(JsonNode jsonNode, String prefix){ + + if (jsonNode.isArray()) { + ArrayNode array = (ArrayNode) jsonNode; + for (int i = 0; i < array.size(); i++) { + JsonNode child = array.get(i); + String nodeKey = getNodeKey(prefix, i); + + if (child.isValueNode()) { + nodeAndJsonNodeMapping.put(nodeKey, child); + } else { + if (rowAndFieldMapping.containsValue(nodeKey)) { + nodeAndJsonNodeMapping.put(nodeKey, child); + } + parseTree(child, nodeKey); + } + } + return; + } + + Iterator iterator = jsonNode.fieldNames(); + while (iterator.hasNext()){ + String next = iterator.next(); + JsonNode child = jsonNode.get(next); + String nodeKey = getNodeKey(prefix, next); + + if (child.isValueNode()) { + nodeAndJsonNodeMapping.put(nodeKey, child); + } else if(child.isArray()){ + parseTree(child, nodeKey); + } else { + parseTree(child, nodeKey); + } + } + } + + private String getNodeKey(String prefix, String nodeName){ + if(Strings.isNullOrEmpty(prefix)){ + return nodeName; + } + + return prefix + "." + nodeName; + } + + private String getNodeKey(String prefix, int i) { + if (Strings.isNullOrEmpty(prefix)) { + return "[" + i + "]"; + } + + return prefix + "[" + i + "]"; + } + + public void setFetcher(AbstractFetcher fetcher) { + this.fetcher = fetcher; + } + + + protected void registerPtMetric(AbstractFetcher fetcher) throws Exception { + + Field consumerThreadField = fetcher.getClass().getSuperclass().getDeclaredField("consumerThread"); + consumerThreadField.setAccessible(true); + KafkaConsumerThread consumerThread = (KafkaConsumerThread) consumerThreadField.get(fetcher); + + Field hasAssignedPartitionsField = consumerThread.getClass().getDeclaredField("hasAssignedPartitions"); + hasAssignedPartitionsField.setAccessible(true); + + //wait until assignedPartitions + + boolean hasAssignedPartitions = (boolean) hasAssignedPartitionsField.get(consumerThread); + + if(!hasAssignedPartitions){ + throw new RuntimeException("wait 50 secs, but not assignedPartitions"); + } + + Field consumerField = consumerThread.getClass().getDeclaredField("consumer"); + consumerField.setAccessible(true); + + KafkaConsumer kafkaConsumer = (KafkaConsumer) consumerField.get(consumerThread); + Field subscriptionStateField = kafkaConsumer.getClass().getDeclaredField("subscriptions"); + subscriptionStateField.setAccessible(true); + + //topic partitions lag + SubscriptionState subscriptionState = (SubscriptionState) subscriptionStateField.get(kafkaConsumer); + Set assignedPartitions = subscriptionState.assignedPartitions(); + for(TopicPartition topicPartition : assignedPartitions){ + MetricGroup metricGroup = getRuntimeContext().getMetricGroup().addGroup(DT_TOPIC_GROUP, topicPartition.topic()) + .addGroup(DT_PARTITION_GROUP, topicPartition.partition() + ""); + metricGroup.gauge(DT_TOPIC_PARTITION_LAG_GAUGE, new KafkaTopicPartitionLagMetric(subscriptionState, topicPartition)); + } + + } + + private static String partitionLagMetricName(TopicPartition tp) { + return tp + ".records-lag"; + } + + private Object convert(JsonNode node, TypeInformation info) { + if (info.getTypeClass().equals(Types.BOOLEAN.getTypeClass())) { + return node.asBoolean(); + } else if (info.getTypeClass().equals(Types.STRING.getTypeClass())) { + return node.asText(); + } else if (info.getTypeClass().equals(Types.SQL_DATE.getTypeClass())) { + return Date.valueOf(node.asText()); + } else if (info.getTypeClass().equals(Types.SQL_TIME.getTypeClass())) { + // local zone + return Time.valueOf(node.asText()); + } else if (info.getTypeClass().equals(Types.SQL_TIMESTAMP.getTypeClass())) { + // local zone + return Timestamp.valueOf(node.asText()); + } else { + // for types that were specified without JSON schema + // e.g. POJOs + try { + return objectMapper.treeToValue(node, info.getTypeClass()); + } catch (JsonProcessingException e) { + throw new IllegalStateException("Unsupported type information '" + info + "' for node: " + node); + } + } + } +} diff --git a/kafka10/kafka10-source/src/main/java/com/dtstack/flink/sql/source/kafka/CustomerKafka010Consumer.java b/kafka10/kafka10-source/src/main/java/com/dtstack/flink/sql/source/kafka/CustomerKafka010Consumer.java new file mode 100644 index 000000000..945c47407 --- /dev/null +++ b/kafka10/kafka10-source/src/main/java/com/dtstack/flink/sql/source/kafka/CustomerKafka010Consumer.java @@ -0,0 +1,74 @@ +/* + * 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 com.dtstack.flink.sql.source.kafka; + +import com.dtstack.flink.sql.source.AbsDeserialization; +import org.apache.flink.metrics.MetricGroup; +import org.apache.flink.streaming.api.functions.AssignerWithPeriodicWatermarks; +import org.apache.flink.streaming.api.functions.AssignerWithPunctuatedWatermarks; +import org.apache.flink.streaming.api.operators.StreamingRuntimeContext; +import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer010; +import org.apache.flink.streaming.connectors.kafka.config.OffsetCommitMode; +import org.apache.flink.streaming.connectors.kafka.internals.AbstractFetcher; +import org.apache.flink.streaming.connectors.kafka.internals.KafkaTopicPartition; +import org.apache.flink.types.Row; +import org.apache.flink.util.SerializedValue; + +import java.util.Arrays; +import java.util.Map; +import java.util.Properties; +import java.util.regex.Pattern; + +/** + * Reason: + * Date: 2018/10/19 + * Company: www.dtstack.com + * @author xuchao + */ + +public class CustomerKafka010Consumer extends FlinkKafkaConsumer010 { + + private static final long serialVersionUID = 4873757508981691375L; + + private CustomerJsonDeserialization customerJsonDeserialization; + + public CustomerKafka010Consumer(String topic, AbsDeserialization valueDeserializer, Properties props) { + super(Arrays.asList(topic.split(",")), valueDeserializer, props); + this.customerJsonDeserialization = (CustomerJsonDeserialization) valueDeserializer; + } + + public CustomerKafka010Consumer(Pattern subscriptionPattern, AbsDeserialization valueDeserializer, Properties props) { + super(subscriptionPattern, valueDeserializer, props); + this.customerJsonDeserialization = (CustomerJsonDeserialization) valueDeserializer; + } + @Override + public void run(SourceContext sourceContext) throws Exception { + customerJsonDeserialization.setRuntimeContext(getRuntimeContext()); + customerJsonDeserialization.initMetric(); + super.run(sourceContext); + } + + @Override + protected AbstractFetcher createFetcher(SourceContext sourceContext, Map assignedPartitionsWithInitialOffsets, SerializedValue> watermarksPeriodic, SerializedValue> watermarksPunctuated, StreamingRuntimeContext runtimeContext, OffsetCommitMode offsetCommitMode, MetricGroup consumerMetricGroup, boolean useMetrics) throws Exception { + AbstractFetcher fetcher = super.createFetcher(sourceContext, assignedPartitionsWithInitialOffsets, watermarksPeriodic, watermarksPunctuated, runtimeContext, offsetCommitMode, consumerMetricGroup, useMetrics); + customerJsonDeserialization.setFetcher(fetcher); + return fetcher; + } + +} \ No newline at end of file diff --git a/kafka10/kafka10-source/src/main/java/com/dtstack/flink/sql/source/kafka/KafkaConsumer010.java b/kafka10/kafka10-source/src/main/java/com/dtstack/flink/sql/source/kafka/KafkaConsumer010.java deleted file mode 100644 index ad46e7b8c..000000000 --- a/kafka10/kafka10-source/src/main/java/com/dtstack/flink/sql/source/kafka/KafkaConsumer010.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.source.kafka; - -import com.dtstack.flink.sql.format.DeserializationMetricWrapper; -import com.dtstack.flink.sql.source.kafka.deserialization.DtKafkaDeserializationSchemaWrapper; -import com.dtstack.flink.sql.source.kafka.deserialization.KafkaDeserializationMetricWrapper; -import com.dtstack.flink.sql.source.kafka.sample.OffsetFetcher; -import com.dtstack.flink.sql.source.kafka.sample.OffsetMap; -import com.dtstack.flink.sql.source.kafka.sample.SampleCalculateHelper; -import org.apache.commons.lang3.StringUtils; -import org.apache.flink.api.common.serialization.DeserializationSchema; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.metrics.MetricGroup; -import org.apache.flink.streaming.api.functions.AssignerWithPeriodicWatermarks; -import org.apache.flink.streaming.api.functions.AssignerWithPunctuatedWatermarks; -import org.apache.flink.streaming.api.operators.StreamingRuntimeContext; -import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer010; -import org.apache.flink.streaming.connectors.kafka.config.OffsetCommitMode; -import org.apache.flink.streaming.connectors.kafka.internals.AbstractFetcher; -import org.apache.flink.streaming.connectors.kafka.internals.KafkaTopicPartition; -import org.apache.flink.types.Row; -import org.apache.flink.util.SerializedValue; -import org.apache.kafka.clients.consumer.KafkaConsumer; -import org.apache.kafka.common.PartitionInfo; -import org.apache.kafka.common.TopicPartition; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.regex.Pattern; - - -/** - * Reason: - * Date: 2018/10/19 - * Company: www.dtstack.com - * - * @author xuchao - */ -public class KafkaConsumer010 extends FlinkKafkaConsumer010 implements OffsetFetcher { - - private final DeserializationMetricWrapper deserializationMetricWrapper; - - private String topic; - - private final Properties props; - - private final Long sampleSize; - - public KafkaConsumer010( - String topic, - Long sampleSize, - DeserializationMetricWrapper deserializationMetricWrapper, - Properties props) { - super( - Arrays.asList(StringUtils.split(topic, ",")), - new DtKafkaDeserializationSchemaWrapper<>(deserializationMetricWrapper), - props); - this.topic = topic; - this.props = props; - this.sampleSize = sampleSize; - this.deserializationMetricWrapper = deserializationMetricWrapper; - } - - public KafkaConsumer010( - Pattern subscriptionPattern, - Long sampleSize, - DeserializationMetricWrapper deserializationMetricWrapper, - Properties props) { - super( - subscriptionPattern, - new DtKafkaDeserializationSchemaWrapper<>(deserializationMetricWrapper), - props); - this.sampleSize = sampleSize; - this.props = props; - this.deserializationMetricWrapper = deserializationMetricWrapper; - } - - @Override - public void run(SourceContext sourceContext) throws Exception { - deserializationMetricWrapper.setRuntimeContext(getRuntimeContext()); - deserializationMetricWrapper.initMetric(); - super.run(sourceContext); - } - - @Override - protected AbstractFetcher createFetcher(SourceContext sourceContext, - Map assignedPartitionsWithInitialOffsets, - SerializedValue> watermarksPeriodic, - SerializedValue> watermarksPunctuated, - StreamingRuntimeContext runtimeContext, - OffsetCommitMode offsetCommitMode, - MetricGroup consumerMetricGroup, - boolean useMetrics) throws Exception { - final OffsetMap offsetMap = sampleSize > 0 ? seekOffset(props, topic) : new OffsetMap(); - Map rebuild; - - rebuild = - sampleSize > 0 - ? SampleCalculateHelper.rebuildAssignedPartitionsWithInitialOffsets( - offsetMap, sampleSize, assignedPartitionsWithInitialOffsets) - : assignedPartitionsWithInitialOffsets; - - AbstractFetcher fetcher = - super.createFetcher( - sourceContext, - rebuild, - watermarksPeriodic, - watermarksPunctuated, - runtimeContext, - offsetCommitMode, - consumerMetricGroup, - useMetrics); - - ((KafkaDeserializationMetricWrapper) deserializationMetricWrapper).setFetcher(fetcher); - ((DtKafkaDeserializationSchemaWrapper) deserializer).setSpecificEndOffsets(offsetMap); - return fetcher; - } - - @Override - public TypeInformation getProducedType() { - DeserializationSchema deserializationSchema = deserializationMetricWrapper.getDeserializationSchema(); - return deserializationSchema.getProducedType(); - } - - @Override - public OffsetMap fetchOffset(KafkaConsumer consumer, java.lang.String topic) { - OffsetMap offsetMap = new OffsetMap(); - - List topicPartitions = new ArrayList<>(); - - List partitionInfos = consumer.partitionsFor(topic); - - partitionInfos.forEach( - item -> topicPartitions.add(new TopicPartition(topic, item.partition()))); - - consumer.assign(topicPartitions); - consumer.poll(10 * 1000L); - - consumer.seekToEnd(topicPartitions); - topicPartitions.forEach( - item -> - offsetMap.setLatest( - new KafkaTopicPartition(topic, item.partition()), - consumer.position(item))); - - consumer.seekToBeginning(topicPartitions); - topicPartitions.forEach( - item -> - offsetMap.setEarliest( - new KafkaTopicPartition(topic, item.partition()), - consumer.position(item))); - - return offsetMap; - } -} \ No newline at end of file diff --git a/kafka10/kafka10-source/src/main/java/com/dtstack/flink/sql/source/kafka/KafkaConsumer010Factory.java b/kafka10/kafka10-source/src/main/java/com/dtstack/flink/sql/source/kafka/KafkaConsumer010Factory.java deleted file mode 100644 index 8cb584fd0..000000000 --- a/kafka10/kafka10-source/src/main/java/com/dtstack/flink/sql/source/kafka/KafkaConsumer010Factory.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.source.kafka; - -import com.dtstack.flink.sql.format.DeserializationMetricWrapper; -import com.dtstack.flink.sql.source.kafka.table.KafkaSourceTableInfo; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumerBase; -import org.apache.flink.types.Row; -import org.apache.kafka.clients.consumer.internals.SubscriptionState; - -import java.io.Serializable; -import java.util.Properties; -import java.util.regex.Pattern; - -/** - * company: www.dtstack.com - * @author: toutian - * create: 2019/12/24 - */ -public class KafkaConsumer010Factory extends AbstractKafkaConsumerFactory { - - @Override - public FlinkKafkaConsumerBase createKafkaTableSource(KafkaSourceTableInfo kafkaSourceTableInfo, - TypeInformation typeInformation, - Properties props) { - KafkaConsumer010 kafkaSrc; - if (kafkaSourceTableInfo.getTopicIsPattern()) { - DeserializationMetricWrapper deserMetricWrapper = createDeserializationMetricWrapper(kafkaSourceTableInfo, typeInformation, (Calculate & Serializable) SubscriptionState::partitionLag); - kafkaSrc = - new KafkaConsumer010( - Pattern.compile(kafkaSourceTableInfo.getTopic()), - kafkaSourceTableInfo.getSampleSize(), - deserMetricWrapper, - props); - } else { - DeserializationMetricWrapper deserMetricWrapper = createDeserializationMetricWrapper(kafkaSourceTableInfo, typeInformation, (Calculate & Serializable) SubscriptionState::partitionLag); - kafkaSrc = - new KafkaConsumer010( - kafkaSourceTableInfo.getTopic(), - kafkaSourceTableInfo.getSampleSize(), - deserMetricWrapper, - props); - } - - return kafkaSrc; - } - -} diff --git a/kafka10/kafka10-source/src/main/java/com/dtstack/flink/sql/source/kafka/KafkaSource.java b/kafka10/kafka10-source/src/main/java/com/dtstack/flink/sql/source/kafka/KafkaSource.java index b6cb96a79..ab5ad8833 100644 --- a/kafka10/kafka10-source/src/main/java/com/dtstack/flink/sql/source/kafka/KafkaSource.java +++ b/kafka10/kafka10-source/src/main/java/com/dtstack/flink/sql/source/kafka/KafkaSource.java @@ -19,18 +19,27 @@ package com.dtstack.flink.sql.source.kafka; +import com.dtstack.flink.sql.source.IStreamSourceGener; import com.dtstack.flink.sql.source.kafka.table.KafkaSourceTableInfo; -import com.dtstack.flink.sql.table.AbstractSourceTableInfo; +import com.dtstack.flink.sql.table.SourceTableInfo; +import com.dtstack.flink.sql.util.DtStringUtil; +import com.dtstack.flink.sql.util.PluginUtil; +import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; import org.apache.flink.api.common.typeinfo.TypeInformation; +import org.apache.flink.api.java.typeutils.RowTypeInfo; import org.apache.flink.streaming.api.datastream.DataStreamSource; import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer010; +import org.apache.flink.streaming.connectors.kafka.internals.KafkaTopicPartition; import org.apache.flink.table.api.Table; import org.apache.flink.table.api.java.StreamTableEnvironment; import org.apache.flink.types.Row; +import java.util.HashMap; +import java.util.Map; import java.util.Properties; +import java.util.regex.Pattern; /** * If eventtime field is specified, the default time field rowtime @@ -40,24 +49,80 @@ * @author sishu.yss */ -public class KafkaSource extends AbstractKafkaSource { +public class KafkaSource implements IStreamSourceGener

{ - @Override - public Table genStreamSource(AbstractSourceTableInfo sourceTableInfo, StreamExecutionEnvironment env, StreamTableEnvironment tableEnv) { - KafkaSourceTableInfo kafkaSourceTableInfo = (KafkaSourceTableInfo) sourceTableInfo; - String topicName = kafkaSourceTableInfo.getTopic(); + private static final String SOURCE_OPERATOR_NAME_TPL = "${topic}_${table}"; - Properties kafkaProperties = getKafkaProperties(kafkaSourceTableInfo); - TypeInformation typeInformation = getRowTypeInformation(kafkaSourceTableInfo); - FlinkKafkaConsumer010 kafkaSrc = (FlinkKafkaConsumer010) new KafkaConsumer010Factory().createKafkaTableSource(kafkaSourceTableInfo, typeInformation, kafkaProperties); + /** + * Get kafka data source, you need to provide the data field names, data types + * If you do not specify auto.offset.reset, the default use groupoffset + * + * @param sourceTableInfo + * @return + */ + @SuppressWarnings("rawtypes") + @Override + public Table genStreamSource(SourceTableInfo sourceTableInfo, StreamExecutionEnvironment env, StreamTableEnvironment tableEnv) { - String sourceOperatorName = generateOperatorName(sourceTableInfo.getName(), topicName); - DataStreamSource kafkaSource = env.addSource(kafkaSrc, sourceOperatorName, typeInformation); + KafkaSourceTableInfo kafka010SourceTableInfo = (KafkaSourceTableInfo) sourceTableInfo; + String topicName = kafka010SourceTableInfo.getTopic(); - setParallelism(kafkaSourceTableInfo.getParallelism(), kafkaSource); - setStartPosition(kafkaSourceTableInfo.getOffsetReset(), topicName, kafkaSrc, () -> kafkaSrc.setStartFromTimestamp(kafkaSourceTableInfo.getTimestampOffset())); - String fields = StringUtils.join(kafkaSourceTableInfo.getFields(), ","); + Properties props = new Properties(); + props.setProperty("bootstrap.servers", kafka010SourceTableInfo.getBootstrapServers()); + if (DtStringUtil.isJosn(kafka010SourceTableInfo.getOffsetReset())){ + props.setProperty("auto.offset.reset", "none"); + } else { + props.setProperty("auto.offset.reset", kafka010SourceTableInfo.getOffsetReset()); + } + if (StringUtils.isNotBlank(kafka010SourceTableInfo.getGroupId())){ + props.setProperty("group.id", kafka010SourceTableInfo.getGroupId()); + } + // only required for Kafka 0.8 + //TODO props.setProperty("zookeeper.connect", kafka09SourceTableInfo.) - return tableEnv.fromDataStream(kafkaSource, fields); - } + TypeInformation[] types = new TypeInformation[kafka010SourceTableInfo.getFields().length]; + for (int i = 0; i < kafka010SourceTableInfo.getFieldClasses().length; i++) { + types[i] = TypeInformation.of(kafka010SourceTableInfo.getFieldClasses()[i]); + } + + TypeInformation typeInformation = new RowTypeInfo(types, kafka010SourceTableInfo.getFields()); + + FlinkKafkaConsumer010 kafkaSrc; + if (BooleanUtils.isTrue(kafka010SourceTableInfo.getTopicIsPattern())) { + kafkaSrc = new CustomerKafka010Consumer(Pattern.compile(topicName), + new CustomerJsonDeserialization(typeInformation, kafka010SourceTableInfo.getPhysicalFields(), kafka010SourceTableInfo.getFieldExtraInfoList()), props); + } else { + kafkaSrc = new CustomerKafka010Consumer(topicName, + new CustomerJsonDeserialization(typeInformation, kafka010SourceTableInfo.getPhysicalFields(), kafka010SourceTableInfo.getFieldExtraInfoList()), props); + } + + //earliest,latest + if ("earliest".equalsIgnoreCase(kafka010SourceTableInfo.getOffsetReset())) { + kafkaSrc.setStartFromEarliest(); + } else if (DtStringUtil.isJosn(kafka010SourceTableInfo.getOffsetReset())) {// {"0":12312,"1":12321,"2":12312} + try { + Properties properties = PluginUtil.jsonStrToObject(kafka010SourceTableInfo.getOffsetReset(), Properties.class); + Map offsetMap = PluginUtil.ObjectToMap(properties); + Map specificStartupOffsets = new HashMap<>(); + for (Map.Entry entry : offsetMap.entrySet()) { + specificStartupOffsets.put(new KafkaTopicPartition(topicName, Integer.valueOf(entry.getKey())), Long.valueOf(entry.getValue().toString())); + } + kafkaSrc.setStartFromSpecificOffsets(specificStartupOffsets); + } catch (Exception e) { + throw new RuntimeException("not support offsetReset type:" + kafka010SourceTableInfo.getOffsetReset()); + } + } else { + kafkaSrc.setStartFromLatest(); + } + + String fields = StringUtils.join(kafka010SourceTableInfo.getFields(), ","); + String sourceOperatorName = SOURCE_OPERATOR_NAME_TPL.replace("${topic}", topicName).replace("${table}", sourceTableInfo.getName()); + + DataStreamSource kafkaSource = env.addSource(kafkaSrc, sourceOperatorName, typeInformation); + Integer parallelism = kafka010SourceTableInfo.getParallelism(); + if (parallelism != null) { + kafkaSource.setParallelism(parallelism); + } + return tableEnv.fromDataStream(kafkaSource, fields); + } } \ No newline at end of file diff --git a/kafka10/kafka10-source/src/main/java/com/dtstack/flink/sql/source/kafka/metric/KafkaTopicPartitionLagMetric.java b/kafka10/kafka10-source/src/main/java/com/dtstack/flink/sql/source/kafka/metric/KafkaTopicPartitionLagMetric.java new file mode 100644 index 000000000..433699f7a --- /dev/null +++ b/kafka10/kafka10-source/src/main/java/com/dtstack/flink/sql/source/kafka/metric/KafkaTopicPartitionLagMetric.java @@ -0,0 +1,29 @@ +package com.dtstack.flink.sql.source.kafka.metric; + +import org.apache.flink.metrics.Gauge; +import org.apache.kafka.clients.consumer.internals.SubscriptionState; +import org.apache.kafka.common.TopicPartition; + +/** + * Reason: + * Date: 2018/10/24 + * Company: www.dtstack.com + * @author xuchao + */ + +public class KafkaTopicPartitionLagMetric implements Gauge { + + private SubscriptionState subscriptionState; + + private TopicPartition tp; + + public KafkaTopicPartitionLagMetric(SubscriptionState subscriptionState, TopicPartition tp){ + this.subscriptionState = subscriptionState; + this.tp = tp; + } + + @Override + public Long getValue() { + return subscriptionState.partitionLag(tp); + } +} diff --git a/kafka10/kafka10-source/src/main/java/com/dtstack/flink/sql/source/kafka/table/KafkaSourceParser.java b/kafka10/kafka10-source/src/main/java/com/dtstack/flink/sql/source/kafka/table/KafkaSourceParser.java new file mode 100644 index 000000000..563110726 --- /dev/null +++ b/kafka10/kafka10-source/src/main/java/com/dtstack/flink/sql/source/kafka/table/KafkaSourceParser.java @@ -0,0 +1,102 @@ +/* + * 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 com.dtstack.flink.sql.source.kafka.table; + +import com.dtstack.flink.sql.table.AbsSourceParser; +import com.dtstack.flink.sql.table.TableInfo; +import com.dtstack.flink.sql.util.ClassUtil; +import com.dtstack.flink.sql.util.MathUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Reason: + * Date: 2018/09/18 + * Company: www.dtstack.com + * @author sishu.yss + */ + +public class KafkaSourceParser extends AbsSourceParser { + + private static final Logger LOG = LoggerFactory.getLogger(KafkaSourceParser.class); + + private static final String KAFKA_NEST_FIELD_KEY = "nestFieldKey"; + + private static Pattern kafkaNestFieldKeyPattern = Pattern.compile("(?i)((@*\\S+\\.)*\\S+)\\s+(\\w+)\\s+AS\\s+(\\w+)(\\s+NOT\\s+NULL)?$"); + + static { + keyPatternMap.put(KAFKA_NEST_FIELD_KEY, kafkaNestFieldKeyPattern); + + keyHandlerMap.put(KAFKA_NEST_FIELD_KEY, KafkaSourceParser::dealNestField); + } + + /** + * add parser for alias field + * @param matcher + * @param tableInfo + */ + static void dealNestField(Matcher matcher, TableInfo tableInfo) { + String physicalField = matcher.group(1); + String fieldType = matcher.group(3); + String mappingField = matcher.group(4); + Class fieldClass= ClassUtil.stringConvertClass(fieldType); + boolean notNull = matcher.group(5) != null; + TableInfo.FieldExtraInfo fieldExtraInfo = new TableInfo.FieldExtraInfo(); + fieldExtraInfo.setNotNull(notNull); + + tableInfo.addPhysicalMappings(mappingField, physicalField); + tableInfo.addField(mappingField); + tableInfo.addFieldClass(fieldClass); + tableInfo.addFieldType(fieldType); + tableInfo.addFieldExtraInfo(fieldExtraInfo); + if(LOG.isInfoEnabled()){ + LOG.info(physicalField + "--->" + mappingField + " Class: " + fieldClass.toString()); + } + } + + @Override + public TableInfo getTableInfo(String tableName, String fieldsInfo, Map props) throws Exception { + + KafkaSourceTableInfo kafka10SourceTableInfo = new KafkaSourceTableInfo(); + kafka10SourceTableInfo.setName(tableName); + parseFieldsInfo(fieldsInfo, kafka10SourceTableInfo); + + kafka10SourceTableInfo.setParallelism(MathUtil.getIntegerVal(props.get(KafkaSourceTableInfo.PARALLELISM_KEY.toLowerCase()))); + + String bootstrapServer = MathUtil.getString(props.get(KafkaSourceTableInfo.BOOTSTRAPSERVERS_KEY.toLowerCase())); + if (bootstrapServer == null || bootstrapServer.trim().equals("")){ + throw new Exception("BootstrapServers can not be empty!"); + } else { + kafka10SourceTableInfo.setBootstrapServers(bootstrapServer); + } + kafka10SourceTableInfo.setGroupId(MathUtil.getString(props.get(KafkaSourceTableInfo.GROUPID_KEY.toLowerCase()))); + kafka10SourceTableInfo.setTopic(MathUtil.getString(props.get(KafkaSourceTableInfo.TOPIC_KEY.toLowerCase()))); + kafka10SourceTableInfo.setOffsetReset(MathUtil.getString(props.get(KafkaSourceTableInfo.OFFSETRESET_KEY.toLowerCase()))); + kafka10SourceTableInfo.setTopicIsPattern(MathUtil.getBoolean(props.get(KafkaSourceTableInfo.TOPICISPATTERN_KEY.toLowerCase()))); + kafka10SourceTableInfo.setTimeZone(MathUtil.getString(props.get(KafkaSourceTableInfo.TIME_ZONE_KEY.toLowerCase()))); + kafka10SourceTableInfo.check(); + return kafka10SourceTableInfo; + } +} diff --git a/kafka10/kafka10-source/src/main/java/com/dtstack/flink/sql/source/kafka/table/KafkaSourceTableInfo.java b/kafka10/kafka10-source/src/main/java/com/dtstack/flink/sql/source/kafka/table/KafkaSourceTableInfo.java new file mode 100644 index 000000000..da78a2af6 --- /dev/null +++ b/kafka10/kafka10-source/src/main/java/com/dtstack/flink/sql/source/kafka/table/KafkaSourceTableInfo.java @@ -0,0 +1,132 @@ +/* + * 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 com.dtstack.flink.sql.source.kafka.table; + +import com.dtstack.flink.sql.table.SourceTableInfo; +import com.google.common.base.Preconditions; + +/** + * Reason: + * Date: 2018/09/18 + * Company: www.dtstack.com + * @author sishu.yss + */ + +public class KafkaSourceTableInfo extends SourceTableInfo { + + //version + private static final String CURR_TYPE = "kafka10"; + + public static final String BOOTSTRAPSERVERS_KEY = "bootstrapServers"; + + public static final String TOPIC_KEY = "topic"; + + public static final String GROUPID_KEY = "groupId"; + + public static final String OFFSETRESET_KEY="offsetReset"; + + public static final String TOPICISPATTERN_KEY = "topicIsPattern"; + + private String bootstrapServers; + + private String topic; + + private String groupId; + + //latest, earliest + private String offsetReset = "latest"; + + private String offset; + + private Boolean topicIsPattern = false; + + public KafkaSourceTableInfo(){ + super.setType(CURR_TYPE); + } + + + public String getBootstrapServers() { + return bootstrapServers; + } + + public void setBootstrapServers(String bootstrapServers) { + this.bootstrapServers = bootstrapServers; + } + + public String getTopic() { + return topic; + } + + public void setTopic(String topic) { + this.topic = topic; + } + + public String getGroupId() { + return groupId; + } + + public void setGroupId(String groupId) { + this.groupId = groupId; + } + + public String getOffsetReset() { + return offsetReset; + } + + public void setOffsetReset(String offsetReset) { + if(offsetReset == null){ + return; + } + this.offsetReset = offsetReset; + } + + public String getOffset() { + return offset; + } + + public void setOffset(String offset) { + if (offsetReset == null) { + return; + } + this.offset = offset; + } + + public Boolean getTopicIsPattern() { + return topicIsPattern; + } + + public void setTopicIsPattern(Boolean topicIsPattern) { + this.topicIsPattern = topicIsPattern; + } + + @Override + public boolean check() { + Preconditions.checkNotNull(bootstrapServers, "kafka of bootstrapServers is required"); + Preconditions.checkNotNull(topic, "kafka of topic is required"); + return false; + } + + @Override + public String getType() { +// return super.getType() + SOURCE_SUFFIX; + return super.getType(); + } +} diff --git a/kafka10/kafka10-source/src/test/java/com/dtstack/flink/sql/source/kafka/KafkaSourceTest.java b/kafka10/kafka10-source/src/test/java/com/dtstack/flink/sql/source/kafka/KafkaSourceTest.java deleted file mode 100644 index 396b69550..000000000 --- a/kafka10/kafka10-source/src/test/java/com/dtstack/flink/sql/source/kafka/KafkaSourceTest.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.dtstack.flink.sql.source.kafka; - -import com.dtstack.flink.sql.source.kafka.table.KafkaSourceTableInfo; -import com.google.common.collect.Sets; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.streaming.api.datastream.DataStreamSource; -import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; -import org.apache.flink.streaming.api.functions.source.SourceFunction; -import org.apache.flink.table.api.java.StreamTableEnvironment; -import org.junit.Test; -import org.mockito.ArgumentMatcher; - -import static org.mockito.Mockito.*; - -public class KafkaSourceTest { - - @Test - public void mockGenStreamSource(){ - KafkaSourceTableInfo kafkaSourceTableInfo = mock(KafkaSourceTableInfo.class); - when(kafkaSourceTableInfo.getTopic()).thenReturn("topic"); - when(kafkaSourceTableInfo.getGroupId()).thenReturn("groupId"); - when(kafkaSourceTableInfo.getBootstrapServers()).thenReturn("localhost"); - when(kafkaSourceTableInfo.getKafkaParamKeys()).thenReturn(Sets.newHashSet("aa")); - when(kafkaSourceTableInfo.getKafkaParam("aa")).thenReturn("xx"); - when(kafkaSourceTableInfo.getFields()).thenReturn(new String[]{"aa"}); - when(kafkaSourceTableInfo.getFieldClasses()).thenReturn(new Class[]{String.class}); - when(kafkaSourceTableInfo.getParallelism()).thenReturn(1); - when(kafkaSourceTableInfo.getName()).thenReturn("roc"); - when(kafkaSourceTableInfo.getOffsetReset()).thenReturn("1"); - when(kafkaSourceTableInfo.getSourceDataType()).thenReturn("json"); - - DataStreamSource dataStreamSource = mock(DataStreamSource.class); - - StreamExecutionEnvironment env = mock(StreamExecutionEnvironment.class); - when(env.addSource(argThat(new ArgumentMatcher>() { - @Override - public boolean matches(SourceFunction sourceFunction) { - return true; - } - }), argThat(new ArgumentMatcher() { - @Override - public boolean matches(String s) { - return true; - } - }), argThat(new ArgumentMatcher() { - @Override - public boolean matches(TypeInformation typeInformation) { - return true; - } - }))).thenReturn(dataStreamSource); - - StreamTableEnvironment tableEnv = mock(StreamTableEnvironment.class); - - KafkaSource kafkaSource = new KafkaSource(); - KafkaSource kafkaSourceSpy = spy(kafkaSource); -// kafkaSourceSpy.genStreamSource(kafkaSourceTableInfo, env, tableEnv); - } - -} - diff --git a/core/src/main/java/com/dtstack/flink/sql/exception/sqlparse/WithoutTableNameException.java b/kafka10/kafka10-source/src/test/java/com/dtstack/flinkx/AppTest.java similarity index 58% rename from core/src/main/java/com/dtstack/flink/sql/exception/sqlparse/WithoutTableNameException.java rename to kafka10/kafka10-source/src/test/java/com/dtstack/flinkx/AppTest.java index e55bdbd91..33a0233ac 100644 --- a/core/src/main/java/com/dtstack/flink/sql/exception/sqlparse/WithoutTableNameException.java +++ b/kafka10/kafka10-source/src/test/java/com/dtstack/flinkx/AppTest.java @@ -16,22 +16,43 @@ * limitations under the License. */ -package com.dtstack.flink.sql.exception.sqlparse; + -import com.dtstack.flink.sql.exception.BaseException; -import com.dtstack.flink.sql.exception.ErrorCode; +package com.dtstack.flinkx; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; /** - * @author: chuixue - * @create: 2020-11-30 14:49 - * @description:流join维表时,select、join、group by等字段未使用t.field - **/ -public class WithoutTableNameException extends BaseException { - public WithoutTableNameException(String msg){ - super(msg); + * Unit test for simple App. + */ +public class AppTest + extends TestCase +{ + /** + * Create the test case + * + * @param testName name of the test case + */ + public AppTest( String testName ) + { + super( testName ); + } + + /** + * @return the suite of tests being tested + */ + public static Test suite() + { + return new TestSuite( AppTest.class ); } - public WithoutTableNameException(ErrorCode errorCode){ - super(errorCode); + /** + * Rigourous Test :-) + */ + public void testApp() + { + assertTrue( true ); } -} \ No newline at end of file +} diff --git a/kafka10/pom.xml b/kafka10/pom.xml index 9e4abd6e1..d8ad7370f 100644 --- a/kafka10/pom.xml +++ b/kafka10/pom.xml @@ -23,6 +23,12 @@ flink-connector-kafka-0.10_2.11 ${flink.version} + + junit + junit + 3.8.1 + test + com.dtstack.flink diff --git a/kafka11/kafka11-sink/pom.xml b/kafka11/kafka11-sink/pom.xml index 3be8b6060..c27ebb791 100644 --- a/kafka11/kafka11-sink/pom.xml +++ b/kafka11/kafka11-sink/pom.xml @@ -6,7 +6,7 @@ sql.kafka11 com.dtstack.flink 1.0-SNAPSHOT - + ../pom.xml 4.0.0 @@ -18,9 +18,9 @@ - sql.sink.kafka-base - com.dtstack.flink - 1.0-SNAPSHOT + org.apache.flink + flink-json + ${flink.version} @@ -37,7 +37,6 @@ shade - false org.slf4j @@ -71,14 +70,14 @@ - + - + diff --git a/kafka11/kafka11-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerFlinkKafkaProducer011.java b/kafka11/kafka11-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerFlinkKafkaProducer011.java new file mode 100644 index 000000000..6d90d44c9 --- /dev/null +++ b/kafka11/kafka11-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerFlinkKafkaProducer011.java @@ -0,0 +1,59 @@ +/** + * 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 com.dtstack.flink.sql.sink.kafka; + +import com.dtstack.flink.sql.metric.MetricConstant; +import org.apache.flink.api.common.functions.RuntimeContext; +import org.apache.flink.api.common.serialization.SerializationSchema; +import org.apache.flink.configuration.Configuration; +import org.apache.flink.metrics.Counter; +import org.apache.flink.metrics.MeterView; +import org.apache.flink.streaming.connectors.kafka.FlinkKafkaProducer010; + +import java.util.Properties; + +/** + * Reason: + * Date: 2019/4/24 + * Company: www.dtstack.com + * + * @author maqi + */ +public class CustomerFlinkKafkaProducer011 extends FlinkKafkaProducer010 { + + CustomerJsonRowSerializationSchema schema; + + public CustomerFlinkKafkaProducer011(String topicId, SerializationSchema serializationSchema, Properties producerConfig) { + super(topicId, serializationSchema, producerConfig); + this.schema = (CustomerJsonRowSerializationSchema) serializationSchema; + } + + @Override + public void open(Configuration configuration) { + producer = getKafkaProducer(this.producerConfig); + + RuntimeContext ctx = getRuntimeContext(); + Counter counter = ctx.getMetricGroup().counter(MetricConstant.DT_NUM_RECORDS_OUT); + MeterView meter = ctx.getMetricGroup().meter(MetricConstant.DT_NUM_RECORDS_OUT_RATE, new MeterView(counter, 20)); + + schema.setCounter(counter); + + super.open(configuration); + } + +} \ No newline at end of file diff --git a/kafka11/kafka11-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerJsonRowSerializationSchema.java b/kafka11/kafka11-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerJsonRowSerializationSchema.java new file mode 100644 index 000000000..0d575a5fd --- /dev/null +++ b/kafka11/kafka11-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerJsonRowSerializationSchema.java @@ -0,0 +1,221 @@ +/* + * 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 com.dtstack.flink.sql.sink.kafka; + +import org.apache.flink.annotation.PublicEvolving; +import org.apache.flink.api.common.serialization.SerializationSchema; +import org.apache.flink.api.common.typeinfo.BasicArrayTypeInfo; +import org.apache.flink.api.common.typeinfo.PrimitiveArrayTypeInfo; +import org.apache.flink.api.common.typeinfo.TypeInformation; +import org.apache.flink.api.common.typeinfo.Types; +import org.apache.flink.api.java.typeutils.ObjectArrayTypeInfo; +import org.apache.flink.api.java.typeutils.RowTypeInfo; +import org.apache.flink.formats.json.JsonRowDeserializationSchema; +import org.apache.flink.formats.json.JsonRowSchemaConverter; +import org.apache.flink.metrics.Counter; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ContainerNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.apache.flink.types.Row; +import org.apache.flink.util.Preconditions; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.sql.Time; +import java.sql.Timestamp; +import java.text.SimpleDateFormat; + +/** + * Serialization schema that serializes an object of Flink types into a JSON bytes. + * + *

Serializes the input Flink object into a JSON string and + * converts it into byte[]. + * + *

Result byte[] messages can be deserialized using {@link JsonRowDeserializationSchema}. + */ +@PublicEvolving +public class CustomerJsonRowSerializationSchema implements SerializationSchema { + + private static final long serialVersionUID = -2885556750743978636L; + + /** Type information describing the input type. */ + private final TypeInformation typeInfo; + + /** Object mapper that is used to create output JSON objects. */ + private final ObjectMapper mapper = new ObjectMapper(); + + /** Formatter for RFC 3339-compliant string representation of a time value (with UTC timezone, without milliseconds). */ + private SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss'Z'"); + + /** Formatter for RFC 3339-compliant string representation of a time value (with UTC timezone). */ + private SimpleDateFormat timeFormatWithMillis = new SimpleDateFormat("HH:mm:ss.SSS'Z'"); + + /** Formatter for RFC 3339-compliant string representation of a timestamp value (with UTC timezone). */ + private SimpleDateFormat timestampFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); + + /** Reusable object node. */ + private transient ObjectNode node; + + private Counter counter; + + /** + * Creates a JSON serialization schema for the given type information. + * + * @param typeInfo The field names of {@link Row} are used to map to JSON properties. + */ + public CustomerJsonRowSerializationSchema(TypeInformation typeInfo) { + Preconditions.checkNotNull(typeInfo, "Type information"); + this.typeInfo = typeInfo; + } + + /** + * Creates a JSON serialization schema for the given JSON schema. + * + * @param jsonSchema JSON schema describing the result type + * + * @see http://json-schema.org/ + */ + public CustomerJsonRowSerializationSchema(String jsonSchema) { + this(JsonRowSchemaConverter.convert(jsonSchema)); + } + + @Override + public byte[] serialize(Row row) { + if (node == null) { + node = mapper.createObjectNode(); + } + + try { + convertRow(node, (RowTypeInfo) typeInfo, row); + counter.inc(); + return mapper.writeValueAsBytes(node); + } catch (Throwable t) { + throw new RuntimeException("Could not serialize row '" + row + "'. " + + "Make sure that the schema matches the input.", t); + } + } + + // -------------------------------------------------------------------------------------------- + + private ObjectNode convertRow(ObjectNode reuse, RowTypeInfo info, Row row) { + if (reuse == null) { + reuse = mapper.createObjectNode(); + } + final String[] fieldNames = info.getFieldNames(); + final TypeInformation[] fieldTypes = info.getFieldTypes(); + + // validate the row + if (row.getArity() != fieldNames.length) { + throw new IllegalStateException(String.format( + "Number of elements in the row '%s' is different from number of field names: %d", row, fieldNames.length)); + } + + for (int i = 0; i < fieldNames.length; i++) { + final String name = fieldNames[i]; + + final JsonNode fieldConverted = convert(reuse, reuse.get(name), fieldTypes[i], row.getField(i)); + reuse.set(name, fieldConverted); + } + + return reuse; + } + + private JsonNode convert(ContainerNode container, JsonNode reuse, TypeInformation info, Object object) { + if (info == Types.VOID || object == null) { + return container.nullNode(); + } else if (info == Types.BOOLEAN) { + return container.booleanNode((Boolean) object); + } else if (info == Types.STRING) { + return container.textNode((String) object); + } else if (info == Types.BIG_DEC) { + // convert decimal if necessary + if (object instanceof BigDecimal) { + return container.numberNode((BigDecimal) object); + } + return container.numberNode(BigDecimal.valueOf(((Number) object).doubleValue())); + } else if (info == Types.BIG_INT) { + // convert integer if necessary + if (object instanceof BigInteger) { + return container.numberNode((BigInteger) object); + } + return container.numberNode(BigInteger.valueOf(((Number) object).longValue())); + } else if (info == Types.SQL_DATE) { + return container.textNode(object.toString()); + } else if (info == Types.SQL_TIME) { + final Time time = (Time) object; + // strip milliseconds if possible + if (time.getTime() % 1000 > 0) { + return container.textNode(timeFormatWithMillis.format(time)); + } + return container.textNode(timeFormat.format(time)); + } else if (info == Types.SQL_TIMESTAMP) { + return container.textNode(timestampFormat.format((Timestamp) object)); + } else if (info instanceof RowTypeInfo) { + if (reuse != null && reuse instanceof ObjectNode) { + return convertRow((ObjectNode) reuse, (RowTypeInfo) info, (Row) object); + } else { + return convertRow(null, (RowTypeInfo) info, (Row) object); + } + } else if (info instanceof ObjectArrayTypeInfo) { + if (reuse != null && reuse instanceof ArrayNode) { + return convertObjectArray((ArrayNode) reuse, ((ObjectArrayTypeInfo) info).getComponentInfo(), (Object[]) object); + } else { + return convertObjectArray(null, ((ObjectArrayTypeInfo) info).getComponentInfo(), (Object[]) object); + } + } else if (info instanceof BasicArrayTypeInfo) { + if (reuse != null && reuse instanceof ArrayNode) { + return convertObjectArray((ArrayNode) reuse, ((BasicArrayTypeInfo) info).getComponentInfo(), (Object[]) object); + } else { + return convertObjectArray(null, ((BasicArrayTypeInfo) info).getComponentInfo(), (Object[]) object); + } + } else if (info instanceof PrimitiveArrayTypeInfo && ((PrimitiveArrayTypeInfo) info).getComponentType() == Types.BYTE) { + return container.binaryNode((byte[]) object); + } else { + // for types that were specified without JSON schema + // e.g. POJOs + try { + return mapper.valueToTree(object); + } catch (IllegalArgumentException e) { + throw new IllegalStateException("Unsupported type information '" + info + "' for object: " + object, e); + } + } + } + + private ArrayNode convertObjectArray(ArrayNode reuse, TypeInformation info, Object[] array) { + if (reuse == null) { + reuse = mapper.createArrayNode(); + } else { + reuse.removeAll(); + } + + for (Object object : array) { + reuse.add(convert(reuse, null, info, object)); + } + return reuse; + } + + public Counter getCounter() { + return counter; + } + + public void setCounter(Counter counter) { + this.counter = counter; + } +} \ No newline at end of file diff --git a/kafka11/kafka11-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerKafka11JsonTableSink.java b/kafka11/kafka11-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerKafka11JsonTableSink.java new file mode 100644 index 000000000..89d1543a5 --- /dev/null +++ b/kafka11/kafka11-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/CustomerKafka11JsonTableSink.java @@ -0,0 +1,67 @@ +/** + * 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 com.dtstack.flink.sql.sink.kafka; + +import org.apache.flink.api.common.serialization.SerializationSchema; +import org.apache.flink.streaming.api.datastream.DataStream; +import org.apache.flink.streaming.api.functions.sink.SinkFunction; +import org.apache.flink.streaming.connectors.kafka.Kafka011TableSink; +import org.apache.flink.streaming.connectors.kafka.partitioner.FlinkKafkaPartitioner; +import org.apache.flink.table.api.TableSchema; +import org.apache.flink.table.utils.TableConnectorUtils; +import org.apache.flink.types.Row; + +import java.util.Optional; +import java.util.Properties; + +/** + * + * Reason: add schema info + * Date: 2019/4/8 + * Company: www.dtstack.com + * + * @author maqi + */ +public class CustomerKafka11JsonTableSink extends Kafka011TableSink { + + protected SerializationSchema schema; + + + public CustomerKafka11JsonTableSink(TableSchema schema, + String topic, + Properties properties, + Optional> partitioner, + SerializationSchema serializationSchema) { + + super(schema, topic, properties, partitioner, serializationSchema); + this.schema = serializationSchema; + } + + @Override + protected SinkFunction createKafkaProducer(String topic, Properties properties, SerializationSchema serializationSchema, Optional> optional) { + return new CustomerFlinkKafkaProducer011(topic, serializationSchema, properties); + } + + @Override + public void emitDataStream(DataStream dataStream) { + SinkFunction kafkaProducer = createKafkaProducer(topic, properties, schema, partitioner); + // always enable flush on checkpoint to achieve at-least-once if query runs with checkpointing enabled. + //kafkaProducer.setFlushOnCheckpoint(true); + dataStream.addSink(kafkaProducer).name(TableConnectorUtils.generateRuntimeName(this.getClass(), getFieldNames())); + } +} \ No newline at end of file diff --git a/kafka11/kafka11-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/KafkaProducer011.java b/kafka11/kafka11-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/KafkaProducer011.java deleted file mode 100644 index 8988da21c..000000000 --- a/kafka11/kafka11-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/KafkaProducer011.java +++ /dev/null @@ -1,65 +0,0 @@ -/** - * 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 com.dtstack.flink.sql.sink.kafka; - -import com.dtstack.flink.sql.format.SerializationMetricWrapper; -import com.dtstack.flink.sql.sink.kafka.serialization.CustomerKeyedSerializationSchema; -import org.apache.flink.api.common.functions.RuntimeContext; -import org.apache.flink.api.common.serialization.SerializationSchema - ; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.configuration.Configuration; -import org.apache.flink.streaming.connectors.kafka.FlinkKafkaProducer011; -import org.apache.flink.streaming.connectors.kafka.partitioner.FlinkKafkaPartitioner; -import org.apache.flink.types.Row; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Optional; -import java.util.Properties; - -/** - * Reason: - * Date: 2019/4/24 - * Company: www.dtstack.com - * - * @author maqi - */ -public class KafkaProducer011 extends FlinkKafkaProducer011> { - - private static final Logger LOG = LoggerFactory.getLogger(KafkaProducer011.class); - - private static final long serialVersionUID = 1L; - - private SerializationMetricWrapper serializationMetricWrapper; - - public KafkaProducer011(String topicId, SerializationSchema> serializationSchema, Properties producerConfig, Optional>> customPartitioner, String[] partitionKeys) { - super(topicId, new CustomerKeyedSerializationSchema((SerializationMetricWrapper)serializationSchema, partitionKeys), producerConfig, customPartitioner); - this.serializationMetricWrapper = (SerializationMetricWrapper) serializationSchema; - } - - @Override - public void open(Configuration configuration) throws Exception { - LOG.info("--KafkaProducer011 open--"); - RuntimeContext runtimeContext = getRuntimeContext(); - serializationMetricWrapper.setRuntimeContext(runtimeContext); - serializationMetricWrapper.initMetric(); - super.open(configuration); - } - -} \ No newline at end of file diff --git a/kafka11/kafka11-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/KafkaProducer011Factory.java b/kafka11/kafka11-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/KafkaProducer011Factory.java deleted file mode 100644 index 1fe8ac0c2..000000000 --- a/kafka11/kafka11-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/KafkaProducer011Factory.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.kafka; - -import com.dtstack.flink.sql.sink.kafka.table.KafkaSinkTableInfo; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.streaming.api.functions.sink.RichSinkFunction; -import org.apache.flink.streaming.connectors.kafka.partitioner.FlinkKafkaPartitioner; -import org.apache.flink.types.Row; - -import java.util.Optional; -import java.util.Properties; - -/** - * company: www.dtstack.com - * - * @author: toutian - * create: 2019/12/24 - */ -public class KafkaProducer011Factory extends AbstractKafkaProducerFactory { - - @Override - public RichSinkFunction> createKafkaProducer(KafkaSinkTableInfo kafkaSinkTableInfo, TypeInformation> typeInformation, - Properties properties, Optional>> partitioner, - String[] partitionKeys) { - return new KafkaProducer011(kafkaSinkTableInfo.getTopic(), createSerializationMetricWrapper(kafkaSinkTableInfo, typeInformation), properties, partitioner, partitionKeys); - } -} diff --git a/kafka11/kafka11-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/KafkaSink.java b/kafka11/kafka11-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/KafkaSink.java index f6e9d6529..5b0ac683f 100644 --- a/kafka11/kafka11-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/KafkaSink.java +++ b/kafka11/kafka11-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/KafkaSink.java @@ -18,8 +18,22 @@ package com.dtstack.flink.sql.sink.kafka; +import com.dtstack.flink.sql.sink.IStreamSinkGener; import com.dtstack.flink.sql.sink.kafka.table.KafkaSinkTableInfo; -import com.dtstack.flink.sql.table.AbstractTargetTableInfo; +import com.dtstack.flink.sql.table.TargetTableInfo; +import org.apache.flink.api.common.serialization.SerializationSchema; +import org.apache.flink.api.common.typeinfo.TypeInformation; +import org.apache.flink.api.java.tuple.Tuple2; +import org.apache.flink.api.java.typeutils.RowTypeInfo; +import org.apache.flink.api.java.typeutils.TupleTypeInfo; +import org.apache.flink.streaming.api.datastream.DataStream; +import org.apache.flink.streaming.connectors.kafka.KafkaTableSinkBase; +import org.apache.flink.streaming.connectors.kafka.partitioner.FlinkFixedPartitioner; +import org.apache.flink.streaming.connectors.kafka.partitioner.FlinkKafkaPartitioner; +import org.apache.flink.table.api.TableSchema; +import org.apache.flink.table.sinks.RetractStreamTableSink; +import org.apache.flink.table.sinks.TableSink; +import org.apache.flink.types.Row; import java.util.Optional; import java.util.Properties; @@ -34,23 +48,103 @@ * @modifyer maqi * */ -public class KafkaSink extends AbstractKafkaSink { +public class KafkaSink implements RetractStreamTableSink, IStreamSinkGener { + + protected String[] fieldNames; + + protected TypeInformation[] fieldTypes; + + protected String topic; + + protected int parallelism; + + protected Properties properties; + + /** Serialization schema for encoding records to Kafka. */ + protected SerializationSchema serializationSchema; + + /** The schema of the table. */ + private TableSchema schema; + + /** Partitioner to select Kafka partition for each item. */ + protected Optional> partitioner; + + @Override - public KafkaSink genStreamSink(AbstractTargetTableInfo targetTableInfo) { + public KafkaSink genStreamSink(TargetTableInfo targetTableInfo) { KafkaSinkTableInfo kafka11SinkTableInfo = (KafkaSinkTableInfo) targetTableInfo; - - Properties kafkaProperties = getKafkaProperties(kafka11SinkTableInfo); - this.tableName = kafka11SinkTableInfo.getName(); - this.updateMode = kafka11SinkTableInfo.getUpdateMode(); this.topic = kafka11SinkTableInfo.getTopic(); - this.partitioner = Optional.of(new CustomerFlinkPartition<>()); - this.partitionKeys = getPartitionKeys(kafka11SinkTableInfo); + + properties = new Properties(); + properties.setProperty("bootstrap.servers", kafka11SinkTableInfo.getBootstrapServers()); + + for (String key : kafka11SinkTableInfo.getKafkaParamKeys()) { + properties.setProperty(key, kafka11SinkTableInfo.getKafkaParam(key)); + } + this.partitioner = Optional.of(new FlinkFixedPartitioner<>()); this.fieldNames = kafka11SinkTableInfo.getFields(); - this.fieldTypes = getTypeInformations(kafka11SinkTableInfo); - this.schema = buildTableSchema(fieldNames, fieldTypes); - this.parallelism = kafka11SinkTableInfo.getParallelism(); - this.sinkOperatorName = SINK_OPERATOR_NAME_TPL.replace("${topic}", topic).replace("${table}", tableName); - this.kafkaProducer011 = new KafkaProducer011Factory().createKafkaProducer(kafka11SinkTableInfo, getOutputType(), kafkaProperties, partitioner, partitionKeys); + TypeInformation[] types = new TypeInformation[kafka11SinkTableInfo.getFields().length]; + for (int i = 0; i < kafka11SinkTableInfo.getFieldClasses().length; i++) { + types[i] = TypeInformation.of(kafka11SinkTableInfo.getFieldClasses()[i]); + } + this.fieldTypes = types; + + TableSchema.Builder schemaBuilder = TableSchema.builder(); + for (int i=0;i getRecordType() { + return new RowTypeInfo(fieldTypes, fieldNames); + } + + @Override + public void emitDataStream(DataStream> dataStream) { + KafkaTableSinkBase kafkaTableSink = new CustomerKafka11JsonTableSink( + schema, + topic, + properties, + partitioner, + serializationSchema + ); + + DataStream ds = dataStream.map((Tuple2 record) -> { + return record.f1; + }).returns(getOutputType().getTypeAt(1)).setParallelism(parallelism); + + kafkaTableSink.emitDataStream(ds); + } + + @Override + public TupleTypeInfo> getOutputType() { + return new TupleTypeInfo(org.apache.flink.table.api.Types.BOOLEAN(), new RowTypeInfo(fieldTypes, fieldNames)); + } + + @Override + public String[] getFieldNames() { + return fieldNames; + } + + @Override + public TypeInformation[] getFieldTypes() { + return fieldTypes; + } + + @Override + public TableSink>configure(String[] fieldNames, TypeInformation[] fieldTypes) { + this.fieldNames = fieldNames; + this.fieldTypes = fieldTypes; return this; } } diff --git a/kafka11/kafka11-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/table/KafkaSinkParser.java b/kafka11/kafka11-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/table/KafkaSinkParser.java new file mode 100644 index 000000000..ca4ffd5cf --- /dev/null +++ b/kafka11/kafka11-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/table/KafkaSinkParser.java @@ -0,0 +1,66 @@ +/* + * 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 com.dtstack.flink.sql.sink.kafka.table; + +import com.dtstack.flink.sql.table.AbsTableParser; +import com.dtstack.flink.sql.table.TableInfo; +import com.dtstack.flink.sql.util.MathUtil; + +import java.util.Map; +/** + * + * Date: 2018/12/18 + * Company: www.dtstack.com + * @author DocLi + * + * @modifyer maqi + * + */ +public class KafkaSinkParser extends AbsTableParser { + @Override + public TableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { + KafkaSinkTableInfo kafka11SinkTableInfo = new KafkaSinkTableInfo(); + kafka11SinkTableInfo.setName(tableName); + parseFieldsInfo(fieldsInfo, kafka11SinkTableInfo); + kafka11SinkTableInfo.setParallelism(MathUtil.getIntegerVal(props.get(KafkaSinkTableInfo.PARALLELISM_KEY.toLowerCase()))); + + if (props.get(KafkaSinkTableInfo.SINK_DATA_TYPE) != null) { + kafka11SinkTableInfo.setSinkDataType(props.get(KafkaSinkTableInfo.SINK_DATA_TYPE).toString()); + } + +// if (props.get(KafkaSinkTableInfo.FIELD_DELINITER) != null) { +// kafka11SinkTableInfo.setFieldDelimiter(props.get(KafkaSinkTableInfo.FIELD_DELINITER).toString()); +// } + + kafka11SinkTableInfo.setBootstrapServers(MathUtil.getString(props.get(KafkaSinkTableInfo.BOOTSTRAPSERVERS_KEY.toLowerCase()))); + kafka11SinkTableInfo.setTopic(MathUtil.getString(props.get(KafkaSinkTableInfo.TOPIC_KEY.toLowerCase()))); + + Integer parallelism = MathUtil.getIntegerVal(props.get(KafkaSinkTableInfo.PARALLELISM_KEY.toLowerCase())); + kafka11SinkTableInfo.setParallelism(parallelism); + + for (String key : props.keySet()) { + if (!key.isEmpty() && key.startsWith("kafka.")) { + kafka11SinkTableInfo.addKafkaParam(key.substring(6), props.get(key).toString()); + } + } + kafka11SinkTableInfo.check(); + + return kafka11SinkTableInfo; + } +} \ No newline at end of file diff --git a/kafka11/kafka11-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/table/KafkaSinkTableInfo.java b/kafka11/kafka11-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/table/KafkaSinkTableInfo.java new file mode 100644 index 000000000..46275da7b --- /dev/null +++ b/kafka11/kafka11-sink/src/main/java/com/dtstack/flink/sql/sink/kafka/table/KafkaSinkTableInfo.java @@ -0,0 +1,96 @@ +/* + * 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 com.dtstack.flink.sql.sink.kafka.table; + +import com.dtstack.flink.sql.table.TargetTableInfo; +import com.google.common.base.Preconditions; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +/** + * + * Date: 2018/12/18 + * Company: www.dtstack.com + * @author DocLi + * + * @modifyer maqi + * + */ +public class KafkaSinkTableInfo extends TargetTableInfo { + //version + private static final String CURR_TYPE = "kafka11"; + + public KafkaSinkTableInfo(){ + super.setType(CURR_TYPE); + } + public static final String BOOTSTRAPSERVERS_KEY = "bootstrapServers"; + + public static final String TOPIC_KEY = "topic"; + + private String bootstrapServers; + + public Map kafkaParam = new HashMap(); + + private String topic; + + + public void addKafkaParam(String key,String value){ + kafkaParam.put(key,value); + } + + public String getKafkaParam(String key){ + return kafkaParam.get(key); + } + + public Set getKafkaParamKeys(){ + return kafkaParam.keySet(); + } + + + public String getBootstrapServers() { + return bootstrapServers; + } + + public void setBootstrapServers(String bootstrapServers) { + this.bootstrapServers = bootstrapServers; + } + + public String getTopic() { + return topic; + } + + public void setTopic(String topic) { + this.topic = topic; + } + + + @Override + public boolean check() { + Preconditions.checkNotNull(bootstrapServers, "kafka of bootstrapServers is required"); + Preconditions.checkNotNull(topic, "kafka of topic is required"); + //Preconditions.checkNotNull(kafkaParam.get("groupId"), "kafka of groupId is required"); + return false; + } + + @Override + public String getType() { + return super.getType(); + } +} \ No newline at end of file diff --git a/kafka11/kafka11-sink/src/test/java/com/dtstack/flink/sql/sink/kafka/KafkaSinkTest.java b/kafka11/kafka11-sink/src/test/java/com/dtstack/flink/sql/sink/kafka/KafkaSinkTest.java deleted file mode 100644 index b4fde8efb..000000000 --- a/kafka11/kafka11-sink/src/test/java/com/dtstack/flink/sql/sink/kafka/KafkaSinkTest.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.dtstack.flink.sql.sink.kafka; - -import com.dtstack.flink.sql.sink.kafka.table.KafkaSinkTableInfo; -import com.google.common.collect.Sets; -import org.junit.Test; - -import static org.mockito.Mockito.*; - -public class KafkaSinkTest { - - @Test - public void mockGenStreamSink(){ - KafkaSinkTableInfo kafkaSinkTableInfo = mock(KafkaSinkTableInfo.class); - when(kafkaSinkTableInfo.getName()).thenReturn("roc"); - when(kafkaSinkTableInfo.getTopic()).thenReturn("topic"); - when(kafkaSinkTableInfo.getBootstrapServers()).thenReturn("localhost"); - when(kafkaSinkTableInfo.getKafkaParamKeys()).thenReturn(Sets.newHashSet("aa")); - when(kafkaSinkTableInfo.getKafkaParam("aa")).thenReturn("xx"); - when(kafkaSinkTableInfo.getPartitionKeys()).thenReturn(null); - when(kafkaSinkTableInfo.getFields()).thenReturn(new String[]{"aa"}); - when(kafkaSinkTableInfo.getFieldClasses()).thenReturn(new Class[]{String.class}); - when(kafkaSinkTableInfo.getParallelism()).thenReturn(1); - when(kafkaSinkTableInfo.getSinkDataType()).thenReturn("json"); - when(kafkaSinkTableInfo.getUpdateMode()).thenReturn("append"); - - KafkaSink kafkaSink = new KafkaSink(); - KafkaSink kafkaSinkSpy = spy(kafkaSink); - kafkaSinkSpy.genStreamSink(kafkaSinkTableInfo); - } -} diff --git a/kafka11/kafka11-source/pom.xml b/kafka11/kafka11-source/pom.xml index b19b58dac..90a6de20b 100644 --- a/kafka11/kafka11-source/pom.xml +++ b/kafka11/kafka11-source/pom.xml @@ -14,13 +14,7 @@ kafka11-source http://maven.apache.org - - - sql.source.kafka-base - com.dtstack.flink - 1.0-SNAPSHOT - - + @@ -35,7 +29,6 @@ shade - false org.slf4j @@ -69,14 +62,14 @@ - + - + diff --git a/kafka11/kafka11-source/src/main/java/com/dtstack/flink/sql/source/kafka/CustomerJsonDeserialization.java b/kafka11/kafka11-source/src/main/java/com/dtstack/flink/sql/source/kafka/CustomerJsonDeserialization.java new file mode 100644 index 000000000..b433804af --- /dev/null +++ b/kafka11/kafka11-source/src/main/java/com/dtstack/flink/sql/source/kafka/CustomerJsonDeserialization.java @@ -0,0 +1,289 @@ +/* + * 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 com.dtstack.flink.sql.source.kafka; + + +import com.dtstack.flink.sql.source.AbsDeserialization; +import com.dtstack.flink.sql.source.kafka.metric.KafkaTopicPartitionLagMetric; +import com.dtstack.flink.sql.table.TableInfo; +import org.apache.flink.api.common.typeinfo.TypeInformation; +import org.apache.flink.api.common.typeinfo.Types; +import org.apache.flink.api.java.typeutils.RowTypeInfo; +import com.google.common.base.Strings; +import org.apache.flink.metrics.MetricGroup; +import com.google.common.collect.Maps; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import org.apache.flink.streaming.connectors.kafka.internal.KafkaConsumerThread; +import org.apache.flink.streaming.connectors.kafka.internals.AbstractFetcher; +import org.apache.flink.types.Row; +import org.apache.kafka.clients.consumer.KafkaConsumer; +import org.apache.kafka.clients.consumer.internals.SubscriptionState; +import org.apache.kafka.common.TopicPartition; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.lang.reflect.Field; +import java.sql.Date; +import java.sql.Time; +import java.sql.Timestamp; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static com.dtstack.flink.sql.metric.MetricConstant.DT_PARTITION_GROUP; +import static com.dtstack.flink.sql.metric.MetricConstant.DT_TOPIC_GROUP; +import static com.dtstack.flink.sql.metric.MetricConstant.DT_TOPIC_PARTITION_LAG_GAUGE; + +/** + * json string parsing custom + * Date: 2018/09/18 + * Company: www.dtstack.com + * @author sishu.yss + */ + +public class CustomerJsonDeserialization extends AbsDeserialization { + + private static final Logger LOG = LoggerFactory.getLogger(CustomerJsonDeserialization.class); + + private static final long serialVersionUID = 2385115520960444192L; + + private static int dirtyDataFrequency = 1000; + + private final ObjectMapper objectMapper = new ObjectMapper(); + + /** Type information describing the result type. */ + private final TypeInformation typeInfo; + + /** Field names to parse. Indices match fieldTypes indices. */ + private final String[] fieldNames; + + /** Types to parse fields as. Indices match fieldNames indices. */ + private final TypeInformation[] fieldTypes; + + private AbstractFetcher fetcher; + + private boolean firstMsg = true; + + private Map nodeAndJsonNodeMapping = Maps.newHashMap(); + + private Map rowAndFieldMapping; + + private List fieldExtraInfos; + + public CustomerJsonDeserialization(TypeInformation typeInfo, Map rowAndFieldMapping, List fieldExtraInfos){ + this.typeInfo = typeInfo; + this.fieldNames = ((RowTypeInfo) typeInfo).getFieldNames(); + this.fieldTypes = ((RowTypeInfo) typeInfo).getFieldTypes(); + this.rowAndFieldMapping= rowAndFieldMapping; + this.fieldExtraInfos = fieldExtraInfos; + } + + @Override + public Row deserialize(byte[] message) throws IOException { + + if(firstMsg){ + try { + registerPtMetric(fetcher); + } catch (Exception e) { + LOG.error("register topic partition metric error.", e); + } + + firstMsg = false; + } + + try { + JsonNode root = objectMapper.readTree(message); + + if (numInRecord.getCount() % dirtyDataFrequency == 0) { + LOG.info(root.toString()); + } + + numInRecord.inc(); + numInBytes.inc(message.length); + + parseTree(root, null); + Row row = new Row(fieldNames.length); + + for (int i = 0; i < fieldNames.length; i++) { + JsonNode node = getIgnoreCase(fieldNames[i]); + TableInfo.FieldExtraInfo fieldExtraInfo = fieldExtraInfos.get(i); + + if (node == null) { + if (fieldExtraInfo != null && fieldExtraInfo.getNotNull()) { + throw new IllegalStateException("Failed to find field with name '" + + fieldNames[i] + "'."); + } else { + row.setField(i, null); + } + } else { + // Read the value as specified type + + Object value = convert(node, fieldTypes[i]); + row.setField(i, value); + } + } + + numInResolveRecord.inc(); + return row; + } catch (Exception e) { + //add metric of dirty data + if (dirtyDataCounter.getCount() % dirtyDataFrequency == 0) { + LOG.info("dirtyData: " + new String(message)); + LOG.error("" , e); + } + dirtyDataCounter.inc(); + return null; + }finally { + nodeAndJsonNodeMapping.clear(); + } + } + + public JsonNode getIgnoreCase(String key) { + String nodeMappingKey = rowAndFieldMapping.getOrDefault(key, key); + return nodeAndJsonNodeMapping.get(nodeMappingKey); + } + + private void parseTree(JsonNode jsonNode, String prefix){ + + if (jsonNode.isArray()) { + ArrayNode array = (ArrayNode) jsonNode; + for (int i = 0; i < array.size(); i++) { + JsonNode child = array.get(i); + String nodeKey = getNodeKey(prefix, i); + + if (child.isValueNode()) { + nodeAndJsonNodeMapping.put(nodeKey, child); + } else { + if (rowAndFieldMapping.containsValue(nodeKey)) { + nodeAndJsonNodeMapping.put(nodeKey, child); + } + parseTree(child, nodeKey); + } + } + return; + } + + Iterator iterator = jsonNode.fieldNames(); + while (iterator.hasNext()){ + String next = iterator.next(); + JsonNode child = jsonNode.get(next); + String nodeKey = getNodeKey(prefix, next); + + if (child.isValueNode()){ + nodeAndJsonNodeMapping.put(nodeKey, child); + }else if(child.isArray()){ + parseTree(child, nodeKey); + }else { + parseTree(child, nodeKey); + } + } + } + + private String getNodeKey(String prefix, String nodeName){ + if(Strings.isNullOrEmpty(prefix)){ + return nodeName; + } + + return prefix + "." + nodeName; + } + + private String getNodeKey(String prefix, int i) { + if (Strings.isNullOrEmpty(prefix)) { + return "[" + i + "]"; + } + + return prefix + "[" + i + "]"; + } + + public void setFetcher(AbstractFetcher fetcher) { + this.fetcher = fetcher; + } + + + protected void registerPtMetric(AbstractFetcher fetcher) throws Exception { + + Field consumerThreadField = fetcher.getClass().getSuperclass().getDeclaredField("consumerThread"); + consumerThreadField.setAccessible(true); + KafkaConsumerThread consumerThread = (KafkaConsumerThread) consumerThreadField.get(fetcher); + + Field hasAssignedPartitionsField = consumerThread.getClass().getDeclaredField("hasAssignedPartitions"); + hasAssignedPartitionsField.setAccessible(true); + + //wait until assignedPartitions + + boolean hasAssignedPartitions = (boolean) hasAssignedPartitionsField.get(consumerThread); + + if(!hasAssignedPartitions){ + throw new RuntimeException("wait 50 secs, but not assignedPartitions"); + } + + Field consumerField = consumerThread.getClass().getDeclaredField("consumer"); + consumerField.setAccessible(true); + + KafkaConsumer kafkaConsumer = (KafkaConsumer) consumerField.get(consumerThread); + Field subscriptionStateField = kafkaConsumer.getClass().getDeclaredField("subscriptions"); + subscriptionStateField.setAccessible(true); + + //topic partitions lag + SubscriptionState subscriptionState = (SubscriptionState) subscriptionStateField.get(kafkaConsumer); + Set assignedPartitions = subscriptionState.assignedPartitions(); + for(TopicPartition topicPartition : assignedPartitions){ + MetricGroup metricGroup = getRuntimeContext().getMetricGroup().addGroup(DT_TOPIC_GROUP, topicPartition.topic()) + .addGroup(DT_PARTITION_GROUP, topicPartition.partition() + ""); + metricGroup.gauge(DT_TOPIC_PARTITION_LAG_GAUGE, new KafkaTopicPartitionLagMetric(subscriptionState, topicPartition)); + } + + } + + private static String partitionLagMetricName(TopicPartition tp) { + return tp + ".records-lag"; + } + + private Object convert(JsonNode node, TypeInformation info) { + if (info.getTypeClass().equals(Types.BOOLEAN.getTypeClass())) { + return node.asBoolean(); + } else if (info.getTypeClass().equals(Types.STRING.getTypeClass())) { + return node.asText(); + } else if (info.getTypeClass().equals(Types.SQL_DATE.getTypeClass())) { + return Date.valueOf(node.asText()); + } else if (info.getTypeClass().equals(Types.SQL_TIME.getTypeClass())) { + // local zone + return Time.valueOf(node.asText()); + } else if (info.getTypeClass().equals(Types.SQL_TIMESTAMP.getTypeClass())) { + // local zone + return Timestamp.valueOf(node.asText()); + } else { + // for types that were specified without JSON schema + // e.g. POJOs + try { + return objectMapper.treeToValue(node, info.getTypeClass()); + } catch (JsonProcessingException e) { + throw new IllegalStateException("Unsupported type information '" + info + "' for node: " + node); + } + } + } + +} diff --git a/kafka11/kafka11-source/src/main/java/com/dtstack/flink/sql/source/kafka/CustomerKafka011Consumer.java b/kafka11/kafka11-source/src/main/java/com/dtstack/flink/sql/source/kafka/CustomerKafka011Consumer.java new file mode 100644 index 000000000..0a6c7cfca --- /dev/null +++ b/kafka11/kafka11-source/src/main/java/com/dtstack/flink/sql/source/kafka/CustomerKafka011Consumer.java @@ -0,0 +1,78 @@ +/* + * 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 com.dtstack.flink.sql.source.kafka; + +import com.dtstack.flink.sql.source.AbsDeserialization; +import org.apache.flink.metrics.MetricGroup; +import org.apache.flink.streaming.api.functions.AssignerWithPeriodicWatermarks; +import org.apache.flink.streaming.api.functions.AssignerWithPunctuatedWatermarks; +import org.apache.flink.streaming.api.functions.source.SourceFunction; +import org.apache.flink.streaming.api.operators.StreamingRuntimeContext; +import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer011; +import org.apache.flink.streaming.connectors.kafka.config.OffsetCommitMode; +import org.apache.flink.streaming.connectors.kafka.internals.AbstractFetcher; +import org.apache.flink.streaming.connectors.kafka.internals.KafkaTopicPartition; +import org.apache.flink.types.Row; +import org.apache.flink.util.SerializedValue; + + +import java.util.Arrays; +import java.util.Collections; +import java.util.Map; +import java.util.Properties; +import java.util.regex.Pattern; + +/** + * Reason: + * Date: 2018/10/19 + * Company: www.dtstack.com + * + * @author xuchao + */ + +public class CustomerKafka011Consumer extends FlinkKafkaConsumer011 { + + private static final long serialVersionUID = -2265366268827807739L; + + private CustomerJsonDeserialization customerJsonDeserialization; + + public CustomerKafka011Consumer(String topic, AbsDeserialization valueDeserializer, Properties props) { + super(Arrays.asList(topic.split(",")), valueDeserializer, props); + this.customerJsonDeserialization = (CustomerJsonDeserialization) valueDeserializer; + } + + public CustomerKafka011Consumer(Pattern subscriptionPattern, AbsDeserialization valueDeserializer, Properties props) { + super(subscriptionPattern, valueDeserializer, props); + this.customerJsonDeserialization = (CustomerJsonDeserialization) valueDeserializer; + } + + @Override + public void run(SourceContext sourceContext) throws Exception { + customerJsonDeserialization.setRuntimeContext(getRuntimeContext()); + customerJsonDeserialization.initMetric(); + super.run(sourceContext); + } + + @Override + protected AbstractFetcher createFetcher(SourceContext sourceContext, Map assignedPartitionsWithInitialOffsets, SerializedValue> watermarksPeriodic, SerializedValue> watermarksPunctuated, StreamingRuntimeContext runtimeContext, OffsetCommitMode offsetCommitMode, MetricGroup consumerMetricGroup, boolean useMetrics) throws Exception { + AbstractFetcher fetcher = super.createFetcher(sourceContext, assignedPartitionsWithInitialOffsets, watermarksPeriodic, watermarksPunctuated, runtimeContext, offsetCommitMode, consumerMetricGroup, useMetrics); + customerJsonDeserialization.setFetcher(fetcher); + return fetcher; + } +} \ No newline at end of file diff --git a/kafka11/kafka11-source/src/main/java/com/dtstack/flink/sql/source/kafka/KafkaConsumer011.java b/kafka11/kafka11-source/src/main/java/com/dtstack/flink/sql/source/kafka/KafkaConsumer011.java deleted file mode 100644 index 9323e7ffe..000000000 --- a/kafka11/kafka11-source/src/main/java/com/dtstack/flink/sql/source/kafka/KafkaConsumer011.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.source.kafka; - -import com.dtstack.flink.sql.format.DeserializationMetricWrapper; -import com.dtstack.flink.sql.source.kafka.deserialization.DtKafkaDeserializationSchemaWrapper; -import com.dtstack.flink.sql.source.kafka.deserialization.KafkaDeserializationMetricWrapper; -import com.dtstack.flink.sql.source.kafka.sample.OffsetFetcher; -import com.dtstack.flink.sql.source.kafka.sample.OffsetMap; -import com.dtstack.flink.sql.source.kafka.sample.SampleCalculateHelper; -import org.apache.commons.lang3.StringUtils; -import org.apache.flink.api.common.serialization.DeserializationSchema; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.metrics.MetricGroup; -import org.apache.flink.streaming.api.functions.AssignerWithPeriodicWatermarks; -import org.apache.flink.streaming.api.functions.AssignerWithPunctuatedWatermarks; -import org.apache.flink.streaming.api.operators.StreamingRuntimeContext; -import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer011; -import org.apache.flink.streaming.connectors.kafka.config.OffsetCommitMode; -import org.apache.flink.streaming.connectors.kafka.internals.AbstractFetcher; -import org.apache.flink.streaming.connectors.kafka.internals.KafkaTopicPartition; -import org.apache.flink.types.Row; -import org.apache.flink.util.SerializedValue; -import org.apache.kafka.clients.consumer.KafkaConsumer; -import org.apache.kafka.common.PartitionInfo; -import org.apache.kafka.common.TopicPartition; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.regex.Pattern; - - -/** - * Reason: - * Date: 2018/10/19 - * Company: www.dtstack.com - * - * @author xuchao - */ -public class KafkaConsumer011 extends FlinkKafkaConsumer011 implements OffsetFetcher { - - private final DeserializationMetricWrapper deserializationMetricWrapper; - - private String topic; - - private final Properties props; - - private final Long sampleSize; - - public KafkaConsumer011( - String topic, - Long sampleSize, - DeserializationMetricWrapper deserializationMetricWrapper, - Properties props) { - super( - Arrays.asList(StringUtils.split(topic, ",")), - new DtKafkaDeserializationSchemaWrapper<>(deserializationMetricWrapper), - props); - this.topic = topic; - this.props = props; - this.sampleSize = sampleSize; - this.deserializationMetricWrapper = deserializationMetricWrapper; - } - - public KafkaConsumer011( - Pattern subscriptionPattern, - Long sampleSize, - DeserializationMetricWrapper deserializationMetricWrapper, - Properties props) { - super( - subscriptionPattern, - new DtKafkaDeserializationSchemaWrapper<>(deserializationMetricWrapper), - props); - this.sampleSize = sampleSize; - this.props = props; - this.deserializationMetricWrapper = deserializationMetricWrapper; - } - - @Override - public void run(SourceContext sourceContext) throws Exception { - deserializationMetricWrapper.setRuntimeContext(getRuntimeContext()); - deserializationMetricWrapper.initMetric(); - super.run(sourceContext); - } - - @Override - protected AbstractFetcher createFetcher(SourceContext sourceContext, - Map assignedPartitionsWithInitialOffsets, - SerializedValue> watermarksPeriodic, - SerializedValue> watermarksPunctuated, - StreamingRuntimeContext runtimeContext, - OffsetCommitMode offsetCommitMode, - MetricGroup consumerMetricGroup, - boolean useMetrics) throws Exception { - final OffsetMap offsetMap = sampleSize > 0 ? seekOffset(props, topic) : new OffsetMap(); - Map rebuild; - - rebuild = - sampleSize > 0 - ? SampleCalculateHelper.rebuildAssignedPartitionsWithInitialOffsets( - offsetMap, sampleSize, assignedPartitionsWithInitialOffsets) - : assignedPartitionsWithInitialOffsets; - - AbstractFetcher fetcher = - super.createFetcher( - sourceContext, - rebuild, - watermarksPeriodic, - watermarksPunctuated, - runtimeContext, - offsetCommitMode, - consumerMetricGroup, - useMetrics); - ((KafkaDeserializationMetricWrapper) deserializationMetricWrapper).setFetcher(fetcher); - ((DtKafkaDeserializationSchemaWrapper) deserializer).setSpecificEndOffsets(offsetMap); - return fetcher; - } - - @Override - public TypeInformation getProducedType() { - DeserializationSchema deserializationSchema = deserializationMetricWrapper.getDeserializationSchema(); - return deserializationSchema.getProducedType(); - } - - @Override - public OffsetMap fetchOffset(KafkaConsumer consumer, String topic) { - OffsetMap offsetMap = new OffsetMap(); - - List topicPartitions = new ArrayList<>(); - - List partitionInfos = consumer.partitionsFor(topic); - - partitionInfos.forEach( - item -> topicPartitions.add(new TopicPartition(topic, item.partition()))); - - consumer.assign(topicPartitions); - consumer.poll(10 * 1000L); - - consumer.seekToEnd(topicPartitions); - topicPartitions.forEach( - item -> - offsetMap.setLatest( - new KafkaTopicPartition(topic, item.partition()), - consumer.position(item))); - - consumer.seekToBeginning(topicPartitions); - topicPartitions.forEach( - item -> - offsetMap.setEarliest( - new KafkaTopicPartition(topic, item.partition()), - consumer.position(item))); - - return offsetMap; - } -} \ No newline at end of file diff --git a/kafka11/kafka11-source/src/main/java/com/dtstack/flink/sql/source/kafka/KafkaConsumer011Factory.java b/kafka11/kafka11-source/src/main/java/com/dtstack/flink/sql/source/kafka/KafkaConsumer011Factory.java deleted file mode 100644 index 0f50e299e..000000000 --- a/kafka11/kafka11-source/src/main/java/com/dtstack/flink/sql/source/kafka/KafkaConsumer011Factory.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.source.kafka; - -import com.dtstack.flink.sql.format.DeserializationMetricWrapper; -import com.dtstack.flink.sql.source.kafka.table.KafkaSourceTableInfo; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumerBase; -import org.apache.flink.types.Row; -import org.apache.kafka.common.requests.IsolationLevel; - -import java.io.Serializable; -import java.util.Properties; -import java.util.regex.Pattern; - -/** - * company: www.dtstack.com - * create: 2019/12/24 - * @author: toutian - */ -public class KafkaConsumer011Factory extends AbstractKafkaConsumerFactory { - - @Override - public FlinkKafkaConsumerBase createKafkaTableSource(KafkaSourceTableInfo kafkaSourceTableInfo, TypeInformation typeInformation, Properties props) { - KafkaConsumer011 kafkaSrc; - if (kafkaSourceTableInfo.getTopicIsPattern()) { - DeserializationMetricWrapper deserMetricWrapper = createDeserializationMetricWrapper(kafkaSourceTableInfo, typeInformation, (Calculate & Serializable) (subscriptionState, tp) -> subscriptionState.partitionLag(tp, IsolationLevel.READ_UNCOMMITTED)); - kafkaSrc = - new KafkaConsumer011( - Pattern.compile(kafkaSourceTableInfo.getTopic()), - kafkaSourceTableInfo.getSampleSize(), - deserMetricWrapper, - props); - } else { - DeserializationMetricWrapper deserMetricWrapper = createDeserializationMetricWrapper(kafkaSourceTableInfo, typeInformation, (Calculate & Serializable) (subscriptionState, tp) -> subscriptionState.partitionLag(tp, IsolationLevel.READ_UNCOMMITTED)); - kafkaSrc = - new KafkaConsumer011( - kafkaSourceTableInfo.getTopic(), - kafkaSourceTableInfo.getSampleSize(), - deserMetricWrapper, - props); - } - return kafkaSrc; - } - -} diff --git a/kafka11/kafka11-source/src/main/java/com/dtstack/flink/sql/source/kafka/KafkaSource.java b/kafka11/kafka11-source/src/main/java/com/dtstack/flink/sql/source/kafka/KafkaSource.java index e23924f6e..8a552cc40 100644 --- a/kafka11/kafka11-source/src/main/java/com/dtstack/flink/sql/source/kafka/KafkaSource.java +++ b/kafka11/kafka11-source/src/main/java/com/dtstack/flink/sql/source/kafka/KafkaSource.java @@ -19,17 +19,27 @@ package com.dtstack.flink.sql.source.kafka; +import com.dtstack.flink.sql.source.IStreamSourceGener; import com.dtstack.flink.sql.source.kafka.table.KafkaSourceTableInfo; -import com.dtstack.flink.sql.table.AbstractSourceTableInfo; +import com.dtstack.flink.sql.table.SourceTableInfo; +import com.dtstack.flink.sql.util.DtStringUtil; +import com.dtstack.flink.sql.util.PluginUtil; +import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; import org.apache.flink.api.common.typeinfo.TypeInformation; +import org.apache.flink.api.java.typeutils.RowTypeInfo; import org.apache.flink.streaming.api.datastream.DataStreamSource; import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer011; +import org.apache.flink.streaming.connectors.kafka.internals.KafkaTopicPartition; import org.apache.flink.table.api.Table; import org.apache.flink.table.api.java.StreamTableEnvironment; import org.apache.flink.types.Row; + +import java.util.HashMap; +import java.util.Map; import java.util.Properties; +import java.util.regex.Pattern; /** * If eventtime field is specified, the default time field rowtime @@ -39,24 +49,80 @@ * @author sishu.yss */ -public class KafkaSource extends AbstractKafkaSource { +public class KafkaSource implements IStreamSourceGener

{ + + private static final String SOURCE_OPERATOR_NAME_TPL = "${topic}_${table}"; + + /** + * Get kafka data source, you need to provide the data field names, data types + * If you do not specify auto.offset.reset, the default use groupoffset + * + * @param sourceTableInfo + * @return + */ + @SuppressWarnings("rawtypes") + @Override + public Table genStreamSource(SourceTableInfo sourceTableInfo, StreamExecutionEnvironment env, StreamTableEnvironment tableEnv) { + + KafkaSourceTableInfo kafka011SourceTableInfo = (KafkaSourceTableInfo) sourceTableInfo; + String topicName = kafka011SourceTableInfo.getTopic(); + + Properties props = new Properties(); + props.setProperty("bootstrap.servers", kafka011SourceTableInfo.getBootstrapServers()); + if (DtStringUtil.isJosn(kafka011SourceTableInfo.getOffsetReset())){ + props.setProperty("auto.offset.reset", "none"); + } else { + props.setProperty("auto.offset.reset", kafka011SourceTableInfo.getOffsetReset()); + } + if (StringUtils.isNotBlank(kafka011SourceTableInfo.getGroupId())){ + props.setProperty("group.id", kafka011SourceTableInfo.getGroupId()); + } + // only required for Kafka 0.8 + //TODO props.setProperty("zookeeper.connect", kafka09SourceTableInfo.) + + TypeInformation[] types = new TypeInformation[kafka011SourceTableInfo.getFields().length]; + for (int i = 0; i < kafka011SourceTableInfo.getFieldClasses().length; i++) { + types[i] = TypeInformation.of(kafka011SourceTableInfo.getFieldClasses()[i]); + } - @Override - public Table genStreamSource(AbstractSourceTableInfo sourceTableInfo, StreamExecutionEnvironment env, StreamTableEnvironment tableEnv) { - KafkaSourceTableInfo kafkaSourceTableInfo = (KafkaSourceTableInfo) sourceTableInfo; - String topicName = kafkaSourceTableInfo.getTopic(); + TypeInformation typeInformation = new RowTypeInfo(types, kafka011SourceTableInfo.getFields()); - Properties kafkaProperties = getKafkaProperties(kafkaSourceTableInfo); - TypeInformation typeInformation = getRowTypeInformation(kafkaSourceTableInfo); - FlinkKafkaConsumer011 kafkaSrc = (FlinkKafkaConsumer011) new KafkaConsumer011Factory().createKafkaTableSource(kafkaSourceTableInfo, typeInformation, kafkaProperties); + FlinkKafkaConsumer011 kafkaSrc; + if (BooleanUtils.isTrue(kafka011SourceTableInfo.getTopicIsPattern())) { + kafkaSrc = new CustomerKafka011Consumer(Pattern.compile(topicName), + new CustomerJsonDeserialization(typeInformation, kafka011SourceTableInfo.getPhysicalFields(), kafka011SourceTableInfo.getFieldExtraInfoList()), props); + } else { + kafkaSrc = new CustomerKafka011Consumer(topicName, + new CustomerJsonDeserialization(typeInformation, kafka011SourceTableInfo.getPhysicalFields(), kafka011SourceTableInfo.getFieldExtraInfoList()), props); + } - String sourceOperatorName = generateOperatorName(sourceTableInfo.getName(), topicName); - DataStreamSource kafkaSource = env.addSource(kafkaSrc, sourceOperatorName, typeInformation); + //earliest,latest + if ("earliest".equalsIgnoreCase(kafka011SourceTableInfo.getOffsetReset())) { + kafkaSrc.setStartFromEarliest(); + } else if (DtStringUtil.isJosn(kafka011SourceTableInfo.getOffsetReset())) {// {"0":12312,"1":12321,"2":12312} + try { + Properties properties = PluginUtil.jsonStrToObject(kafka011SourceTableInfo.getOffsetReset(), Properties.class); + Map offsetMap = PluginUtil.ObjectToMap(properties); + Map specificStartupOffsets = new HashMap<>(); + for (Map.Entry entry : offsetMap.entrySet()) { + specificStartupOffsets.put(new KafkaTopicPartition(topicName, Integer.valueOf(entry.getKey())), Long.valueOf(entry.getValue().toString())); + } + kafkaSrc.setStartFromSpecificOffsets(specificStartupOffsets); + } catch (Exception e) { + throw new RuntimeException("not support offsetReset type:" + kafka011SourceTableInfo.getOffsetReset()); + } + } else { + kafkaSrc.setStartFromLatest(); + } - setParallelism(kafkaSourceTableInfo.getParallelism(), kafkaSource); - setStartPosition(kafkaSourceTableInfo.getOffsetReset(), topicName, kafkaSrc, () -> kafkaSrc.setStartFromTimestamp(kafkaSourceTableInfo.getTimestampOffset())); - String fields = StringUtils.join(kafkaSourceTableInfo.getFields(), ","); + String fields = StringUtils.join(kafka011SourceTableInfo.getFields(), ","); + String sourceOperatorName = SOURCE_OPERATOR_NAME_TPL.replace("${topic}", topicName).replace("${table}", sourceTableInfo.getName()); - return tableEnv.fromDataStream(kafkaSource, fields); - } + DataStreamSource kafkaSource = env.addSource(kafkaSrc, sourceOperatorName, typeInformation); + Integer parallelism = kafka011SourceTableInfo.getParallelism(); + if (parallelism != null) { + kafkaSource.setParallelism(parallelism); + } + return tableEnv.fromDataStream(kafkaSource, fields); + } } diff --git a/kafka11/kafka11-source/src/main/java/com/dtstack/flink/sql/source/kafka/metric/KafkaTopicPartitionLagMetric.java b/kafka11/kafka11-source/src/main/java/com/dtstack/flink/sql/source/kafka/metric/KafkaTopicPartitionLagMetric.java new file mode 100644 index 000000000..7059690f8 --- /dev/null +++ b/kafka11/kafka11-source/src/main/java/com/dtstack/flink/sql/source/kafka/metric/KafkaTopicPartitionLagMetric.java @@ -0,0 +1,30 @@ +package com.dtstack.flink.sql.source.kafka.metric; + +import org.apache.flink.metrics.Gauge; +import org.apache.kafka.clients.consumer.internals.SubscriptionState; +import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.requests.IsolationLevel; + +/** + * Reason: + * Date: 2018/10/24 + * Company: www.dtstack.com + * @author xuchao + */ + +public class KafkaTopicPartitionLagMetric implements Gauge { + + private SubscriptionState subscriptionState; + + private TopicPartition tp; + + public KafkaTopicPartitionLagMetric(SubscriptionState subscriptionState, TopicPartition tp){ + this.subscriptionState = subscriptionState; + this.tp = tp; + } + + @Override + public Long getValue() { + return subscriptionState.partitionLag(tp, IsolationLevel.READ_UNCOMMITTED); + } +} diff --git a/kafka11/kafka11-source/src/main/java/com/dtstack/flink/sql/source/kafka/table/KafkaSourceParser.java b/kafka11/kafka11-source/src/main/java/com/dtstack/flink/sql/source/kafka/table/KafkaSourceParser.java new file mode 100644 index 000000000..07e12b0c0 --- /dev/null +++ b/kafka11/kafka11-source/src/main/java/com/dtstack/flink/sql/source/kafka/table/KafkaSourceParser.java @@ -0,0 +1,101 @@ +/* + * 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 com.dtstack.flink.sql.source.kafka.table; + +import com.dtstack.flink.sql.table.AbsSourceParser; +import com.dtstack.flink.sql.table.TableInfo; +import com.dtstack.flink.sql.util.ClassUtil; +import com.dtstack.flink.sql.util.MathUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Reason: + * Date: 2018/09/18 + * Company: www.dtstack.com + * @author sishu.yss + */ + +public class KafkaSourceParser extends AbsSourceParser { + + private static final Logger LOG = LoggerFactory.getLogger(KafkaSourceParser.class); + + private static final String KAFKA_NEST_FIELD_KEY = "nestFieldKey"; + + private static Pattern kafkaNestFieldKeyPattern = Pattern.compile("(?i)((@*\\S+\\.)*\\S+)\\s+(\\w+)\\s+AS\\s+(\\w+)(\\s+NOT\\s+NULL)?$"); + + static { + keyPatternMap.put(KAFKA_NEST_FIELD_KEY, kafkaNestFieldKeyPattern); + + keyHandlerMap.put(KAFKA_NEST_FIELD_KEY, KafkaSourceParser::dealNestField); + } + + /** + * add parser for alias field + * @param matcher + * @param tableInfo + */ + static void dealNestField(Matcher matcher, TableInfo tableInfo) { + String physicalField = matcher.group(1); + String fieldType = matcher.group(3); + String mappingField = matcher.group(4); + Class fieldClass= ClassUtil.stringConvertClass(fieldType); + boolean notNull = matcher.group(5) != null; + TableInfo.FieldExtraInfo fieldExtraInfo = new TableInfo.FieldExtraInfo(); + fieldExtraInfo.setNotNull(notNull); + + tableInfo.addPhysicalMappings(mappingField, physicalField); + tableInfo.addField(mappingField); + tableInfo.addFieldClass(fieldClass); + tableInfo.addFieldType(fieldType); + tableInfo.addFieldExtraInfo(fieldExtraInfo); + if(LOG.isInfoEnabled()){ + LOG.info(physicalField + "--->" + mappingField + " Class: " + fieldClass.toString()); + } + } + + @Override + public TableInfo getTableInfo(String tableName, String fieldsInfo, Map props) throws Exception { + + KafkaSourceTableInfo kafka11SourceTableInfo = new KafkaSourceTableInfo(); + kafka11SourceTableInfo.setName(tableName); + parseFieldsInfo(fieldsInfo, kafka11SourceTableInfo); + + kafka11SourceTableInfo.setParallelism(MathUtil.getIntegerVal(props.get(KafkaSourceTableInfo.PARALLELISM_KEY.toLowerCase()))); + String bootstrapServer = MathUtil.getString(props.get(KafkaSourceTableInfo.BOOTSTRAPSERVERS_KEY.toLowerCase())); + if (bootstrapServer == null || bootstrapServer.trim().equals("")){ + throw new Exception("BootstrapServers can not be empty!"); + } else { + kafka11SourceTableInfo.setBootstrapServers(bootstrapServer); + } + kafka11SourceTableInfo.setGroupId(MathUtil.getString(props.get(KafkaSourceTableInfo.GROUPID_KEY.toLowerCase()))); + kafka11SourceTableInfo.setTopic(MathUtil.getString(props.get(KafkaSourceTableInfo.TOPIC_KEY.toLowerCase()))); + kafka11SourceTableInfo.setOffsetReset(MathUtil.getString(props.get(KafkaSourceTableInfo.OFFSETRESET_KEY.toLowerCase()))); + kafka11SourceTableInfo.setTopicIsPattern(MathUtil.getBoolean(props.get(KafkaSourceTableInfo.TOPICISPATTERN_KEY.toLowerCase()))); + kafka11SourceTableInfo.setTimeZone(MathUtil.getString(props.get(KafkaSourceTableInfo.TIME_ZONE_KEY.toLowerCase()))); + kafka11SourceTableInfo.check(); + return kafka11SourceTableInfo; + } +} diff --git a/kafka11/kafka11-source/src/main/java/com/dtstack/flink/sql/source/kafka/table/KafkaSourceTableInfo.java b/kafka11/kafka11-source/src/main/java/com/dtstack/flink/sql/source/kafka/table/KafkaSourceTableInfo.java new file mode 100644 index 000000000..7a166695b --- /dev/null +++ b/kafka11/kafka11-source/src/main/java/com/dtstack/flink/sql/source/kafka/table/KafkaSourceTableInfo.java @@ -0,0 +1,132 @@ +/* + * 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 com.dtstack.flink.sql.source.kafka.table; + +import com.dtstack.flink.sql.table.SourceTableInfo; +import com.google.common.base.Preconditions; + +/** + * Reason: + * Date: 2018/09/18 + * Company: www.dtstack.com + * + * @author sishu.yss + */ + +public class KafkaSourceTableInfo extends SourceTableInfo { + + //version + private static final String CURR_TYPE = "kafka11"; + + public static final String BOOTSTRAPSERVERS_KEY = "bootstrapServers"; + + public static final String TOPIC_KEY = "topic"; + + public static final String GROUPID_KEY = "groupId"; + + public static final String OFFSETRESET_KEY = "offsetReset"; + + public static final String TOPICISPATTERN_KEY = "topicIsPattern"; + + private String bootstrapServers; + + private String topic; + + private String groupId; + + private Boolean topicIsPattern = false; + + public Boolean getTopicIsPattern() { + return topicIsPattern; + } + + public void setTopicIsPattern(Boolean topicIsPattern) { + if (topicIsPattern == null) return; + + this.topicIsPattern = topicIsPattern; + } + + //latest, earliest + private String offsetReset = "latest"; + + private String offset; + + public KafkaSourceTableInfo() { + super.setType(CURR_TYPE); + } + + + public String getBootstrapServers() { + return bootstrapServers; + } + + public void setBootstrapServers(String bootstrapServers) { + this.bootstrapServers = bootstrapServers; + } + + public String getTopic() { + return topic; + } + + public void setTopic(String topic) { + this.topic = topic; + } + + public String getGroupId() { + return groupId; + } + + public void setGroupId(String groupId) { + this.groupId = groupId; + } + + public String getOffsetReset() { + return offsetReset; + } + + public void setOffsetReset(String offsetReset) { + if (offsetReset == null) { + return; + } + + this.offsetReset = offsetReset; + } + + public String getOffset() { + return offset; + } + + public void setOffset(String offset) { + this.offset = offset; + } + + @Override + public boolean check() { + Preconditions.checkNotNull(bootstrapServers, "kafka of bootstrapServers is required"); + Preconditions.checkNotNull(topic, "kafka of topic is required"); + return false; + } + + @Override + public String getType() { +// return super.getType() + SOURCE_SUFFIX; + return super.getType(); + } +} diff --git a/kafka11/kafka11-source/src/test/java/com/dtstack/flink/sql/source/kafka/KafkaSourceTest.java b/kafka11/kafka11-source/src/test/java/com/dtstack/flink/sql/source/kafka/KafkaSourceTest.java deleted file mode 100644 index 396b69550..000000000 --- a/kafka11/kafka11-source/src/test/java/com/dtstack/flink/sql/source/kafka/KafkaSourceTest.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.dtstack.flink.sql.source.kafka; - -import com.dtstack.flink.sql.source.kafka.table.KafkaSourceTableInfo; -import com.google.common.collect.Sets; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.streaming.api.datastream.DataStreamSource; -import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; -import org.apache.flink.streaming.api.functions.source.SourceFunction; -import org.apache.flink.table.api.java.StreamTableEnvironment; -import org.junit.Test; -import org.mockito.ArgumentMatcher; - -import static org.mockito.Mockito.*; - -public class KafkaSourceTest { - - @Test - public void mockGenStreamSource(){ - KafkaSourceTableInfo kafkaSourceTableInfo = mock(KafkaSourceTableInfo.class); - when(kafkaSourceTableInfo.getTopic()).thenReturn("topic"); - when(kafkaSourceTableInfo.getGroupId()).thenReturn("groupId"); - when(kafkaSourceTableInfo.getBootstrapServers()).thenReturn("localhost"); - when(kafkaSourceTableInfo.getKafkaParamKeys()).thenReturn(Sets.newHashSet("aa")); - when(kafkaSourceTableInfo.getKafkaParam("aa")).thenReturn("xx"); - when(kafkaSourceTableInfo.getFields()).thenReturn(new String[]{"aa"}); - when(kafkaSourceTableInfo.getFieldClasses()).thenReturn(new Class[]{String.class}); - when(kafkaSourceTableInfo.getParallelism()).thenReturn(1); - when(kafkaSourceTableInfo.getName()).thenReturn("roc"); - when(kafkaSourceTableInfo.getOffsetReset()).thenReturn("1"); - when(kafkaSourceTableInfo.getSourceDataType()).thenReturn("json"); - - DataStreamSource dataStreamSource = mock(DataStreamSource.class); - - StreamExecutionEnvironment env = mock(StreamExecutionEnvironment.class); - when(env.addSource(argThat(new ArgumentMatcher>() { - @Override - public boolean matches(SourceFunction sourceFunction) { - return true; - } - }), argThat(new ArgumentMatcher() { - @Override - public boolean matches(String s) { - return true; - } - }), argThat(new ArgumentMatcher() { - @Override - public boolean matches(TypeInformation typeInformation) { - return true; - } - }))).thenReturn(dataStreamSource); - - StreamTableEnvironment tableEnv = mock(StreamTableEnvironment.class); - - KafkaSource kafkaSource = new KafkaSource(); - KafkaSource kafkaSourceSpy = spy(kafkaSource); -// kafkaSourceSpy.genStreamSource(kafkaSourceTableInfo, env, tableEnv); - } - -} - diff --git a/kafka11/kafka11-source/src/test/java/com/dtstack/flinkx/AppTest.java b/kafka11/kafka11-source/src/test/java/com/dtstack/flinkx/AppTest.java new file mode 100644 index 000000000..33a0233ac --- /dev/null +++ b/kafka11/kafka11-source/src/test/java/com/dtstack/flinkx/AppTest.java @@ -0,0 +1,58 @@ +/* + * 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 com.dtstack.flinkx; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +/** + * Unit test for simple App. + */ +public class AppTest + extends TestCase +{ + /** + * Create the test case + * + * @param testName name of the test case + */ + public AppTest( String testName ) + { + super( testName ); + } + + /** + * @return the suite of tests being tested + */ + public static Test suite() + { + return new TestSuite( AppTest.class ); + } + + /** + * Rigourous Test :-) + */ + public void testApp() + { + assertTrue( true ); + } +} diff --git a/kafka11/pom.xml b/kafka11/pom.xml index 9fb4b61d7..90972fa82 100644 --- a/kafka11/pom.xml +++ b/kafka11/pom.xml @@ -24,6 +24,13 @@ ${flink.version} + + junit + junit + 3.8.1 + test + + com.dtstack.flink sql.core diff --git a/kingbase/kingbase-side/kingbase-all-side/pom.xml b/kingbase/kingbase-side/kingbase-all-side/pom.xml deleted file mode 100644 index 8f5d6905c..000000000 --- a/kingbase/kingbase-side/kingbase-all-side/pom.xml +++ /dev/null @@ -1,87 +0,0 @@ - - - - sql.side.kingbase - com.dtstack.flink - 1.0-SNAPSHOT - ../pom.xml - - 4.0.0 - kingbase-all-side - jar - sql.side.all.kingbase - - - - com.dtstack.flink - sql.side.kingbase.core - 1.0-SNAPSHOT - - - - - - - org.apache.maven.plugins - maven-shade-plugin - 3.2.1 - - - package - - shade - - - false - - - - - - - - *:* - - META-INF/*.SF - META-INF/*.DSA - META-INF/*.RSA - - - - - - - - - - maven-antrun-plugin - 1.2 - - - copy-resources - - package - - run - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/kingbase/kingbase-side/kingbase-all-side/src/main/java/com/dtstack/flink/sql/side/kingbase/KingbaseAllReqRow.java b/kingbase/kingbase-side/kingbase-all-side/src/main/java/com/dtstack/flink/sql/side/kingbase/KingbaseAllReqRow.java deleted file mode 100644 index e328ae710..000000000 --- a/kingbase/kingbase-side/kingbase-all-side/src/main/java/com/dtstack/flink/sql/side/kingbase/KingbaseAllReqRow.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.kingbase; - -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.rdb.all.AbstractRdbAllReqRow; -import com.dtstack.flink.sql.util.DtStringUtil; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.shaded.guava18.com.google.common.collect.Maps; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.sql.Connection; -import java.sql.DriverManager; -import java.util.List; -import java.util.Map; - -/** - * Date: 2020/9/11 - * Company: www.dtstack.com - * - * @author tiezhu - */ -public class KingbaseAllReqRow extends AbstractRdbAllReqRow { - - private static final long serialVersionUID = 2021683212163965319L; - - private static final Logger LOG = LoggerFactory.getLogger(KingbaseAllReqRow.class); - - private static final String KINGBASE_DRIVER = "com.kingbase8.Driver"; - - public KingbaseAllReqRow(RowTypeInfo rowTypeInfo, - JoinInfo joinInfo, - List outFieldInfoList, - AbstractSideTableInfo sideTableInfo) { - super(new KingbaseAllSideInfo(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo)); - } - - @Override - public Connection getConn(String dbUrl, String userName, String password) { - try { - Class.forName(KINGBASE_DRIVER); - //add param useCursorFetch=true - Map addParams = Maps.newHashMap(); - addParams.put("useCursorFetch", "true"); - String targetDbUrl = DtStringUtil.addJdbcParam(dbUrl, addParams, true); - return DriverManager.getConnection(targetDbUrl, userName, password); - } catch (Exception e) { - LOG.error("kingbase get connection error", e); - throw new RuntimeException("kingbase get connect error", e); - } - } -} diff --git a/kingbase/kingbase-side/kingbase-all-side/src/main/java/com/dtstack/flink/sql/side/kingbase/KingbaseAllSideInfo.java b/kingbase/kingbase-side/kingbase-all-side/src/main/java/com/dtstack/flink/sql/side/kingbase/KingbaseAllSideInfo.java deleted file mode 100644 index 22cb5c95a..000000000 --- a/kingbase/kingbase-side/kingbase-all-side/src/main/java/com/dtstack/flink/sql/side/kingbase/KingbaseAllSideInfo.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.kingbase; - -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.rdb.all.RdbAllSideInfo; -import com.dtstack.flink.sql.side.rdb.table.RdbSideTableInfo; -import com.dtstack.flink.sql.util.DtStringUtil; -import org.apache.flink.api.java.typeutils.RowTypeInfo; - -import java.util.List; - -/** - * Date: 2020/9/11 - * Company: www.dtstack.com - * - * @author tiezhu - */ -public class KingbaseAllSideInfo extends RdbAllSideInfo { - - private static final long serialVersionUID = 3486920874840522682L; - - public KingbaseAllSideInfo(RowTypeInfo rowTypeInfo, - JoinInfo joinInfo, - List outFieldInfoList, - AbstractSideTableInfo sideTableInfo) { - super(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); - } - - @Override - public String getTableName(RdbSideTableInfo rdbSideTableInfo) { - return DtStringUtil.getTableFullPath(rdbSideTableInfo.getSchema(), rdbSideTableInfo.getTableName()); - } -} diff --git a/kingbase/kingbase-side/kingbase-all-side/src/test/java/com/dtstack/flink/sql/side/kingbase/KingbaseAllReqRowTest.java b/kingbase/kingbase-side/kingbase-all-side/src/test/java/com/dtstack/flink/sql/side/kingbase/KingbaseAllReqRowTest.java deleted file mode 100644 index 62c33aadd..000000000 --- a/kingbase/kingbase-side/kingbase-all-side/src/test/java/com/dtstack/flink/sql/side/kingbase/KingbaseAllReqRowTest.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.dtstack.flink.sql.side.kingbase; - -import com.dtstack.flink.sql.side.rdb.all.RdbAllReqRowTestBase; - -public class KingbaseAllReqRowTest extends RdbAllReqRowTestBase { - - @Override - protected void init() { - clazz = KingbaseAllReqRow.class; - } - -} \ No newline at end of file diff --git a/kingbase/kingbase-side/kingbase-async-side/pom.xml b/kingbase/kingbase-side/kingbase-async-side/pom.xml deleted file mode 100644 index 2100696c3..000000000 --- a/kingbase/kingbase-side/kingbase-async-side/pom.xml +++ /dev/null @@ -1,86 +0,0 @@ - - - - sql.side.kingbase - com.dtstack.flink - 1.0-SNAPSHOT - ../pom.xml - - 4.0.0 - kingbase-async-side - sql.side.async.kingbase - jar - - - - com.dtstack.flink - sql.side.kingbase.core - 1.0-SNAPSHOT - - - - - - - org.apache.maven.plugins - maven-shade-plugin - 3.2.1 - - - package - - shade - - - false - - - - - - - - *:* - - META-INF/*.SF - META-INF/*.DSA - META-INF/*.RSA - - - - - - - - - - maven-antrun-plugin - 1.2 - - - copy-resources - - package - - run - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/kingbase/kingbase-side/kingbase-async-side/src/main/java/com/dtstack/flink/sql/side/kingbase/KingbaseAsyncReqRow.java b/kingbase/kingbase-side/kingbase-async-side/src/main/java/com/dtstack/flink/sql/side/kingbase/KingbaseAsyncReqRow.java deleted file mode 100644 index a303509a8..000000000 --- a/kingbase/kingbase-side/kingbase-async-side/src/main/java/com/dtstack/flink/sql/side/kingbase/KingbaseAsyncReqRow.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.kingbase; - -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.rdb.async.RdbAsyncReqRow; -import com.dtstack.flink.sql.side.rdb.table.RdbSideTableInfo; -import io.vertx.core.json.JsonObject; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.configuration.Configuration; - -import java.util.List; - -/** - * Date: 2020/9/11 - * Company: www.dtstack.com - * - * @author tiezhu - */ -public class KingbaseAsyncReqRow extends RdbAsyncReqRow { - - private static final long serialVersionUID = -4614565210747028814L; - - public KingbaseAsyncReqRow(RowTypeInfo rowTypeInfo, - JoinInfo joinInfo, - List outFieldInfoList, - AbstractSideTableInfo sideTableInfo) { - super(new KingbaseAsyncSideInfo(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo)); - } - - private final static String KINGBASE_DRIVER = "com.kingbase8.Driver"; - - @Override - public void open(Configuration parameters) throws Exception { - super.open(parameters); - } - - @Override - public JsonObject buildJdbcConfig() { - JsonObject kingbaseClient = new JsonObject(); - RdbSideTableInfo rdbSideTableInfo = (RdbSideTableInfo) sideInfo.getSideTableInfo(); - kingbaseClient.put("url", rdbSideTableInfo.getUrl()) - .put("driver_class", KINGBASE_DRIVER) - .put("max_pool_size", rdbSideTableInfo.getAsyncPoolSize()) - .put("user", rdbSideTableInfo.getUserName()) - .put("password", rdbSideTableInfo.getPassword()) - .put("preferred_test_query", PREFERRED_TEST_QUERY_SQL) - .put("idle_connection_test_period", DEFAULT_IDLE_CONNECTION_TEST_PEROID) - .put("test_connection_on_checkin", DEFAULT_TEST_CONNECTION_ON_CHECKIN); - - return kingbaseClient; - } -} diff --git a/kingbase/kingbase-side/kingbase-async-side/src/main/java/com/dtstack/flink/sql/side/kingbase/KingbaseAsyncSideInfo.java b/kingbase/kingbase-side/kingbase-async-side/src/main/java/com/dtstack/flink/sql/side/kingbase/KingbaseAsyncSideInfo.java deleted file mode 100644 index 4e9a4c30f..000000000 --- a/kingbase/kingbase-side/kingbase-async-side/src/main/java/com/dtstack/flink/sql/side/kingbase/KingbaseAsyncSideInfo.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.kingbase; - -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.rdb.async.RdbAsyncSideInfo; -import com.dtstack.flink.sql.side.rdb.table.RdbSideTableInfo; -import com.dtstack.flink.sql.util.DtStringUtil; -import org.apache.flink.api.java.typeutils.RowTypeInfo; - -import java.util.List; - -/** - * Date: 2020/9/11 - * Company: www.dtstack.com - * - * @author tiezhu - */ -public class KingbaseAsyncSideInfo extends RdbAsyncSideInfo { - - private static final long serialVersionUID = -1893856733189188893L; - - public KingbaseAsyncSideInfo(RowTypeInfo rowTypeInfo, - JoinInfo joinInfo, - List outFieldInfoList, - AbstractSideTableInfo sideTableInfo) { - super(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); - } - - @Override - public String getTableName(RdbSideTableInfo rdbSideTableInfo) { - return DtStringUtil.getTableFullPath(rdbSideTableInfo.getSchema(), rdbSideTableInfo.getTableName()); - } -} diff --git a/kingbase/kingbase-side/kingbase-async-side/src/test/java/com/dtstack/flink/sql/side/kingbase/KingbaseAsyncReqRowTest.java b/kingbase/kingbase-side/kingbase-async-side/src/test/java/com/dtstack/flink/sql/side/kingbase/KingbaseAsyncReqRowTest.java deleted file mode 100644 index 66dbaa6b4..000000000 --- a/kingbase/kingbase-side/kingbase-async-side/src/test/java/com/dtstack/flink/sql/side/kingbase/KingbaseAsyncReqRowTest.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.dtstack.flink.sql.side.kingbase; - -import com.dtstack.flink.sql.side.rdb.async.RdbAsyncReqRowTestBase; - -public class KingbaseAsyncReqRowTest extends RdbAsyncReqRowTestBase { - - @Override - protected void init() { - clazz = KingbaseAsyncReqRow.class; - } - -} \ No newline at end of file diff --git a/kingbase/kingbase-side/kingbase-side-core/pom.xml b/kingbase/kingbase-side/kingbase-side-core/pom.xml deleted file mode 100644 index 1cffd92b1..000000000 --- a/kingbase/kingbase-side/kingbase-side-core/pom.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - sql.side.kingbase - com.dtstack.flink - 1.0-SNAPSHOT - ../pom.xml - - 4.0.0 - 1.0-SNAPSHOT - jar - sql.side.kingbase.core - kingbase-side-core - - \ No newline at end of file diff --git a/kingbase/kingbase-side/kingbase-side-core/src/main/java/com/dtstack/flink/sql/side/kingbase/table/KingbaseSideParser.java b/kingbase/kingbase-side/kingbase-side-core/src/main/java/com/dtstack/flink/sql/side/kingbase/table/KingbaseSideParser.java deleted file mode 100644 index 8153918d7..000000000 --- a/kingbase/kingbase-side/kingbase-side-core/src/main/java/com/dtstack/flink/sql/side/kingbase/table/KingbaseSideParser.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.kingbase.table; - -import com.dtstack.flink.sql.core.rdb.JdbcCheckKeys; -import com.dtstack.flink.sql.side.rdb.table.RdbSideParser; -import com.dtstack.flink.sql.table.AbstractTableInfo; - -import java.util.Map; - -/** - * Date: 2020/9/11 - * Company: www.dtstack.com - * - * @author tiezhu - */ -public class KingbaseSideParser extends RdbSideParser { - private static final String CURRENT_TYPE = "kingbase"; - - @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { - props.put(JdbcCheckKeys.DRIVER_NAME, "com.kingbase8.Driver"); - AbstractTableInfo kingbaseTableInfo = super.getTableInfo(tableName, fieldsInfo, props); - kingbaseTableInfo.setType(CURRENT_TYPE); - return kingbaseTableInfo; - } -} diff --git a/kingbase/kingbase-side/pom.xml b/kingbase/kingbase-side/pom.xml deleted file mode 100644 index 5348c397d..000000000 --- a/kingbase/kingbase-side/pom.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - sql.kingbase - com.dtstack.flink - 1.0-SNAPSHOT - - 4.0.0 - - sql.side.kingbase - pom - - kingbase-all-side - kingbase-async-side - kingbase-side-core - - - 1.0-SNAPSHOT - - - - - com.dtstack.flink - sql.side.rdb - ${rdb.side.version} - - - - - - com.dtstack.flink - sql.side.rdb - ${rdb.side.version} - test-jar - test - - - - \ No newline at end of file diff --git a/kingbase/kingbase-sink/pom.xml b/kingbase/kingbase-sink/pom.xml deleted file mode 100644 index 3d5dfa899..000000000 --- a/kingbase/kingbase-sink/pom.xml +++ /dev/null @@ -1,88 +0,0 @@ - - - - sql.kingbase - com.dtstack.flink - 1.0-SNAPSHOT - ../pom.xml - - 4.0.0 - kingbase-sink - jar - sql.sink.kingbase - - 1.0-SNAPSHOT - - - - - com.dtstack.flink - sql.sink.rdb - ${sql.sink.rdb.version} - - - - - - org.apache.maven.plugins - maven-shade-plugin - 3.2.1 - - - package - - shade - - - false - - - - - - - - *:* - - META-INF/*.SF - META-INF/*.DSA - META-INF/*.RSA - - - - - - - - - - maven-antrun-plugin - 1.2 - - - copy-resources - - package - - run - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/kingbase/kingbase-sink/src/main/java/com/dtstack/flink/sql/sink/kingbase/KingbaseDialect.java b/kingbase/kingbase-sink/src/main/java/com/dtstack/flink/sql/sink/kingbase/KingbaseDialect.java deleted file mode 100644 index 9da079f5e..000000000 --- a/kingbase/kingbase-sink/src/main/java/com/dtstack/flink/sql/sink/kingbase/KingbaseDialect.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.kingbase; - -import com.dtstack.flink.sql.sink.rdb.dialect.JDBCDialect; - -import java.util.Arrays; -import java.util.Optional; -import java.util.stream.Collectors; - -/** - * Date: 2020/09/10 - * Company: www.dtstack.com - * - * @author tiezhu - */ -public class KingbaseDialect implements JDBCDialect { - private static final long serialVersionUID = -8548141999909854264L; - - @Override - public boolean canHandle(String url) { - return url.startsWith("jdbc:kingbase"); - } - - @Override - public Optional defaultDriverName() { - return Optional.of("com.kingbase8.Driver"); - } - - @Override - public String quoteIdentifier(String identifier) { - return "\"" + identifier + "\""; - } - - @Override - public Optional getUpsertStatement(String schema, String tableName, String[] fieldNames, String[] uniqueKeyFields, boolean allReplace) { - String uniqueColumns = Arrays.stream(uniqueKeyFields) - .map(this::quoteIdentifier) - .collect(Collectors.joining(", ")); - - String updateClause = Arrays.stream(fieldNames) - .map(f -> quoteIdentifier(f) + "=EXCLUDED." + quoteIdentifier(f)) - .collect(Collectors.joining(", ")); - - return Optional.of(getInsertIntoStatement(schema, tableName, fieldNames, null) + - " ON CONFLICT (" + uniqueColumns + ")" + - " DO UPDATE SET " + updateClause - ); - } -} diff --git a/kingbase/kingbase-sink/src/main/java/com/dtstack/flink/sql/sink/kingbase/KingbaseSink.java b/kingbase/kingbase-sink/src/main/java/com/dtstack/flink/sql/sink/kingbase/KingbaseSink.java deleted file mode 100644 index a339767ba..000000000 --- a/kingbase/kingbase-sink/src/main/java/com/dtstack/flink/sql/sink/kingbase/KingbaseSink.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.kingbase; - -import com.dtstack.flink.sql.sink.IStreamSinkGener; -import com.dtstack.flink.sql.sink.rdb.AbstractRdbSink; -import com.dtstack.flink.sql.sink.rdb.JDBCOptions; -import com.dtstack.flink.sql.sink.rdb.format.JDBCUpsertOutputFormat; - -/** - * Date: 2020/09/10 - * Company: www.dtstack.com - * - * @author tiezhu - */ -public class KingbaseSink extends AbstractRdbSink implements IStreamSinkGener { - - private static final long serialVersionUID = 6999055592225653354L; - - public KingbaseSink() { - super(new KingbaseDialect()); - } - - @Override - public JDBCUpsertOutputFormat getOutputFormat() { - JDBCOptions jdbcOptions = JDBCOptions.builder() - .setDbUrl(dbUrl) - .setDialect(jdbcDialect) - .setUsername(userName) - .setPassword(password) - .setTableName(tableName) - .setSchema(schema) - .build(); - - return JDBCUpsertOutputFormat.builder() - .setOptions(jdbcOptions) - .setFieldNames(fieldNames) - .setFlushMaxSize(batchNum) - .setFlushIntervalMills(batchWaitInterval) - .setFieldTypes(sqlTypes) - .setKeyFields(primaryKeys) - .setAllReplace(allReplace) - .setUpdateMode(updateMode) - .setErrorLimit(errorLimit) - .build(); - } -} diff --git a/kingbase/kingbase-sink/src/main/java/com/dtstack/flink/sql/sink/kingbase/table/KingbaseSinkParser.java b/kingbase/kingbase-sink/src/main/java/com/dtstack/flink/sql/sink/kingbase/table/KingbaseSinkParser.java deleted file mode 100644 index a22d09004..000000000 --- a/kingbase/kingbase-sink/src/main/java/com/dtstack/flink/sql/sink/kingbase/table/KingbaseSinkParser.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.kingbase.table; - -import com.dtstack.flink.sql.core.rdb.JdbcCheckKeys; -import com.dtstack.flink.sql.sink.rdb.table.RdbSinkParser; -import com.dtstack.flink.sql.table.AbstractTableInfo; - -import java.util.Map; - -/** - * Date: 2020/09/10 - * Company: www.dtstack.com - * - * @author tiezhu - */ -public class KingbaseSinkParser extends RdbSinkParser { - private static final String CURRENT_TYPE = "kingbase"; - - @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { - props.put(JdbcCheckKeys.DRIVER_NAME, "com.kingbase8.Driver"); - AbstractTableInfo kingbaseTableInfo = super.getTableInfo(tableName, fieldsInfo, props); - kingbaseTableInfo.setType(CURRENT_TYPE); - return kingbaseTableInfo; - } -} diff --git a/kingbase/pom.xml b/kingbase/pom.xml deleted file mode 100644 index cdbdc8ebb..000000000 --- a/kingbase/pom.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - flink.sql - com.dtstack.flink - 1.0-SNAPSHOT - - 4.0.0 - - sql.kingbase - pom - - kingbase-sink - kingbase-side - - - - 8.2.0 - 1.0-SNAPSHOT - - - - - com.kingbase8 - kingbase8 - ${kingbase.connector.version} - - - - com.dtstack.flink - sql.core - ${sql.core.version} - provided - - - - - \ No newline at end of file diff --git a/kudu/kudu-side/kudu-all-side/pom.xml b/kudu/kudu-side/kudu-all-side/pom.xml index f1e351142..5c35d4cd9 100644 --- a/kudu/kudu-side/kudu-all-side/pom.xml +++ b/kudu/kudu-side/kudu-all-side/pom.xml @@ -70,14 +70,14 @@ - + - + diff --git a/kudu/kudu-side/kudu-all-side/src/main/java/com/dtstack/flink/sql/side/kudu/KuduAllReqRow.java b/kudu/kudu-side/kudu-all-side/src/main/java/com/dtstack/flink/sql/side/kudu/KuduAllReqRow.java index 3173f8b06..681f5faab 100644 --- a/kudu/kudu-side/kudu-all-side/src/main/java/com/dtstack/flink/sql/side/kudu/KuduAllReqRow.java +++ b/kudu/kudu-side/kudu-all-side/src/main/java/com/dtstack/flink/sql/side/kudu/KuduAllReqRow.java @@ -1,49 +1,32 @@ package com.dtstack.flink.sql.side.kudu; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.BaseAllReqRow; +import com.dtstack.flink.sql.side.AllReqRow; import com.dtstack.flink.sql.side.FieldInfo; import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.PredicateInfo; +import com.dtstack.flink.sql.side.SideTableInfo; import com.dtstack.flink.sql.side.kudu.table.KuduSideTableInfo; -import com.dtstack.flink.sql.side.kudu.utils.KuduUtil; -import com.dtstack.flink.sql.util.KrbUtils; -import com.dtstack.flink.sql.util.RowDataComplete; -import com.google.common.base.Preconditions; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; import org.apache.calcite.sql.JoinType; import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.lang3.StringUtils; import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.table.dataformat.BaseRow; -import org.apache.flink.table.dataformat.GenericRow; +import org.apache.flink.calcite.shaded.com.google.common.collect.Lists; +import org.apache.flink.calcite.shaded.com.google.common.collect.Maps; +import org.apache.flink.table.typeutils.TimeIndicatorTypeInfo; +import org.apache.flink.types.Row; import org.apache.flink.util.Collector; -import org.apache.hadoop.security.UserGroupInformation; +import org.apache.flink.util.Preconditions; import org.apache.kudu.ColumnSchema; import org.apache.kudu.Schema; -import org.apache.kudu.client.KuduClient; -import org.apache.kudu.client.KuduException; -import org.apache.kudu.client.KuduPredicate; -import org.apache.kudu.client.KuduScanner; -import org.apache.kudu.client.KuduTable; -import org.apache.kudu.client.PartialRow; -import org.apache.kudu.client.RowResult; -import org.apache.kudu.client.RowResultIterator; +import org.apache.kudu.Type; +import org.apache.kudu.client.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.IOException; -import java.security.PrivilegedAction; import java.sql.SQLException; -import java.util.Arrays; -import java.util.Calendar; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.sql.Timestamp; +import java.util.*; import java.util.concurrent.atomic.AtomicReference; -public class KuduAllReqRow extends BaseAllReqRow { +public class KuduAllReqRow extends AllReqRow { private static final long serialVersionUID = 6051774809356082219L; @@ -64,10 +47,37 @@ public class KuduAllReqRow extends BaseAllReqRow { private AtomicReference>>> cacheRef = new AtomicReference<>(); - public KuduAllReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { + public KuduAllReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, SideTableInfo sideTableInfo) { super(new KuduAllSideInfo(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo)); } + + @Override + public Row fillData(Row input, Object sideInput) { + Map cacheInfo = (Map) sideInput; + Row row = new Row(sideInfo.getOutFieldInfoList().size()); + for (Map.Entry entry : sideInfo.getInFieldIndex().entrySet()) { + Object obj = input.getField(entry.getValue()); + boolean isTimeIndicatorTypeInfo = TimeIndicatorTypeInfo.class.isAssignableFrom(sideInfo.getRowTypeInfo().getTypeAt(entry.getValue()).getClass()); + + //Type information for indicating event or processing time. However, it behaves like a regular SQL timestamp but is serialized as Long. + if (obj instanceof Timestamp && isTimeIndicatorTypeInfo) { + obj = ((Timestamp) obj).getTime(); + } + row.setField(entry.getKey(), obj); + } + + for (Map.Entry entry : sideInfo.getSideFieldNameIndex().entrySet()) { + if (cacheInfo == null) { + row.setField(entry.getKey(), null); + } else { + row.setField(entry.getKey(), cacheInfo.get(entry.getValue())); + } + } + + return row; + } + @Override protected void initCache() throws SQLException { Map>> newCache = Maps.newConcurrentMap(); @@ -83,16 +93,15 @@ protected void reloadCache() { loadData(newCache); cacheRef.set(newCache); - LOG.info("----- kudu all cacheRef reload end:{}", Calendar.getInstance()); + LOG.info("----- Mongo all cacheRef reload end:{}", Calendar.getInstance()); } @Override - public void flatMap(BaseRow input, Collector out) throws Exception { - GenericRow genericRow = (GenericRow) input; + public void flatMap(Row value, Collector out) throws Exception { List inputParams = Lists.newArrayList(); for (Integer conValIndex : sideInfo.getEqualValIndex()) { - Object equalObj = genericRow.getField(conValIndex); + Object equalObj = value.getField(conValIndex); if (equalObj == null) { out.collect(null); } @@ -103,15 +112,14 @@ public void flatMap(BaseRow input, Collector out) throws Exception { List> cacheList = cacheRef.get().get(key); if (CollectionUtils.isEmpty(cacheList)) { if (sideInfo.getJoinType() == JoinType.LEFT) { - BaseRow row = fillData(input, null); - RowDataComplete.collectBaseRow(out, row); + Row row = fillData(value, null); + out.collect(row); } return; } for (Map one : cacheList) { - BaseRow row = fillData(input, one); - RowDataComplete.collectBaseRow(out, row); + out.collect(fillData(value, one)); } } @@ -132,13 +140,13 @@ private void loadData(Map>> tmpCache) { LOG.warn("get conn fail, wait for 5 sec and try again, connInfo:" + connInfo); Thread.sleep(5 * 1000); } catch (InterruptedException e1) { - LOG.error("",e1); + e1.printStackTrace(); } } } //load data from table assert scanner != null; - String[] sideFieldNames = StringUtils.split(sideInfo.getSideSelectFields(), ","); + String[] sideFieldNames = sideInfo.getSideSelectFields().split(","); while (scanner.hasMoreRows()) { @@ -150,7 +158,7 @@ private void loadData(Map>> tmpCache) { String sideFieldName = sideFieldName1.trim(); ColumnSchema columnSchema = table.getSchema().getColumn(sideFieldName); if (null != columnSchema) { - oneRow.put(sideFieldName, result.getObject(sideFieldName)); + setMapValue(columnSchema.getType(), oneRow, sideFieldName, result); } } String cacheKey = buildKey(oneRow, sideInfo.getEqualFieldList()); @@ -169,6 +177,15 @@ private void loadData(Map>> tmpCache) { LOG.error("Error while closing scanner.", e); } } + //放置到close中关闭 每次刷新时间较长则可以选择在这里关闭 +// if (null != client) { +// try { +// client.close(); +// } catch (Exception e) { +// LOG.error("Error while closing client.", e); +// } +// } + } @@ -194,63 +211,57 @@ private String buildKey(Map val, List equalFieldList) { private KuduScanner getConn(KuduSideTableInfo tableInfo) { try { if (client == null) { + String kuduMasters = tableInfo.getKuduMasters(); String tableName = tableInfo.getTableName(); - client = getClient(tableInfo); + Integer workerCount = tableInfo.getWorkerCount(); + Integer defaultSocketReadTimeoutMs = tableInfo.getDefaultSocketReadTimeoutMs(); + Integer defaultOperationTimeoutMs = tableInfo.getDefaultOperationTimeoutMs(); + + Preconditions.checkNotNull(kuduMasters, "kuduMasters could not be null"); + + KuduClient.KuduClientBuilder kuduClientBuilder = new KuduClient.KuduClientBuilder(kuduMasters); + if (null != workerCount) { + kuduClientBuilder.workerCount(workerCount); + } + if (null != defaultSocketReadTimeoutMs) { + kuduClientBuilder.defaultSocketReadTimeoutMs(defaultSocketReadTimeoutMs); + } + + if (null != defaultOperationTimeoutMs) { + kuduClientBuilder.defaultOperationTimeoutMs(defaultOperationTimeoutMs); + } + client = kuduClientBuilder.build(); + if (!client.tableExists(tableName)) { throw new IllegalArgumentException("Table Open Failed , please check table exists"); } table = client.openTable(tableName); } Schema schema = table.getSchema(); + LOG.info("connect kudu is successed!"); KuduScanner.KuduScannerBuilder tokenBuilder = client.newScannerBuilder(table); return buildScanner(tokenBuilder, schema, tableInfo); - } catch (Exception e) { + } catch ( + Exception e) { LOG.error("connect kudu is error:" + e.getMessage()); - throw new RuntimeException(e); } + return null; } - private KuduClient getClient(KuduSideTableInfo tableInfo) throws IOException { - String kuduMasters = tableInfo.getKuduMasters(); - Integer workerCount = tableInfo.getWorkerCount(); - Integer defaultOperationTimeoutMs = tableInfo.getDefaultOperationTimeoutMs(); - Preconditions.checkNotNull(kuduMasters, "kuduMasters could not be null"); - - KuduClient.KuduClientBuilder kuduClientBuilder = new KuduClient.KuduClientBuilder(kuduMasters); - - if (null != workerCount) { - kuduClientBuilder.workerCount(workerCount); - } - - if (null != defaultOperationTimeoutMs) { - kuduClientBuilder.defaultOperationTimeoutMs(defaultOperationTimeoutMs); - } - - if (tableInfo.isEnableKrb()) { - UserGroupInformation ugi = KrbUtils.loginAndReturnUgi(tableInfo.getPrincipal(), tableInfo.getKeytab(), tableInfo.getKrb5conf()); - return ugi.doAs(new PrivilegedAction() { - @Override - public KuduClient run() { - return kuduClientBuilder.build(); - } - }); - } else { - return kuduClientBuilder.build(); - } - } /** * @param builder 创建AsyncKuduScanner对象 * @param schema kudu中表约束 * @param tableInfo AsyncKuduScanner的配置信息 * @return */ - private KuduScanner buildScanner(KuduScanner.KuduScannerBuilder builder, Schema schema, KuduSideTableInfo tableInfo) { + private KuduScanner buildScanner(KuduScanner.KuduScannerBuilder builder, Schema schema, KuduSideTableInfo + tableInfo) { Integer batchSizeBytes = tableInfo.getBatchSizeBytes(); Long limitNum = tableInfo.getLimitNum(); Boolean isFaultTolerant = tableInfo.getFaultTolerant(); //查询需要的字段 - String[] sideFieldNames = StringUtils.split(sideInfo.getSideSelectFields(), ","); + String[] sideFieldNames = sideInfo.getSideSelectFields().split(","); //主键过滤条件 主键最小值 String lowerBoundPrimaryKey = tableInfo.getLowerBoundPrimaryKey(); //主键过滤条件 主键最大值 @@ -268,17 +279,6 @@ private KuduScanner buildScanner(KuduScanner.KuduScannerBuilder builder, Schema if (null != isFaultTolerant) { builder.setFaultTolerant(isFaultTolerant); } - // 填充谓词信息 - List predicateInfoes = sideInfo.getSideTableInfo().getPredicateInfoes(); - if (predicateInfoes.size() > 0) { - predicateInfoes.stream().map(info -> { - KuduPredicate kuduPredicate = KuduUtil.buildKuduPredicate(schema, info); - if (null != kuduPredicate) { - builder.addPredicate(kuduPredicate); - } - return info; - }).count(); - } if (null != lowerBoundPrimaryKey && null != upperBoundPrimaryKey && null != primaryKeys) { List columnSchemas = schema.getPrimaryKeyColumns(); @@ -289,22 +289,96 @@ private KuduScanner buildScanner(KuduScanner.KuduScannerBuilder builder, Schema String[] primaryKey = splitString(primaryKeys); String[] lowerBounds = splitString(lowerBoundPrimaryKey); String[] upperBounds = splitString(upperBoundPrimaryKey); - PartialRow lowerPartialRow = schema.newPartialRow(); - PartialRow upperPartialRow = schema.newPartialRow(); for (int i = 0; i < primaryKey.length; i++) { Integer index = columnName.get(primaryKey[i]); - KuduUtil.primaryKeyRange(lowerPartialRow, columnSchemas.get(index).getType(), primaryKey[i], lowerBounds[i]); - KuduUtil.primaryKeyRange(upperPartialRow, columnSchemas.get(index).getType(), primaryKey[i], upperBounds[i]); + if (null != index) { + builder.lowerBound(primaryKeyRange(columnSchemas.get(index).getType(), primaryKey[i], lowerBounds[i], schema)); + builder.exclusiveUpperBound(primaryKeyRange(columnSchemas.get(index).getType(), primaryKey[i], upperBounds[i], schema)); + } } - builder.lowerBound(lowerPartialRow); - builder.exclusiveUpperBound(upperPartialRow); } List projectColumns = Arrays.asList(sideFieldNames); return builder.setProjectedColumnNames(projectColumns).build(); } private String[] splitString(String data) { - return StringUtils.split(data, ","); + return data.split(","); + } + + private PartialRow primaryKeyRange(Type type, String primaryKey, String value, Schema schema) { + PartialRow partialRow = schema.newPartialRow(); + switch (type) { + case STRING: + partialRow.addString(primaryKey, value); + break; + case FLOAT: + partialRow.addFloat(primaryKey, Float.valueOf(value)); + break; + case INT8: + partialRow.addByte(primaryKey, Byte.valueOf(value)); + break; + case INT16: + partialRow.addShort(primaryKey, Short.valueOf(value)); + break; + case INT32: + partialRow.addInt(primaryKey, Integer.valueOf(value)); + break; + case INT64: + partialRow.addLong(primaryKey, Long.valueOf(value)); + break; + case DOUBLE: + partialRow.addDouble(primaryKey, Double.valueOf(value)); + break; + case BOOL: + partialRow.addBoolean(primaryKey, Boolean.valueOf(value)); + break; + case UNIXTIME_MICROS: + partialRow.addTimestamp(primaryKey, Timestamp.valueOf(value)); + break; + case BINARY: + partialRow.addBinary(primaryKey, value.getBytes()); + break; + default: + throw new IllegalArgumentException("Illegal var type: " + type); + } + return partialRow; + } + + private void setMapValue(Type type, Map oneRow, String sideFieldName, RowResult result) { + switch (type) { + case STRING: + oneRow.put(sideFieldName, result.getString(sideFieldName)); + break; + case FLOAT: + oneRow.put(sideFieldName, result.getFloat(sideFieldName)); + break; + case INT8: + oneRow.put(sideFieldName, result.getFloat(sideFieldName)); + break; + case INT16: + oneRow.put(sideFieldName, result.getShort(sideFieldName)); + break; + case INT32: + oneRow.put(sideFieldName, result.getInt(sideFieldName)); + break; + case INT64: + oneRow.put(sideFieldName, result.getLong(sideFieldName)); + break; + case DOUBLE: + oneRow.put(sideFieldName, result.getDouble(sideFieldName)); + break; + case BOOL: + oneRow.put(sideFieldName, result.getBoolean(sideFieldName)); + break; + case UNIXTIME_MICROS: + oneRow.put(sideFieldName, result.getTimestamp(sideFieldName)); + break; + case BINARY: + oneRow.put(sideFieldName, result.getBinary(sideFieldName)); + break; + default: + throw new IllegalArgumentException("Illegal var type: " + type); + } } @Override diff --git a/kudu/kudu-side/kudu-all-side/src/main/java/com/dtstack/flink/sql/side/kudu/KuduAllSideInfo.java b/kudu/kudu-side/kudu-all-side/src/main/java/com/dtstack/flink/sql/side/kudu/KuduAllSideInfo.java index 1241a6f37..fd933a38a 100644 --- a/kudu/kudu-side/kudu-all-side/src/main/java/com/dtstack/flink/sql/side/kudu/KuduAllSideInfo.java +++ b/kudu/kudu-side/kudu-all-side/src/main/java/com/dtstack/flink/sql/side/kudu/KuduAllSideInfo.java @@ -2,27 +2,33 @@ import com.dtstack.flink.sql.side.FieldInfo; import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.BaseSideInfo; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.util.ParseUtils; +import com.dtstack.flink.sql.side.SideInfo; +import com.dtstack.flink.sql.side.SideTableInfo; +import com.dtstack.flink.sql.side.kudu.table.KuduSideTableInfo; +import org.apache.calcite.sql.SqlBasicCall; +import org.apache.calcite.sql.SqlKind; import org.apache.calcite.sql.SqlNode; import org.apache.commons.collections.CollectionUtils; import org.apache.flink.api.java.typeutils.RowTypeInfo; -import com.google.common.collect.Lists; +import org.apache.flink.calcite.shaded.com.google.common.collect.Lists; import java.util.List; -public class KuduAllSideInfo extends BaseSideInfo { +public class KuduAllSideInfo extends SideInfo { private static final long serialVersionUID = 9005389633060174746L; - public KuduAllSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { + public KuduAllSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, SideTableInfo sideTableInfo) { super(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); } @Override - public void buildEqualInfo(JoinInfo joinInfo, AbstractSideTableInfo sideTableInfo) { - // no use + public void buildEqualInfo(JoinInfo joinInfo, SideTableInfo sideTableInfo) { + KuduSideTableInfo kuduSideTableInfo = (KuduSideTableInfo) sideTableInfo; + + sqlCondition = "select ${selectField} from ${tableName} "; + sqlCondition = sqlCondition.replace("${tableName}", kuduSideTableInfo.getTableName()).replace("${selectField}", sideSelectFields); + System.out.println("---------side_exe_sql-----\n" + sqlCondition); } @Override @@ -55,7 +61,11 @@ public void parseSelectFields(JoinInfo joinInfo) { SqlNode conditionNode = joinInfo.getCondition(); List sqlNodeList = Lists.newArrayList(); - ParseUtils.parseAnd(conditionNode, sqlNodeList); + if (conditionNode.getKind() == SqlKind.AND) { + sqlNodeList.addAll(Lists.newArrayList(((SqlBasicCall) conditionNode).getOperands())); + } else { + sqlNodeList.add(conditionNode); + } for (SqlNode sqlNode : sqlNodeList) { dealOneEqualCon(sqlNode, sideTableName); diff --git a/kudu/kudu-side/kudu-all-side/src/test/java/com/dtstack/flink/sql/side/kudu/KuduAllReqRowTest.java b/kudu/kudu-side/kudu-all-side/src/test/java/com/dtstack/flink/sql/side/kudu/KuduAllReqRowTest.java deleted file mode 100644 index a68a3d926..000000000 --- a/kudu/kudu-side/kudu-all-side/src/test/java/com/dtstack/flink/sql/side/kudu/KuduAllReqRowTest.java +++ /dev/null @@ -1,189 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.kudu; - -import com.dtstack.flink.sql.side.BaseAllReqRow; -import com.dtstack.flink.sql.side.BaseSideInfo; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.kudu.table.KuduSideTableInfo; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import org.apache.calcite.sql.JoinType; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.table.dataformat.GenericRow; -import org.apache.flink.types.Row; -import org.apache.flink.util.Collector; -import org.apache.kudu.ColumnSchema; -import org.apache.kudu.Schema; -import org.apache.kudu.Type; -import org.apache.kudu.client.KuduClient; -import org.apache.kudu.client.KuduScanner; -import org.apache.kudu.client.KuduTable; -import org.apache.kudu.client.PartialRow; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import org.powermock.reflect.Whitebox; - -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicReference; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.powermock.api.mockito.PowerMockito.when; -import static org.powermock.api.mockito.PowerMockito.whenNew; -import static org.powermock.api.support.membermodification.MemberMatcher.constructor; -import static org.powermock.api.support.membermodification.MemberModifier.suppress; - -/** - * @author: chuixue - * @create: 2020-08-10 14:12 - * @description: - **/ -@RunWith(PowerMockRunner.class) -@PrepareForTest({ - KuduAllReqRow.class, - KuduAllSideInfo.class, - BaseAllReqRow.class, - KuduClient.KuduClientBuilder.class -}) -public class KuduAllReqRowTest { - - private KuduAllReqRow kuduAllReqRow; - private BaseSideInfo sideInfo = mock(BaseSideInfo.class); - private KuduClient client = mock(KuduClient.class); - - @Before - public void setUp() { - suppress(constructor(KuduAllSideInfo.class)); - suppress(constructor(BaseAllReqRow.class)); - kuduAllReqRow = new KuduAllReqRow(null, null, null, null); - } - - @Test - public void testReloadCache() throws Exception { - ColumnSchema columnSchema = mock(ColumnSchema.class); - List columnSchemas = Lists.newArrayList(); - columnSchemas.add(columnSchema); - PartialRow partialRow = mock(PartialRow.class); - Schema schema = mock(Schema.class); - KuduTable table = mock(KuduTable.class); - Whitebox.setInternalState(kuduAllReqRow, "sideInfo", sideInfo); - KuduSideTableInfo tableInfo = mock(KuduSideTableInfo.class); - KuduClient.KuduClientBuilder kuduClientBuilder = mock(KuduClient.KuduClientBuilder.class); - KuduScanner.KuduScannerBuilder tokenBuilder = mock(KuduScanner.KuduScannerBuilder.class); - KuduScanner scanner = mock(KuduScanner.class); - - when(columnSchema.getName()).thenReturn("mid"); - when(columnSchema.getType()).thenReturn(Type.STRING); - whenNew(KuduClient.KuduClientBuilder.class).withArguments("localhost").thenReturn(kuduClientBuilder); - when(kuduClientBuilder.build()).thenReturn(client); - when(client.tableExists("tablename")).thenReturn(true); - when(client.openTable("tablename")).thenReturn(table); - when(tokenBuilder.setProjectedColumnNames(any())).thenReturn(tokenBuilder); - when(tokenBuilder.build()).thenReturn(scanner); - - when(client.newScannerBuilder(table)).thenReturn(tokenBuilder); - when(table.getSchema()).thenReturn(schema); - when(schema.getPrimaryKeyColumns()).thenReturn(columnSchemas); - when(schema.newPartialRow()).thenReturn(partialRow); - when(sideInfo.getSideTableInfo()).thenReturn(tableInfo); - when(sideInfo.getSideSelectFields()).thenReturn("a,b"); - when(tableInfo.getKuduMasters()).thenReturn("localhost"); - when(tableInfo.getTableName()).thenReturn("tablename"); - when(tableInfo.getWorkerCount()).thenReturn(3); - when(tableInfo.getDefaultOperationTimeoutMs()).thenReturn(1000); - when(tableInfo.getBatchSizeBytes()).thenReturn(1000); - when(tableInfo.getLimitNum()).thenReturn(1000L); - when(tableInfo.getFaultTolerant()).thenReturn(true); - when(tableInfo.getLowerBoundPrimaryKey()).thenReturn("lower"); - when(tableInfo.getUpperBoundPrimaryKey()).thenReturn("upper"); - when(tableInfo.getPrimaryKey()).thenReturn("mid"); - - kuduAllReqRow.reloadCache(); - } - - @Test - public void testFlatMap() throws Exception { - Collector out = mock(Collector.class); - GenericRow row = new GenericRow(4); - row.setField(0, 1); - row.setField(1, 23); - row.setField(2, 10f); - row.setField(3, 12L); - - List equalValIndex = Lists.newArrayList(); - equalValIndex.add(0); - - AtomicReference>>> cacheRef = new AtomicReference<>(); - Map keyValue = Maps.newConcurrentMap(); - keyValue.put("1", Lists.newArrayList()); - cacheRef.set(keyValue); - - List outFieldInfoList = Lists.newArrayList(); - FieldInfo fieldInfo = new FieldInfo(); - fieldInfo.setTable("m"); - fieldInfo.setFieldName("id"); - fieldInfo.setTypeInformation(TypeInformation.of(Integer.class)); - outFieldInfoList.add(fieldInfo); - outFieldInfoList.add(fieldInfo); - outFieldInfoList.add(fieldInfo); - outFieldInfoList.add(fieldInfo); - outFieldInfoList.add(fieldInfo); - outFieldInfoList.add(fieldInfo); - outFieldInfoList.add(fieldInfo); - outFieldInfoList.add(fieldInfo); - - RowTypeInfo rowTypeInfo = new RowTypeInfo(new TypeInformation[]{TypeInformation.of(Integer.class), TypeInformation.of(Integer.class), TypeInformation.of(Integer.class), TypeInformation.of(Integer.class)}, new String[]{"id", "bb", "ddd", "PROCTIME"}); - - Map inFieldIndex = Maps.newHashMap(); - inFieldIndex.put(0, 0); - inFieldIndex.put(1, 1); - inFieldIndex.put(2, 2); - inFieldIndex.put(3, 3); - - Map sideFieldNameIndex = Maps.newHashMap(); - sideFieldNameIndex.put(3, "rowkey"); - sideFieldNameIndex.put(4, "channel"); - sideFieldNameIndex.put(5, "f"); - sideFieldNameIndex.put(6, "l"); - - Whitebox.setInternalState(kuduAllReqRow, "cacheRef", cacheRef); - Whitebox.setInternalState(kuduAllReqRow, "sideInfo", sideInfo); - - when(sideInfo.getOutFieldInfoList()).thenReturn(outFieldInfoList); - when(sideInfo.getInFieldIndex()).thenReturn(inFieldIndex); - when(sideInfo.getRowTypeInfo()).thenReturn(rowTypeInfo); - when(sideInfo.getSideFieldNameIndex()).thenReturn(sideFieldNameIndex); - when(sideInfo.getEqualValIndex()).thenReturn(equalValIndex); - when(sideInfo.getJoinType()).thenReturn(JoinType.LEFT); - - kuduAllReqRow.flatMap(row, out); - } - - @Test - public void testClose() throws Exception { - Whitebox.setInternalState(kuduAllReqRow, "client", client); - kuduAllReqRow.close(); - } -} diff --git a/kudu/kudu-side/kudu-all-side/src/test/java/com/dtstack/flink/sql/side/kudu/KuduAllSideInfoTest.java b/kudu/kudu-side/kudu-all-side/src/test/java/com/dtstack/flink/sql/side/kudu/KuduAllSideInfoTest.java deleted file mode 100644 index 4703be19a..000000000 --- a/kudu/kudu-side/kudu-all-side/src/test/java/com/dtstack/flink/sql/side/kudu/KuduAllSideInfoTest.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.kudu; - -import com.dtstack.flink.sql.side.BaseSideInfo; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.util.ParseUtils; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import org.apache.calcite.sql.SqlNode; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import org.powermock.reflect.Whitebox; - -import java.util.List; - -import static org.powermock.api.mockito.PowerMockito.mock; -import static org.powermock.api.mockito.PowerMockito.when; -import static org.powermock.api.support.membermodification.MemberMatcher.constructor; -import static org.powermock.api.support.membermodification.MemberMatcher.method; -import static org.powermock.api.support.membermodification.MemberModifier.suppress; - - -/** - * @author: chuixue - * @create: 2020-08-10 13:48 - * @description: - **/ -@RunWith(PowerMockRunner.class) -@PrepareForTest({ParseUtils.class, - KuduAllSideInfo.class, - BaseSideInfo.class -}) -public class KuduAllSideInfoTest { - - private KuduAllSideInfo kuduAllSideInfo; - - @Before - public void setUp() { - suppress(constructor(BaseSideInfo.class)); - kuduAllSideInfo = new KuduAllSideInfo(null, null, null, null); - } - - @Test - public void testParseSelectFields() { - List outFieldInfoList = Lists.newArrayList(); - FieldInfo fieldInfo = new FieldInfo(); - fieldInfo.setTable("m"); - fieldInfo.setFieldName("id"); - fieldInfo.setTypeInformation(TypeInformation.of(Integer.class)); - FieldInfo fieldInfo2 = new FieldInfo(); - fieldInfo2.setTable("s"); - fieldInfo2.setFieldName("aa"); - fieldInfo2.setTypeInformation(TypeInformation.of(Integer.class)); - outFieldInfoList.add(fieldInfo); - outFieldInfoList.add(fieldInfo); - outFieldInfoList.add(fieldInfo2); - outFieldInfoList.add(fieldInfo2); - JoinInfo joinInfo = mock(JoinInfo.class); - RowTypeInfo rowTypeInfo = new RowTypeInfo(new TypeInformation[]{TypeInformation.of(Integer.class), TypeInformation.of(String.class), TypeInformation.of(Integer.class)}, new String[]{"id", "bb", "PROCTIME"}); - List equalFieldList = Lists.newArrayList(); - equalFieldList.add("a"); - equalFieldList.add("b"); - - Whitebox.setInternalState(kuduAllSideInfo, "rowTypeInfo", rowTypeInfo); - Whitebox.setInternalState(kuduAllSideInfo, "outFieldInfoList", outFieldInfoList); - Whitebox.setInternalState(kuduAllSideInfo, "sideFieldIndex", Maps.newHashMap()); - Whitebox.setInternalState(kuduAllSideInfo, "sideFieldNameIndex", Maps.newHashMap()); - Whitebox.setInternalState(kuduAllSideInfo, "inFieldIndex", Maps.newHashMap()); - Whitebox.setInternalState(kuduAllSideInfo, "equalFieldList", equalFieldList); - - when(joinInfo.getSideTableName()).thenReturn("m"); - when(joinInfo.getNonSideTable()).thenReturn("s"); - suppress(method(ParseUtils.class, "parseAnd", SqlNode.class, List.class)); - - kuduAllSideInfo.parseSelectFields(joinInfo); - } -} diff --git a/kudu/kudu-side/kudu-async-side/pom.xml b/kudu/kudu-side/kudu-async-side/pom.xml index 02c77a458..6ab098ea9 100644 --- a/kudu/kudu-side/kudu-async-side/pom.xml +++ b/kudu/kudu-side/kudu-async-side/pom.xml @@ -88,14 +88,14 @@ - + - + diff --git a/kudu/kudu-side/kudu-async-side/src/main/java/com/dtstack/flink/sql/side/kudu/KuduAsyncReqRow.java b/kudu/kudu-side/kudu-async-side/src/main/java/com/dtstack/flink/sql/side/kudu/KuduAsyncReqRow.java index 0bfaa4039..10fee59f4 100644 --- a/kudu/kudu-side/kudu-async-side/src/main/java/com/dtstack/flink/sql/side/kudu/KuduAsyncReqRow.java +++ b/kudu/kudu-side/kudu-async-side/src/main/java/com/dtstack/flink/sql/side/kudu/KuduAsyncReqRow.java @@ -1,54 +1,34 @@ package com.dtstack.flink.sql.side.kudu; import com.dtstack.flink.sql.enums.ECacheContentType; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.BaseAsyncReqRow; -import com.dtstack.flink.sql.side.CacheMissVal; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.PredicateInfo; +import com.dtstack.flink.sql.side.*; import com.dtstack.flink.sql.side.cache.CacheObj; import com.dtstack.flink.sql.side.kudu.table.KuduSideTableInfo; -import com.dtstack.flink.sql.side.kudu.utils.KuduUtil; -import com.dtstack.flink.sql.util.DateUtil; -import com.dtstack.flink.sql.util.KrbUtils; -import com.dtstack.flink.sql.util.RowDataComplete; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; import com.stumbleupon.async.Callback; import com.stumbleupon.async.Deferred; -import org.apache.commons.lang3.StringUtils; +import io.vertx.core.json.JsonArray; import org.apache.flink.api.java.typeutils.RowTypeInfo; +import org.apache.flink.calcite.shaded.com.google.common.collect.Lists; import org.apache.flink.configuration.Configuration; +import org.apache.flink.shaded.guava18.com.google.common.collect.Maps; import org.apache.flink.streaming.api.functions.async.ResultFuture; -import org.apache.flink.table.dataformat.BaseRow; -import org.apache.flink.table.dataformat.GenericRow; +import org.apache.flink.table.typeutils.TimeIndicatorTypeInfo; import org.apache.flink.types.Row; import org.apache.flink.util.Preconditions; -import org.apache.hadoop.security.UserGroupInformation; import org.apache.kudu.ColumnSchema; import org.apache.kudu.Schema; -import org.apache.kudu.client.AsyncKuduClient; -import org.apache.kudu.client.AsyncKuduScanner; -import org.apache.kudu.client.KuduException; -import org.apache.kudu.client.KuduPredicate; -import org.apache.kudu.client.KuduTable; -import org.apache.kudu.client.RowResult; -import org.apache.kudu.client.RowResultIterator; +import org.apache.kudu.Type; +import org.apache.kudu.client.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.IOException; -import java.math.BigDecimal; -import java.security.PrivilegedAction; import java.sql.Timestamp; -import java.time.Instant; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; -public class KuduAsyncReqRow extends BaseAsyncReqRow { +public class KuduAsyncReqRow extends AsyncReqRow { private static final Logger LOG = LoggerFactory.getLogger(KuduAsyncReqRow.class); /** @@ -71,7 +51,7 @@ public class KuduAsyncReqRow extends BaseAsyncReqRow { private AsyncKuduScanner.AsyncKuduScannerBuilder scannerBuilder; - public KuduAsyncReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { + public KuduAsyncReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, SideTableInfo sideTableInfo) { super(new KuduAsyncSideInfo(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo)); } @@ -87,22 +67,40 @@ public void open(Configuration parameters) throws Exception { * * @throws KuduException */ - private void connKuDu() throws IOException { + private void connKuDu() throws KuduException { if (null == table) { + String kuduMasters = kuduSideTableInfo.getKuduMasters(); String tableName = kuduSideTableInfo.getTableName(); - asyncClient = getClient(); + Integer workerCount = kuduSideTableInfo.getWorkerCount(); + Integer defaultSocketReadTimeoutMs = kuduSideTableInfo.getDefaultSocketReadTimeoutMs(); + Integer defaultOperationTimeoutMs = kuduSideTableInfo.getDefaultOperationTimeoutMs(); + + Preconditions.checkNotNull(kuduMasters, "kuduMasters could not be null"); + + AsyncKuduClient.AsyncKuduClientBuilder asyncKuduClientBuilder = new AsyncKuduClient.AsyncKuduClientBuilder(kuduMasters); + if (null != workerCount) { + asyncKuduClientBuilder.workerCount(workerCount); + } + if (null != defaultSocketReadTimeoutMs) { + asyncKuduClientBuilder.defaultSocketReadTimeoutMs(defaultSocketReadTimeoutMs); + } + + if (null != defaultOperationTimeoutMs) { + asyncKuduClientBuilder.defaultOperationTimeoutMs(defaultOperationTimeoutMs); + } + asyncClient = asyncKuduClientBuilder.build(); if (!asyncClient.syncClient().tableExists(tableName)) { throw new IllegalArgumentException("Table Open Failed , please check table exists"); } table = asyncClient.syncClient().openTable(tableName); - LOG.info("connect kudu is succeed!"); + LOG.info("connect kudu is successed!"); } scannerBuilder = asyncClient.newScannerBuilder(table); Integer batchSizeBytes = kuduSideTableInfo.getBatchSizeBytes(); Long limitNum = kuduSideTableInfo.getLimitNum(); Boolean isFaultTolerant = kuduSideTableInfo.getFaultTolerant(); //查询需要的字段 - String[] sideFieldNames = StringUtils.split(sideInfo.getSideSelectFields(), ","); + String[] sideFieldNames = sideInfo.getSideSelectFields().split(","); if (null == limitNum || limitNum <= 0) { scannerBuilder.limit(FETCH_SIZE); @@ -120,137 +118,73 @@ private void connKuDu() throws IOException { scannerBuilder.setProjectedColumnNames(projectColumns); } - private AsyncKuduClient getClient() throws IOException { - String kuduMasters = kuduSideTableInfo.getKuduMasters(); - Integer workerCount = kuduSideTableInfo.getWorkerCount(); - Integer defaultOperationTimeoutMs = kuduSideTableInfo.getDefaultOperationTimeoutMs(); - - Preconditions.checkNotNull(kuduMasters, "kuduMasters could not be null"); - - AsyncKuduClient.AsyncKuduClientBuilder asyncKuduClientBuilder = new AsyncKuduClient.AsyncKuduClientBuilder(kuduMasters); - if (null != workerCount) { - asyncKuduClientBuilder.workerCount(workerCount); - } - - if (null != defaultOperationTimeoutMs) { - asyncKuduClientBuilder.defaultOperationTimeoutMs(defaultOperationTimeoutMs); - } - - if (kuduSideTableInfo.isEnableKrb()) { - UserGroupInformation ugi = KrbUtils.loginAndReturnUgi( - kuduSideTableInfo.getPrincipal(), - kuduSideTableInfo.getKeytab(), - kuduSideTableInfo.getKrb5conf() - ); - return ugi.doAs( - (PrivilegedAction) asyncKuduClientBuilder::build); - } else { - return asyncKuduClientBuilder.build(); - } - } @Override - public void handleAsyncInvoke(Map inputParams, BaseRow input, ResultFuture resultFuture) throws Exception { - GenericRow genericRow = (GenericRow) input; - GenericRow inputCopy = GenericRow.copyReference(genericRow); - //scannerBuilder 设置为null重新加载过滤条件,然后connkudu重新赋值 - //todo:代码需要优化 + public void asyncInvoke(Row input, ResultFuture resultFuture) throws Exception { + //scannerBuilder 设置为null重新加载过滤条件 scannerBuilder = null; connKuDu(); + JsonArray inputParams = new JsonArray(); Schema schema = table.getSchema(); - // @wenbaoup fix bug - inputParams.forEach((key, value) -> { - Object transformValue = transformValue(value); - if (transformValue == null) { - scannerBuilder.addPredicate( - KuduPredicate.newIsNullPredicate(schema.getColumn(key)) - ); + + for (Integer conValIndex : sideInfo.getEqualValIndex()) { + Object equalObj = input.getField(conValIndex); + if (equalObj == null) { + resultFuture.complete(null); return; } - scannerBuilder.addPredicate( - KuduPredicate.newInListPredicate( - schema.getColumn(key), - Collections.singletonList(transformValue) - ) - ); - }); - - // 填充谓词信息 - List predicateInfoes = sideInfo.getSideTableInfo().getPredicateInfoes(); - if (predicateInfoes.size() > 0) { - predicateInfoes.stream().peek(info -> { - KuduPredicate kuduPredicate = KuduUtil.buildKuduPredicate(schema, info); - if (null != kuduPredicate) { - scannerBuilder.addPredicate(kuduPredicate); - } - }).count(); + //增加过滤条件 + scannerBuilder.addPredicate(KuduPredicate.newInListPredicate(schema.getColumn(sideInfo.getEqualFieldList().get(conValIndex)), Collections.singletonList(equalObj))); + inputParams.add(equalObj); } + String key = buildCacheKey(inputParams); + + if (openCache()) { + //判断数据是否已经加载到缓存中 + CacheObj val = getFromCache(key); + if (val != null) { + + if (ECacheContentType.MissVal == val.getType()) { + dealMissKey(input, resultFuture); + return; + } else if (ECacheContentType.SingleLine == val.getType()) { + Row row = fillData(input, val); + resultFuture.complete(Collections.singleton(row)); + } else if (ECacheContentType.MultiLine == val.getType()) { + List rowList = Lists.newArrayList(); + for (Object jsonArray : (List) val.getContent()) { + Row row = fillData(input, jsonArray); + rowList.add(row); + } + resultFuture.complete(rowList); + } else { + throw new RuntimeException("not support cache obj type " + val.getType()); + } + return; + } + } List> cacheContent = Lists.newArrayList(); AsyncKuduScanner asyncKuduScanner = scannerBuilder.build(); - List rowList = Lists.newArrayList(); + List rowList = Lists.newArrayList(); Deferred data = asyncKuduScanner.nextRows(); //从之前的同步修改为调用异步的Callback - data.addCallbackDeferring(new GetListRowCB(inputCopy, cacheContent, rowList, asyncKuduScanner, resultFuture, buildCacheKey(inputParams))); - } - - /** - * 将value转化为Java 通用类型 - * @param value value - * @return 类型转化的value - */ - private Object transformValue(Object value) { - if (value == null) { - return null; - } else if (value instanceof Number && !(value instanceof BigDecimal)) { - return value; - } else if (value instanceof Boolean) { - return value; - } else if (value instanceof String) { - return value; - } else if (value instanceof Character) { - return value; - } else if (value instanceof CharSequence) { - return value; - } else if (value instanceof Map) { - return value; - } else if (value instanceof List) { - return value; - } else if (value instanceof byte[]) { - return value; - } else if (value instanceof Instant) { - return value; - } else if (value instanceof Timestamp) { - value = DateUtil.timestampToString((Timestamp) value); - } else if (value instanceof java.util.Date) { - value = DateUtil.dateToString((java.sql.Date) value); - } else { - value = value.toString(); - } - return value; - } - - @Override - public String buildCacheKey(Map inputParams) { - StringBuilder sb = new StringBuilder(); - for (Object ele : inputParams.values()) { - sb.append(ele) - .append("_"); - } - - return sb.toString(); + data.addCallbackDeferring(new GetListRowCB(input, cacheContent, rowList, asyncKuduScanner, resultFuture, key)); } @Override - public BaseRow fillData(BaseRow input, Object sideInput) { - GenericRow genericRow = (GenericRow) input; + public Row fillData(Row input, Object sideInput) { Map cacheInfo = (Map) sideInput; - GenericRow row = new GenericRow(sideInfo.getOutFieldInfoList().size()); - row.setHeader(genericRow.getHeader()); + Row row = new Row(sideInfo.getOutFieldInfoList().size()); for (Map.Entry entry : sideInfo.getInFieldIndex().entrySet()) { - Object obj = genericRow.getField(entry.getValue()); - obj = convertTimeIndictorTypeInfo(entry.getValue(), obj); + Object obj = input.getField(entry.getValue()); + boolean isTimeIndicatorTypeInfo = TimeIndicatorTypeInfo.class.isAssignableFrom(sideInfo.getRowTypeInfo().getTypeAt(entry.getValue()).getClass()); + + //Type information for indicating event or processing time. However, it behaves like a regular SQL timestamp but is serialized as Long. + if (obj instanceof Timestamp && isTimeIndicatorTypeInfo) { + obj = ((Timestamp) obj).getTime(); + } row.setField(entry.getKey(), obj); } @@ -265,6 +199,16 @@ public BaseRow fillData(BaseRow input, Object sideInput) { return row; } + public String buildCacheKey(JsonArray jsonArray) { + StringBuilder sb = new StringBuilder(); + for (Object ele : jsonArray.getList()) { + sb.append(ele.toString()) + .append("_"); + } + + return sb.toString(); + } + @Override public void close() throws Exception { super.close(); @@ -277,20 +221,56 @@ public void close() throws Exception { } } + private void setMapValue(Type type, Map oneRow, String sideFieldName, RowResult result) { + switch (type) { + case STRING: + oneRow.put(sideFieldName, result.getString(sideFieldName)); + break; + case FLOAT: + oneRow.put(sideFieldName, result.getFloat(sideFieldName)); + break; + case INT8: + oneRow.put(sideFieldName, result.getFloat(sideFieldName)); + break; + case INT16: + oneRow.put(sideFieldName, result.getShort(sideFieldName)); + break; + case INT32: + oneRow.put(sideFieldName, result.getInt(sideFieldName)); + break; + case INT64: + oneRow.put(sideFieldName, result.getLong(sideFieldName)); + break; + case DOUBLE: + oneRow.put(sideFieldName, result.getDouble(sideFieldName)); + break; + case BOOL: + oneRow.put(sideFieldName, result.getBoolean(sideFieldName)); + break; + case UNIXTIME_MICROS: + oneRow.put(sideFieldName, result.getTimestamp(sideFieldName)); + break; + case BINARY: + oneRow.put(sideFieldName, result.getBinary(sideFieldName)); + break; + default: + throw new IllegalArgumentException("Illegal var type: " + type); + } + } + class GetListRowCB implements Callback>, RowResultIterator> { - private BaseRow input; + private Row input; private List> cacheContent; - private List rowList; + private List rowList; private AsyncKuduScanner asyncKuduScanner; - private ResultFuture resultFuture; + private ResultFuture resultFuture; private String key; public GetListRowCB() { } - GetListRowCB(BaseRow input, List> cacheContent, List rowList, - AsyncKuduScanner asyncKuduScanner, ResultFuture resultFuture, String key) { + GetListRowCB(Row input, List> cacheContent, List rowList, AsyncKuduScanner asyncKuduScanner, ResultFuture resultFuture, String key) { this.input = input; this.cacheContent = cacheContent; this.rowList = rowList; @@ -301,21 +281,16 @@ public GetListRowCB() { @Override public Deferred> call(RowResultIterator results) throws Exception { - if (results == null) { - dealMissKey(input, resultFuture); - return null; - } - for (RowResult result : results) { Map oneRow = Maps.newHashMap(); - for (String sideFieldName1 : StringUtils.split(sideInfo.getSideSelectFields(), ",")) { + for (String sideFieldName1 : sideInfo.getSideSelectFields().split(",")) { String sideFieldName = sideFieldName1.trim(); ColumnSchema columnSchema = table.getSchema().getColumn(sideFieldName); if (null != columnSchema) { - oneRow.put(sideFieldName, result.getObject(sideFieldName)); + setMapValue(columnSchema.getType(), oneRow, sideFieldName, result); } } - BaseRow row = fillData(input, oneRow); + Row row = fillData(input, oneRow); if (openCache()) { cacheContent.add(oneRow); } @@ -329,7 +304,7 @@ public Deferred> call(RowResultIterator results) throws Exception { if (openCache()) { putCache(key, CacheObj.buildCacheObj(ECacheContentType.MultiLine, cacheContent)); } - RowDataComplete.completeBaseRow(resultFuture, rowList); + resultFuture.complete(rowList); } else { dealMissKey(input, resultFuture); if (openCache()) { @@ -338,7 +313,6 @@ public Deferred> call(RowResultIterator results) throws Exception { } } - resultFuture.complete(Collections.emptyList()); return null; } } diff --git a/kudu/kudu-side/kudu-async-side/src/main/java/com/dtstack/flink/sql/side/kudu/KuduAsyncSideInfo.java b/kudu/kudu-side/kudu-async-side/src/main/java/com/dtstack/flink/sql/side/kudu/KuduAsyncSideInfo.java index 4bb0a4952..f341f9a8a 100644 --- a/kudu/kudu-side/kudu-async-side/src/main/java/com/dtstack/flink/sql/side/kudu/KuduAsyncSideInfo.java +++ b/kudu/kudu-side/kudu-async-side/src/main/java/com/dtstack/flink/sql/side/kudu/KuduAsyncSideInfo.java @@ -2,28 +2,27 @@ import com.dtstack.flink.sql.side.FieldInfo; import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.BaseSideInfo; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; +import com.dtstack.flink.sql.side.SideInfo; +import com.dtstack.flink.sql.side.SideTableInfo; import com.dtstack.flink.sql.side.kudu.table.KuduSideTableInfo; -import com.dtstack.flink.sql.util.ParseUtils; -import com.google.common.collect.Lists; import org.apache.calcite.sql.SqlBasicCall; import org.apache.calcite.sql.SqlIdentifier; import org.apache.calcite.sql.SqlKind; import org.apache.calcite.sql.SqlNode; import org.apache.flink.api.java.typeutils.RowTypeInfo; +import org.apache.flink.calcite.shaded.com.google.common.collect.Lists; import java.util.List; -public class KuduAsyncSideInfo extends BaseSideInfo { +public class KuduAsyncSideInfo extends SideInfo { - public KuduAsyncSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { + public KuduAsyncSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, SideTableInfo sideTableInfo) { super(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); } @Override - public void buildEqualInfo(JoinInfo joinInfo, AbstractSideTableInfo sideTableInfo) { + public void buildEqualInfo(JoinInfo joinInfo, SideTableInfo sideTableInfo) { KuduSideTableInfo kuduSideTableInfo = (KuduSideTableInfo) sideTableInfo; String sideTableName = joinInfo.getSideTableName(); @@ -31,7 +30,11 @@ public void buildEqualInfo(JoinInfo joinInfo, AbstractSideTableInfo sideTableInf SqlNode conditionNode = joinInfo.getCondition(); List sqlNodeList = Lists.newArrayList(); - ParseUtils.parseAnd(conditionNode, sqlNodeList); + if (conditionNode.getKind() == SqlKind.AND) { + sqlNodeList.addAll(Lists.newArrayList(((SqlBasicCall) conditionNode).getOperands())); + } else { + sqlNodeList.add(conditionNode); + } for (SqlNode sqlNode : sqlNodeList) { dealOneEqualCon(sqlNode, sideTableName); @@ -42,4 +45,55 @@ public void buildEqualInfo(JoinInfo joinInfo, AbstractSideTableInfo sideTableInf System.out.println("---------side_exe_sql-----\n" + sqlCondition); } + @Override + public void dealOneEqualCon(SqlNode sqlNode, String sideTableName) { + if (sqlNode.getKind() != SqlKind.EQUALS) { + throw new RuntimeException("not equal operator."); + } + + SqlIdentifier left = (SqlIdentifier) ((SqlBasicCall) sqlNode).getOperands()[0]; + SqlIdentifier right = (SqlIdentifier) ((SqlBasicCall) sqlNode).getOperands()[1]; + + String leftTableName = left.getComponent(0).getSimple(); + String leftField = left.getComponent(1).getSimple(); + + String rightTableName = right.getComponent(0).getSimple(); + String rightField = right.getComponent(1).getSimple(); + + if (leftTableName.equalsIgnoreCase(sideTableName)) { + equalFieldList.add(leftField); + int equalFieldIndex = -1; + for (int i = 0; i < rowTypeInfo.getFieldNames().length; i++) { + String fieldName = rowTypeInfo.getFieldNames()[i]; + if (fieldName.equalsIgnoreCase(rightField)) { + equalFieldIndex = i; + } + } + if (equalFieldIndex == -1) { + throw new RuntimeException("can't deal equal field: " + sqlNode); + } + + equalValIndex.add(equalFieldIndex); + + } else if (rightTableName.equalsIgnoreCase(sideTableName)) { + + equalFieldList.add(rightField); + int equalFieldIndex = -1; + for (int i = 0; i < rowTypeInfo.getFieldNames().length; i++) { + String fieldName = rowTypeInfo.getFieldNames()[i]; + if (fieldName.equalsIgnoreCase(leftField)) { + equalFieldIndex = i; + } + } + if (equalFieldIndex == -1) { + throw new RuntimeException("can't deal equal field: " + sqlNode.toString()); + } + + equalValIndex.add(equalFieldIndex); + + } else { + throw new RuntimeException("resolve equalFieldList error:" + sqlNode.toString()); + } + + } } diff --git a/kudu/kudu-side/kudu-async-side/src/test/java/com/dtstack/flink/sql/side/kudu/KuduAsyncReqRowTest.java b/kudu/kudu-side/kudu-async-side/src/test/java/com/dtstack/flink/sql/side/kudu/KuduAsyncReqRowTest.java deleted file mode 100644 index 10b5cd84e..000000000 --- a/kudu/kudu-side/kudu-async-side/src/test/java/com/dtstack/flink/sql/side/kudu/KuduAsyncReqRowTest.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.kudu; - -import com.dtstack.flink.sql.side.BaseAsyncReqRow; -import com.dtstack.flink.sql.side.BaseSideInfo; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.kudu.table.KuduSideTableInfo; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.stumbleupon.async.Deferred; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.configuration.Configuration; -import org.apache.flink.streaming.api.functions.async.ResultFuture; -import org.apache.flink.table.dataformat.GenericRow; -import org.apache.flink.table.typeutils.TimeIndicatorTypeInfo; -import org.apache.flink.types.Row; -import org.apache.kudu.client.AsyncKuduClient; -import org.apache.kudu.client.AsyncKuduScanner; -import org.apache.kudu.client.KuduClient; -import org.apache.kudu.client.KuduTable; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import org.powermock.reflect.Whitebox; - -import java.util.List; -import java.util.Map; - -import static org.mockito.Mockito.mock; -import static org.powermock.api.mockito.PowerMockito.when; -import static org.powermock.api.mockito.PowerMockito.whenNew; -import static org.powermock.api.support.membermodification.MemberMatcher.constructor; -import static org.powermock.api.support.membermodification.MemberModifier.suppress; - -/** - * @author: chuixue - * @create: 2020-08-11 14:38 - * @description: - **/ -@RunWith(PowerMockRunner.class) -@PrepareForTest({ - KuduAsyncReqRow.class, - KuduAsyncSideInfo.class, - BaseAsyncReqRow.class, - AsyncKuduClient.AsyncKuduClientBuilder.class, - AsyncKuduScanner.class, - Deferred.class -}) -public class KuduAsyncReqRowTest { - - private KuduAsyncReqRow kuduAsyncReqRow; - private BaseSideInfo sideInfo; - private KuduSideTableInfo kuduSideTableInfo; - private AsyncKuduClient asyncClient; - - @Before - public void setUp() { - asyncClient = mock(AsyncKuduClient.class); - sideInfo = mock(BaseSideInfo.class); - suppress(constructor(KuduAsyncSideInfo.class)); - suppress(constructor(BaseAsyncReqRow.class)); - kuduAsyncReqRow = new KuduAsyncReqRow(null, null, null, null); - Whitebox.setInternalState(kuduAsyncReqRow, "sideInfo", sideInfo); - } - - @Test - public void testHandleAsyncInvoke() throws Exception { - ResultFuture resultFuture = mock(ResultFuture.class); - - GenericRow row = new GenericRow(4); - row.setField(0, 1); - row.setField(1, 23); - row.setField(2, 10f); - row.setField(3, 12L); - - kuduSideTableInfo = mock(KuduSideTableInfo.class); - AsyncKuduClient.AsyncKuduClientBuilder asyncKuduClientBuilder = mock(AsyncKuduClient.AsyncKuduClientBuilder.class); - KuduClient kuduClient = mock(KuduClient.class); - KuduTable table = mock(KuduTable.class); - AsyncKuduScanner.AsyncKuduScannerBuilder scannerBuilder = mock(AsyncKuduScanner.AsyncKuduScannerBuilder.class); - AsyncKuduScanner asyncKuduScanner = mock(AsyncKuduScanner.class); - Deferred data = mock(Deferred.class); - - Whitebox.setInternalState(kuduAsyncReqRow, "kuduSideTableInfo", kuduSideTableInfo); - - suppress(BaseAsyncReqRow.class.getMethod("open", Configuration.class)); - when(sideInfo.getSideTableInfo()).thenReturn(kuduSideTableInfo); - when(sideInfo.getSideSelectFields()).thenReturn("a,b"); - when(kuduSideTableInfo.getKuduMasters()).thenReturn("localhost"); - when(kuduSideTableInfo.getTableName()).thenReturn("tablename"); - when(kuduSideTableInfo.getWorkerCount()).thenReturn(3); - when(kuduSideTableInfo.getDefaultOperationTimeoutMs()).thenReturn(1000); - when(kuduSideTableInfo.getBatchSizeBytes()).thenReturn(1000); - when(kuduSideTableInfo.getLimitNum()).thenReturn(1000L); - when(kuduSideTableInfo.getFaultTolerant()).thenReturn(true); - whenNew(AsyncKuduClient.AsyncKuduClientBuilder.class).withArguments("localhost").thenReturn(asyncKuduClientBuilder); - when(asyncKuduClientBuilder.build()).thenReturn(asyncClient); - when(asyncClient.syncClient()).thenReturn(kuduClient); - when(kuduClient.tableExists("tablename")).thenReturn(true); - when(kuduClient.openTable("tablename")).thenReturn(table); - when(asyncClient.newScannerBuilder(table)).thenReturn(scannerBuilder); - when(scannerBuilder.build()).thenReturn(asyncKuduScanner); - when(asyncKuduScanner.nextRows()).thenReturn(data); - - kuduAsyncReqRow.handleAsyncInvoke(Maps.newHashMap(), row, resultFuture); - } - - @Test - public void testFillData() { - GenericRow row = new GenericRow(3); - row.setField(0, 1); - row.setField(1, "bbbbbb"); - row.setField(2, "2020-07-14 01:27:43.969"); - - List outFieldInfoList = Lists.newArrayList(); - FieldInfo fieldInfo = new FieldInfo(); - fieldInfo.setTable("m"); - fieldInfo.setFieldName("id"); - FieldInfo fieldInfo2 = new FieldInfo(); - fieldInfo2.setTable("s"); - fieldInfo2.setFieldName("_id"); - outFieldInfoList.add(fieldInfo); - outFieldInfoList.add(fieldInfo2); - outFieldInfoList.add(fieldInfo); - outFieldInfoList.add(fieldInfo2); - - Map inFieldIndex = Maps.newHashMap(); - inFieldIndex.put(0, 0); - inFieldIndex.put(1, 1); - - Map sideFieldIndex = Maps.newHashMap(); - sideFieldIndex.put(2, "1"); - sideFieldIndex.put(3, "1"); - RowTypeInfo rowTypeInfo = new RowTypeInfo(new TypeInformation[]{TypeInformation.of(Integer.class), TypeInformation.of(TimeIndicatorTypeInfo.class)}, new String[]{"id", "PROCTIME"}); - - when(sideInfo.getOutFieldInfoList()).thenReturn(outFieldInfoList); - when(sideInfo.getInFieldIndex()).thenReturn(inFieldIndex); - when(sideInfo.getRowTypeInfo()).thenReturn(rowTypeInfo); - when(sideInfo.getSideFieldNameIndex()).thenReturn(sideFieldIndex); - - kuduAsyncReqRow.fillData(row, null); - } - - @Test - public void testClose() throws Exception { - Whitebox.setInternalState(kuduAsyncReqRow, "asyncClient", asyncClient); - kuduAsyncReqRow.close(); - } -} diff --git a/kudu/kudu-side/kudu-async-side/src/test/java/com/dtstack/flink/sql/side/kudu/KuduAsyncSideInfoTest.java b/kudu/kudu-side/kudu-async-side/src/test/java/com/dtstack/flink/sql/side/kudu/KuduAsyncSideInfoTest.java deleted file mode 100644 index f305c28b8..000000000 --- a/kudu/kudu-side/kudu-async-side/src/test/java/com/dtstack/flink/sql/side/kudu/KuduAsyncSideInfoTest.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.kudu; - -import com.dtstack.flink.sql.side.BaseSideInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.kudu.table.KuduSideTableInfo; -import com.dtstack.flink.sql.util.ParseUtils; -import com.google.common.collect.Lists; -import org.apache.calcite.sql.SqlBasicCall; -import org.apache.calcite.sql.SqlBinaryOperator; -import org.apache.calcite.sql.SqlIdentifier; -import org.apache.calcite.sql.SqlNode; -import org.apache.calcite.sql.fun.SqlStdOperatorTable; -import org.apache.calcite.sql.parser.SqlParserPos; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import org.powermock.reflect.Whitebox; - -import java.util.List; - -import static org.powermock.api.mockito.PowerMockito.mock; -import static org.powermock.api.mockito.PowerMockito.when; -import static org.powermock.api.support.membermodification.MemberMatcher.constructor; -import static org.powermock.api.support.membermodification.MemberModifier.suppress; - -/** - * @author: chuixue - * @create: 2020-08-11 13:45 - * @description: - **/ -@RunWith(PowerMockRunner.class) -@PrepareForTest({ParseUtils.class, - KuduAsyncSideInfo.class, - BaseSideInfo.class}) -public class KuduAsyncSideInfoTest { - - private KuduAsyncSideInfo kuduAsyncSideInfo; - - @Before - public void setUp() { - suppress(constructor(BaseSideInfo.class)); - kuduAsyncSideInfo = new KuduAsyncSideInfo(null, null, null, null); - } - - @Test - public void testBuildEqualInfo() { - JoinInfo joinInfo = mock(JoinInfo.class); - KuduSideTableInfo kuduSideTableInfo = mock(KuduSideTableInfo.class); - - SqlBinaryOperator equalsOperators = SqlStdOperatorTable.EQUALS; - SqlNode[] operands = new SqlNode[2]; - List one = Lists.newArrayList(); - one.add("m"); - one.add("id"); - List two = Lists.newArrayList(); - two.add("s"); - two.add("rowkey"); - operands[0] = new SqlIdentifier(one, new SqlParserPos(0, 0)); - operands[1] = new SqlIdentifier(two, new SqlParserPos(0, 0)); - SqlBasicCall sqlBasicCall = new SqlBasicCall(equalsOperators, operands, SqlParserPos.ZERO); - - RowTypeInfo rowTypeInfo = new RowTypeInfo(new TypeInformation[]{TypeInformation.of(Integer.class), TypeInformation.of(String.class), TypeInformation.of(Integer.class)}, new String[]{"id", "rowkey", "PROCTIME"}); - - Whitebox.setInternalState(kuduAsyncSideInfo, "sideSelectFields", "sideSelectFields"); - Whitebox.setInternalState(kuduAsyncSideInfo, "equalFieldList", Lists.newArrayList()); - Whitebox.setInternalState(kuduAsyncSideInfo, "equalValIndex", Lists.newArrayList()); - Whitebox.setInternalState(kuduAsyncSideInfo, "rowTypeInfo", rowTypeInfo); - when(kuduSideTableInfo.getTableName()).thenReturn("ddd"); - when(joinInfo.getSideTableName()).thenReturn("m"); - when(joinInfo.getNonSideTable()).thenReturn("s"); - when(joinInfo.getCondition()).thenReturn(sqlBasicCall); - - kuduAsyncSideInfo.buildEqualInfo(joinInfo, kuduSideTableInfo); - } -} diff --git a/kudu/kudu-side/kudu-side-core/src/main/java/com/dtstack/flink/sql/side/kudu/table/KuduSideParser.java b/kudu/kudu-side/kudu-side-core/src/main/java/com/dtstack/flink/sql/side/kudu/table/KuduSideParser.java index 48a8a443a..ea451286c 100644 --- a/kudu/kudu-side/kudu-side-core/src/main/java/com/dtstack/flink/sql/side/kudu/table/KuduSideParser.java +++ b/kudu/kudu-side/kudu-side-core/src/main/java/com/dtstack/flink/sql/side/kudu/table/KuduSideParser.java @@ -1,18 +1,14 @@ package com.dtstack.flink.sql.side.kudu.table; -import com.dtstack.flink.sql.constant.PluginParamConsts; -import com.dtstack.flink.sql.table.AbstractSideTableParser; -import com.dtstack.flink.sql.table.AbstractTableInfo; +import com.dtstack.flink.sql.table.AbsSideTableParser; +import com.dtstack.flink.sql.table.TableInfo; import com.dtstack.flink.sql.util.MathUtil; -import java.math.BigDecimal; -import java.sql.Date; -import java.sql.Timestamp; import java.util.Map; -import static com.dtstack.flink.sql.table.AbstractTableInfo.PARALLELISM_KEY; +import static com.dtstack.flink.sql.table.TableInfo.PARALLELISM_KEY; -public class KuduSideParser extends AbstractSideTableParser { +public class KuduSideParser extends AbsSideTableParser { public static final String KUDU_MASTERS = "kuduMasters"; @@ -23,6 +19,8 @@ public class KuduSideParser extends AbstractSideTableParser { public static final String OPERATION_TIMEOUT_MS = "defaultOperationTimeoutMs"; + public static final String SOCKET_READ_TIMEOUT_MS = "defaultSocketReadTimeoutMs"; + /** * 查询返回的最大字节数 */ @@ -49,8 +47,9 @@ public class KuduSideParser extends AbstractSideTableParser { */ public static final String UPPER_BOUND_PRIMARY_KEY = "upperBoundPrimaryKey"; + @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { + public TableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { KuduSideTableInfo kuduSideTableInfo = new KuduSideTableInfo(); kuduSideTableInfo.setName(tableName); parseFieldsInfo(fieldsInfo, kuduSideTableInfo); @@ -62,67 +61,14 @@ public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map oneRow, String sideFieldName, RowResult result) { - switch (type) { - case STRING: - oneRow.put(sideFieldName, result.getString(sideFieldName)); - break; - case FLOAT: - oneRow.put(sideFieldName, result.getFloat(sideFieldName)); - break; - case INT8: - oneRow.put(sideFieldName, (int) result.getByte(sideFieldName)); - break; - case INT16: - oneRow.put(sideFieldName, (int) result.getShort(sideFieldName)); - break; - case INT32: - oneRow.put(sideFieldName, result.getInt(sideFieldName)); - break; - case INT64: - oneRow.put(sideFieldName, result.getLong(sideFieldName)); - break; - case DOUBLE: - oneRow.put(sideFieldName, result.getDouble(sideFieldName)); - break; - case BOOL: - oneRow.put(sideFieldName, result.getBoolean(sideFieldName)); - break; - case UNIXTIME_MICROS: - oneRow.put(sideFieldName, result.getTimestamp(sideFieldName)); - break; - case BINARY: - oneRow.put(sideFieldName, result.getBinary(sideFieldName)); - break; - default: - throw new IllegalArgumentException("Illegal var type: " + type); - } - } - - public static Object getValue(String value, Type type){ - if(value == null){ - return null; - } - - if(value.startsWith("\"") || value.endsWith("'")){ - value = value.substring(1, value.length() - 1); - } - - Object objValue; - if (Type.BOOL.equals(type)){ - objValue = Boolean.valueOf(value); - } else if(Type.INT8.equals(type)){ - objValue = Byte.valueOf(value); - } else if(Type.INT16.equals(type)){ - objValue = Short.valueOf(value); - } else if(Type.INT32.equals(type)){ - objValue = Integer.valueOf(value); - } else if(Type.INT64.equals(type)){ - objValue = Long.valueOf(value); - } else if(Type.FLOAT.equals(type)){ - objValue = Float.valueOf(value); - } else if(Type.DOUBLE.equals(type)){ - objValue = Double.valueOf(value); - } else if(Type.DECIMAL.equals(type)){ - objValue = new BigDecimal(value); - } else if(Type.UNIXTIME_MICROS.equals(type)){ - if(NumberUtils.isNumber(value)){ - objValue = Long.valueOf(value); - } else { - objValue = Timestamp.valueOf(value); - } - } else { - objValue = value; - } - - return objValue; - } - - public static KuduPredicate buildKuduPredicate(Schema schema, PredicateInfo info) { - ColumnSchema column = schema.getColumn(info.getFieldName()); - Object value = ""; - switch (info.getOperatorKind()) { - case "IN": - case "NOT_IN": - case "BETWEEN": - value = Arrays.asList(StringUtils.split(info.getCondition(), ",")).stream() - .map(val -> KuduUtil.getValue(val.trim(), column.getType())).collect(Collectors.toList()); - break; - case "IS_NOT_NULL": - case "IS_NULL": - break; - default: - value = KuduUtil.getValue(info.getCondition(), column.getType()); - } - - switch (info.getOperatorName()) { - case "=": - return KuduPredicate.newComparisonPredicate(column, KuduPredicate.ComparisonOp.EQUAL, value); - case ">": - return KuduPredicate.newComparisonPredicate(column, KuduPredicate.ComparisonOp.GREATER, value); - case ">=": - return KuduPredicate.newComparisonPredicate(column, KuduPredicate.ComparisonOp.GREATER_EQUAL, value); - case "<": - return KuduPredicate.newComparisonPredicate(column, KuduPredicate.ComparisonOp.LESS, value); - case "<=": - return KuduPredicate.newComparisonPredicate(column, KuduPredicate.ComparisonOp.LESS_EQUAL, value); - case "IN": - return KuduPredicate.newInListPredicate(column, (List) value); - case "IS NOT NULL": - return KuduPredicate.newIsNotNullPredicate(column); - case "IS NULL": - return KuduPredicate.newIsNullPredicate(column); - default: - } - return null; - - } -} diff --git a/kudu/kudu-side/kudu-side-core/src/test/java/com/dtstack/flink/sql/side/kudu/table/KuduSideParserTest.java b/kudu/kudu-side/kudu-side-core/src/test/java/com/dtstack/flink/sql/side/kudu/table/KuduSideParserTest.java deleted file mode 100644 index f443f005e..000000000 --- a/kudu/kudu-side/kudu-side-core/src/test/java/com/dtstack/flink/sql/side/kudu/table/KuduSideParserTest.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.kudu.table; - -import com.google.common.collect.Maps; -import org.junit.Test; - -import java.util.Map; - -import static org.junit.Assert.assertEquals; - -/** - * @author: chuixue - * @create: 2020-08-10 11:29 - * @description: - **/ -public class KuduSideParserTest { - private KuduSideParser parser = new KuduSideParser(); - - @Test - public void testGetTableInfo() { - Map props = Maps.newHashMap(); - props.put("parallelism", "12"); - props.put("kuduMasters", "localhost"); - props.put("tableName", "tableName"); - props.put("workerCount", "12"); - props.put("defaultOperationTimeoutMs", "111"); - props.put("defaultSocketReadTimeoutMs", "333"); - props.put("batchSizeBytes", "333"); - props.put("limitNum", "333"); - props.put("isFaultTolerant", "true"); - props.put("primaryKey", "mid"); - props.put("lowerBoundPrimaryKey", "lower"); - props.put("upperBoundPrimaryKey", "upper"); - - parser.getTableInfo("Mykafka", " mid int , mbb varchar, sid varchar, sbb varchar, PRIMARY KEY(mid), PERIOD FOR SYSTEM_TIME", props); - - assertEquals(parser, parser); - } - - @Test - public void testDbTypeConvertToJavaType() { - String[] fieldTypes = new String[]{"bool", "int8", "int16", "int", "int64", "string", "float", "double", "date", "unixtime_micros", "decimal", "binary"}; - for (String fieldType : fieldTypes) { - parser.dbTypeConvertToJavaType(fieldType); - } - } -} diff --git a/kudu/kudu-side/kudu-side-core/src/test/java/com/dtstack/flink/sql/side/kudu/utils/KuduUtilTest.java b/kudu/kudu-side/kudu-side-core/src/test/java/com/dtstack/flink/sql/side/kudu/utils/KuduUtilTest.java deleted file mode 100644 index 8bf820faf..000000000 --- a/kudu/kudu-side/kudu-side-core/src/test/java/com/dtstack/flink/sql/side/kudu/utils/KuduUtilTest.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.kudu.utils; - -import com.google.common.collect.Maps; -import org.apache.kudu.Type; -import org.apache.kudu.client.PartialRow; -import org.apache.kudu.client.RowResult; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.modules.junit4.PowerMockRunner; - -import java.util.Map; - -import static org.powermock.api.mockito.PowerMockito.mock; - -/** - * @author: chuixue - * @create: 2020-08-10 11:44 - * @description: - **/ -@RunWith(PowerMockRunner.class) -public class KuduUtilTest { - - private Type[] types = new Type[]{Type.STRING, Type.FLOAT, Type.INT8, Type.INT16, Type.INT32, Type.INT64, Type.DOUBLE, Type.BOOL, Type.BINARY}; - - - @Test - public void testPrimaryKeyRange() { - PartialRow partialRow = mock(PartialRow.class); - for (Type type : types) { - KuduUtil.primaryKeyRange(partialRow, type, "primaryKey", "1"); - } - } - - @Test - public void testSetMapValue() { - RowResult result = mock(RowResult.class); - Map oneRow = Maps.newHashMap(); - for (Type type : types) { - KuduUtil.setMapValue(type, oneRow, "1", result); - } - } - - @Test - public void testGetValue() { - for (Type type : types) { - KuduUtil.getValue("1", type); - } - } -} diff --git a/kudu/kudu-sink/pom.xml b/kudu/kudu-sink/pom.xml index 98c144c5d..9c1bb2a6d 100644 --- a/kudu/kudu-sink/pom.xml +++ b/kudu/kudu-sink/pom.xml @@ -63,14 +63,14 @@ - + - + diff --git a/kudu/kudu-sink/src/main/java/com/dtstack/flink/sql/sink/kudu/KuduOutputFormat.java b/kudu/kudu-sink/src/main/java/com/dtstack/flink/sql/sink/kudu/KuduOutputFormat.java index 24d3322f5..05259ee9b 100644 --- a/kudu/kudu-sink/src/main/java/com/dtstack/flink/sql/sink/kudu/KuduOutputFormat.java +++ b/kudu/kudu-sink/src/main/java/com/dtstack/flink/sql/sink/kudu/KuduOutputFormat.java @@ -18,99 +18,51 @@ package com.dtstack.flink.sql.sink.kudu; -import com.dtstack.flink.sql.exception.ExceptionTrace; -import com.dtstack.flink.sql.factory.DTThreadFactory; -import com.dtstack.flink.sql.outputformat.AbstractDtRichOutputFormat; -import com.dtstack.flink.sql.sink.kudu.table.KuduTableInfo; -import com.dtstack.flink.sql.util.KrbUtils; +import com.dtstack.flink.sql.sink.MetricOutputFormat; import org.apache.flink.api.common.typeinfo.TypeInformation; import org.apache.flink.api.java.tuple.Tuple2; import org.apache.flink.configuration.Configuration; import org.apache.flink.types.Row; -import org.apache.hadoop.security.UserGroupInformation; -import org.apache.kudu.client.KuduClient; -import org.apache.kudu.client.KuduException; -import org.apache.kudu.client.KuduSession; -import org.apache.kudu.client.KuduTable; -import org.apache.kudu.client.Operation; -import org.apache.kudu.client.OperationResponse; -import org.apache.kudu.client.PartialRow; -import org.apache.kudu.client.RowError; -import org.apache.kudu.client.SessionConfiguration; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.apache.kudu.client.*; import java.io.IOException; import java.math.BigDecimal; -import java.security.PrivilegedAction; import java.sql.Timestamp; import java.util.Date; -import java.util.Objects; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * @author gituser - * @modify xiuzhu - */ -public class KuduOutputFormat extends AbstractDtRichOutputFormat> { - private static final long serialVersionUID = 1L; +public class KuduOutputFormat extends MetricOutputFormat { - private static final Logger LOG = LoggerFactory.getLogger(KuduOutputFormat.class); - private static final String MANUAL_FLUSH_BUFFER_BIG_MSG = "MANUAL_FLUSH is enabled but the buffer is too big"; + public enum WriteMode {INSERT, UPDATE, UPSERT} + +// public enum Consistency {EVENTUAL, STRONG} - protected String[] fieldNames; - TypeInformation[] fieldTypes; - boolean enableKrb; private String kuduMasters; + private String tableName; + private WriteMode writeMode; - private KuduClient client; + + protected String[] fieldNames; + + TypeInformation[] fieldTypes; + +// protected List primaryKeys; + +// private Consistency consistency = Consistency.STRONG; + + private AsyncKuduClient client; private KuduTable table; - private volatile KuduSession session; private Integer workerCount; private Integer defaultOperationTimeoutMs; - private int mutationBufferMaxOps; - - /** - * kerberos - */ - private String principal; - private String keytab; - private String krb5conf; - - /** - * batch size - */ - private Integer batchSize; - private Integer batchWaitInterval; - /** - * kudu session flush mode - */ - private String flushMode; - - private transient AtomicInteger rowCount; - - /** - * 定时任务 - */ - private transient ScheduledExecutorService scheduler; - private transient ScheduledFuture scheduledFuture; + private Integer defaultSocketReadTimeoutMs; - private KuduOutputFormat() { - } - public static KuduOutputFormatBuilder buildKuduOutputFormat() { - return new KuduOutputFormatBuilder(); + private KuduOutputFormat() { } @Override @@ -122,203 +74,152 @@ public void configure(Configuration parameters) { public void open(int taskNumber, int numTasks) throws IOException { establishConnection(); initMetric(); - initSchedulerTask(); - rowCount = new AtomicInteger(0); } - /** - * init the scheduler task of {@link KuduOutputFormat#flush()} - */ - private void initSchedulerTask() { - try { - if (batchWaitInterval > 0) { - this.scheduler = new ScheduledThreadPoolExecutor( - 1, - new DTThreadFactory("kudu-batch-flusher") - ); - - this.scheduledFuture = this.scheduler.scheduleWithFixedDelay( - this::flush, batchWaitInterval, batchWaitInterval, TimeUnit.MILLISECONDS); - } - } catch (Exception e) { - LOG.error("init schedule task failed !"); - throw new RuntimeException(e); - } - } - private void establishConnection() throws IOException { - KuduClient.KuduClientBuilder kuduClientBuilder = new KuduClient.KuduClientBuilder(kuduMasters); + private void establishConnection() throws KuduException { + AsyncKuduClient.AsyncKuduClientBuilder asyncKuduClientBuilder = new AsyncKuduClient.AsyncKuduClientBuilder(kuduMasters); if (null != workerCount) { - kuduClientBuilder.workerCount(workerCount); + asyncKuduClientBuilder.workerCount(workerCount); + } + if (null != defaultSocketReadTimeoutMs) { + asyncKuduClientBuilder.workerCount(defaultSocketReadTimeoutMs); } if (null != defaultOperationTimeoutMs) { - kuduClientBuilder.defaultOperationTimeoutMs(defaultOperationTimeoutMs); + asyncKuduClientBuilder.workerCount(defaultOperationTimeoutMs); } + client = asyncKuduClientBuilder.build(); + KuduClient syncClient = client.syncClient(); - if (enableKrb) { - UserGroupInformation ugi = KrbUtils.loginAndReturnUgi( - principal, - keytab, - krb5conf - ); - client = ugi.doAs( - (PrivilegedAction) kuduClientBuilder::build); - } else { - client = kuduClientBuilder.build(); + if (syncClient.tableExists(tableName)) { + table = syncClient.openTable(tableName); } + } - if (client.tableExists(tableName)) { - table = client.openTable(tableName); + @Override + public void writeRecord(Tuple2 record) throws IOException { + Tuple2 tupleTrans = record; + Boolean retract = tupleTrans.getField(0); + if (!retract) { + return; } - if (Objects.isNull(table)) { - throw new IllegalArgumentException( - String.format("Table [%s] Open Failed , please check table exists", tableName)); + Row row = tupleTrans.getField(1); + if (row.getArity() != fieldNames.length) { + return; } - LOG.info("connect kudu is succeed!"); - session = buildSessionWithFlushMode(flushMode, client); + Operation operation = toOperation(writeMode, row); + AsyncKuduSession session = client.newSession(); + session.apply(operation); + session.close(); + outRecords.inc(); } - /** - * According to the different flush mode, build different session. Detail see {@link SessionConfiguration.FlushMode} - * - * @param flushMode flush mode - * @param kuduClient kudu client - * @return KuduSession with flush mode - */ - private KuduSession buildSessionWithFlushMode(String flushMode, KuduClient kuduClient) { - KuduSession kuduSession = kuduClient.newSession(); - if (flushMode.equalsIgnoreCase(KuduTableInfo.KuduFlushMode.MANUAL_FLUSH.name())) { - kuduSession.setFlushMode(SessionConfiguration.FlushMode.MANUAL_FLUSH); - kuduSession.setMutationBufferSpace(mutationBufferMaxOps); + @Override + public void close() { + if (null != client) { + try { + client.close(); + } catch (Exception e) { + throw new IllegalArgumentException("[closeKudu]:" + e.getMessage()); + } } + } + + public static KuduOutputFormatBuilder buildKuduOutputFormat() { + return new KuduOutputFormatBuilder(); + } + + public static class KuduOutputFormatBuilder { + private final KuduOutputFormat kuduOutputFormat; - if (flushMode.equalsIgnoreCase(KuduTableInfo.KuduFlushMode.AUTO_FLUSH_SYNC.name())) { - LOG.warn("Parameter [batchSize] will not take effect at AUTO_FLUSH_SYNC mode."); - kuduSession.setFlushMode(SessionConfiguration.FlushMode.AUTO_FLUSH_SYNC); + protected KuduOutputFormatBuilder() { + this.kuduOutputFormat = new KuduOutputFormat(); } - if (flushMode.equalsIgnoreCase(KuduTableInfo.KuduFlushMode.AUTO_FLUSH_BACKGROUND.name())) { - LOG.warn("Unable to determine the order of data at AUTO_FLUSH_BACKGROUND mode. Only [batchWaitInterval] will effect."); - kuduSession.setFlushMode(SessionConfiguration.FlushMode.AUTO_FLUSH_BACKGROUND); - kuduSession.setFlushInterval(batchWaitInterval); + public KuduOutputFormatBuilder setKuduMasters(String kuduMasters) { + kuduOutputFormat.kuduMasters = kuduMasters; + return this; } - return kuduSession; - } + public KuduOutputFormatBuilder setTableName(String tableName) { + kuduOutputFormat.tableName = tableName; + return this; + } - @Override - public void writeRecord(Tuple2 record) throws IOException { - Boolean retract = record.getField(0); - if (!retract) { - return; + + public KuduOutputFormatBuilder setFieldNames(String[] fieldNames) { + kuduOutputFormat.fieldNames = fieldNames; + return this; } - Row row = record.getField(1); - try { - if (rowCount.getAndIncrement() >= batchSize) { - flush(); - } - // At AUTO_FLUSH_SYNC mode, kudu automatically flush once session apply operation, then get the response from kudu server. - if (flushMode.equalsIgnoreCase(SessionConfiguration.FlushMode.AUTO_FLUSH_SYNC.name())) { - dealResponse(session.apply(toOperation(writeMode, row))); - } else { - session.apply(toOperation(writeMode, row)); - } - outRecords.inc(); - if (outRecords.getCount() % ROW_PRINT_FREQUENCY == 0) { - LOG.info("Receive data : {}", row); - } - } catch (KuduException e) { - // 如果出现了buffer is too big的问题,需要将当前buffer里的数据flush掉即可。 - if (ExceptionTrace.traceOriginalCause(e).contains(MANUAL_FLUSH_BUFFER_BIG_MSG)) { - flush(); - } else { - throw new RuntimeException(e); - } + public KuduOutputFormatBuilder setFieldTypes(TypeInformation[] fieldTypes) { + kuduOutputFormat.fieldTypes = fieldTypes; + return this; } - } +// +// public KuduOutputFormatBuilder setPrimaryKeys(List primaryKeys) { +// kuduOutputFormat.primaryKeys = primaryKeys; +// return this; +// } - /** - * Flush data with session, then deal the responses of operations and reset rowCount. - * Detail of flush see {@link KuduSession#flush()} - */ - private synchronized void flush() { - try { - if (session.isClosed()) { - throw new IllegalStateException("Session is closed! Flush data error!"); + public KuduOutputFormatBuilder setWriteMode(WriteMode writeMode) { + if (null == writeMode) { + kuduOutputFormat.writeMode = WriteMode.UPSERT; } + kuduOutputFormat.writeMode = writeMode; + return this; + } - // At AUTO_FLUSH_SYNC mode, kudu automatically flush once session apply operation - if (flushMode.equalsIgnoreCase(SessionConfiguration.FlushMode.AUTO_FLUSH_SYNC.name())) { - return; - } - session.flush().forEach(this::dealResponse); - // clear - rowCount.set(0); - } catch (KuduException kuduException) { - LOG.error("flush data error!", kuduException); - throw new RuntimeException(kuduException); + public KuduOutputFormatBuilder setWorkerCount(Integer workerCount) { + kuduOutputFormat.workerCount = workerCount; + return this; } - } - /** - * Deal response when operation apply. - * At MANUAL_FLUSH mode, response returns after {@link KuduSession#flush()}. - * But at AUTO_FLUSH_SYNC mode, response returns after {@link KuduSession#apply(Operation)} - * - * @param response {@link OperationResponse} response after operation done. - */ - private void dealResponse(OperationResponse response) { - if (response.hasRowError()) { - RowError error = response.getRowError(); - String errorMsg = error.getErrorStatus().toString(); - if (outDirtyRecords.getCount() % DIRTY_PRINT_FREQUENCY == 0) { - LOG.error(errorMsg); - LOG.error(String.format("Dirty data count: [%s]. Row data: [%s]", - outDirtyRecords.getCount() + 1, error.getOperation().getRow().toString())); - } - outDirtyRecords.inc(); - - if (error.getErrorStatus().isNotFound() - || error.getErrorStatus().isIOError() - || error.getErrorStatus().isRuntimeError() - || error.getErrorStatus().isServiceUnavailable() - || error.getErrorStatus().isIllegalState()) { - throw new RuntimeException(errorMsg); - } +// public KuduOutputFormatBuilder setConsistency(String consistency) { +// switch (consistency) { +// case "EVENTUAL": +// kuduOutputFormat.consistency = Consistency.EVENTUAL; +// break; +// case "STRONG": +// kuduOutputFormat.consistency = Consistency.STRONG; +// break; +// default: +// kuduOutputFormat.consistency = Consistency.STRONG; +// } +// return this; +// } + + + public KuduOutputFormatBuilder setDefaultOperationTimeoutMs(Integer defaultOperationTimeoutMs) { + kuduOutputFormat.defaultOperationTimeoutMs = defaultOperationTimeoutMs; + return this; } - } - @Override - public void close() { - if (Objects.nonNull(session) && !session.isClosed()) { - try { - session.close(); - } catch (Exception e) { - throw new IllegalArgumentException("[closeKuduSession]: " + e.getMessage()); - } + public KuduOutputFormatBuilder setDefaultSocketReadTimeoutMs(Integer defaultSocketReadTimeoutMs) { + kuduOutputFormat.defaultSocketReadTimeoutMs = defaultSocketReadTimeoutMs; + return this; } - if (null != client) { - try { - client.shutdown(); - } catch (Exception e) { - throw new IllegalArgumentException("[closeKuduClient]:" + e.getMessage()); + + public KuduOutputFormat finish() { + if (kuduOutputFormat.kuduMasters == null) { + throw new IllegalArgumentException("No kuduMasters supplied."); } - } - if (scheduledFuture != null) { - scheduledFuture.cancel(false); - } + if (kuduOutputFormat.tableName == null) { + throw new IllegalArgumentException("No tablename supplied."); + } - if (scheduler != null) { - scheduler.shutdownNow(); + return kuduOutputFormat; } } private Operation toOperation(WriteMode writeMode, Row row) { + if (null == table) { + throw new IllegalArgumentException("Table Open Failed , please check table exists"); + } Operation operation = toOperation(writeMode); PartialRow partialRow = operation.getRow(); @@ -397,117 +298,11 @@ private Operation toOperation(WriteMode writeMode) { return table.newInsert(); case UPDATE: return table.newUpdate(); + case UPSERT: + return table.newUpsert(); default: return table.newUpsert(); } } - public enum WriteMode { - // insert - INSERT, - // update - UPDATE, - // update or insert - UPSERT - } - - public static class KuduOutputFormatBuilder { - private final KuduOutputFormat kuduOutputFormat; - - protected KuduOutputFormatBuilder() { - this.kuduOutputFormat = new KuduOutputFormat(); - } - - public KuduOutputFormatBuilder setKuduMasters(String kuduMasters) { - kuduOutputFormat.kuduMasters = kuduMasters; - return this; - } - - public KuduOutputFormatBuilder setTableName(String tableName) { - kuduOutputFormat.tableName = tableName; - return this; - } - - - public KuduOutputFormatBuilder setFieldNames(String[] fieldNames) { - kuduOutputFormat.fieldNames = fieldNames; - return this; - } - - public KuduOutputFormatBuilder setFieldTypes(TypeInformation[] fieldTypes) { - kuduOutputFormat.fieldTypes = fieldTypes; - return this; - } - - public KuduOutputFormatBuilder setWriteMode(WriteMode writeMode) { - if (null == writeMode) { - kuduOutputFormat.writeMode = WriteMode.UPSERT; - } - kuduOutputFormat.writeMode = writeMode; - return this; - } - - public KuduOutputFormatBuilder setWorkerCount(Integer workerCount) { - kuduOutputFormat.workerCount = workerCount; - return this; - } - - public KuduOutputFormatBuilder setDefaultOperationTimeoutMs(Integer defaultOperationTimeoutMs) { - kuduOutputFormat.defaultOperationTimeoutMs = defaultOperationTimeoutMs; - return this; - } - - public KuduOutputFormatBuilder setPrincipal(String principal) { - kuduOutputFormat.principal = principal; - return this; - } - - public KuduOutputFormatBuilder setKeytab(String keytab) { - kuduOutputFormat.keytab = keytab; - return this; - } - - public KuduOutputFormatBuilder setKrb5conf(String krb5conf) { - kuduOutputFormat.krb5conf = krb5conf; - return this; - } - - public KuduOutputFormatBuilder setEnableKrb(boolean enableKrb) { - kuduOutputFormat.enableKrb = enableKrb; - return this; - } - - public KuduOutputFormatBuilder setBatchSize(Integer batchSize) { - kuduOutputFormat.batchSize = batchSize; - return this; - } - - public KuduOutputFormatBuilder setBatchWaitInterval(Integer batchWaitInterval) { - kuduOutputFormat.batchWaitInterval = batchWaitInterval; - return this; - } - - public KuduOutputFormatBuilder setFlushMode(String flushMode) { - kuduOutputFormat.flushMode = flushMode; - return this; - } - - public KuduOutputFormatBuilder setMutationBufferMaxOps(Integer mutationBufferMaxOps) { - kuduOutputFormat.mutationBufferMaxOps = mutationBufferMaxOps; - return this; - } - - public KuduOutputFormat finish() { - if (kuduOutputFormat.kuduMasters == null) { - throw new IllegalArgumentException("No kuduMasters supplied."); - } - - if (kuduOutputFormat.tableName == null) { - throw new IllegalArgumentException("No tablename supplied."); - } - - return kuduOutputFormat; - } - } - } \ No newline at end of file diff --git a/kudu/kudu-sink/src/main/java/com/dtstack/flink/sql/sink/kudu/KuduSink.java b/kudu/kudu-sink/src/main/java/com/dtstack/flink/sql/sink/kudu/KuduSink.java index 1ca28b866..24dff85ae 100644 --- a/kudu/kudu-sink/src/main/java/com/dtstack/flink/sql/sink/kudu/KuduSink.java +++ b/kudu/kudu-sink/src/main/java/com/dtstack/flink/sql/sink/kudu/KuduSink.java @@ -3,13 +3,12 @@ import com.dtstack.flink.sql.sink.IStreamSinkGener; import com.dtstack.flink.sql.sink.kudu.table.KuduTableInfo; -import com.dtstack.flink.sql.table.AbstractTargetTableInfo; +import com.dtstack.flink.sql.table.TargetTableInfo; import org.apache.flink.api.common.typeinfo.TypeInformation; import org.apache.flink.api.java.tuple.Tuple2; import org.apache.flink.api.java.typeutils.RowTypeInfo; import org.apache.flink.api.java.typeutils.TupleTypeInfo; import org.apache.flink.streaming.api.datastream.DataStream; -import org.apache.flink.streaming.api.datastream.DataStreamSink; import org.apache.flink.streaming.api.functions.sink.OutputFormatSinkFunction; import org.apache.flink.streaming.api.functions.sink.RichSinkFunction; import org.apache.flink.table.sinks.RetractStreamTableSink; @@ -17,82 +16,59 @@ import org.apache.flink.types.Row; import java.io.Serializable; -import java.util.Objects; public class KuduSink implements RetractStreamTableSink, Serializable, IStreamSinkGener { - protected String[] fieldNames; - TypeInformation[] fieldTypes; - boolean enableKrb; private String kuduMasters; + private String tableName; + private KuduOutputFormat.WriteMode writeMode; + + protected String[] fieldNames; + + TypeInformation[] fieldTypes; + +// protected List primaryKeys; + +// private KuduOutputFormat.Consistency consistency = KuduOutputFormat.Consistency.STRONG; + + private Integer workerCount; + private Integer defaultOperationTimeoutMs; - private int parallelism = 1; - private String principal; - private String keytab; - private String krb5conf; - private Integer batchSize; - private Integer batchWaitInterval; - private String flushMode; - private Integer mutationBufferMaxOps; + + private Integer defaultSocketReadTimeoutMs; + + private int parallelism = -1; @Override - public KuduSink genStreamSink(AbstractTargetTableInfo targetTableInfo) { + public KuduSink genStreamSink(TargetTableInfo targetTableInfo) { KuduTableInfo kuduTableInfo = (KuduTableInfo) targetTableInfo; this.kuduMasters = kuduTableInfo.getKuduMasters(); this.tableName = kuduTableInfo.getTableName(); this.defaultOperationTimeoutMs = kuduTableInfo.getDefaultOperationTimeoutMs(); + this.defaultSocketReadTimeoutMs = kuduTableInfo.getDefaultSocketReadTimeoutMs(); this.workerCount = kuduTableInfo.getWorkerCount(); this.writeMode = kuduTableInfo.getWriteMode(); - this.principal = kuduTableInfo.getPrincipal(); - this.keytab = kuduTableInfo.getKeytab(); - this.krb5conf = kuduTableInfo.getKrb5conf(); - this.enableKrb = kuduTableInfo.isEnableKrb(); - this.parallelism = Objects.isNull(kuduTableInfo.getParallelism()) ? - parallelism : kuduTableInfo.getParallelism(); - - this.batchSize = kuduTableInfo.getBatchSize(); - this.batchWaitInterval = kuduTableInfo.getBatchWaitInterval(); - this.flushMode = kuduTableInfo.getFlushMode(); - this.mutationBufferMaxOps = Objects.isNull(kuduTableInfo.getMutationBufferMaxOps()) ? - Integer.parseInt(String.valueOf(Math.round(batchSize * 1.2))) : - kuduTableInfo.getMutationBufferMaxOps(); + return this; } @Override public void emitDataStream(DataStream> dataStream) { - consumeDataStream(dataStream); - } - - @Override - public DataStreamSink> consumeDataStream(DataStream> dataStream) { KuduOutputFormat.KuduOutputFormatBuilder builder = KuduOutputFormat.buildKuduOutputFormat(); - KuduOutputFormat kuduOutputFormat = builder.setKuduMasters(this.kuduMasters) + builder.setKuduMasters(this.kuduMasters) .setTableName(this.tableName) .setWriteMode(writeMode) .setWorkerCount(this.workerCount) .setDefaultOperationTimeoutMs(this.defaultOperationTimeoutMs) + .setDefaultSocketReadTimeoutMs(this.defaultSocketReadTimeoutMs) .setFieldNames(this.fieldNames) - .setFieldTypes(this.fieldTypes) - .setPrincipal(this.principal) - .setKeytab(this.keytab) - .setKrb5conf(this.krb5conf) - .setEnableKrb(this.enableKrb) - .setBatchSize(this.batchSize) - .setBatchWaitInterval(this.batchWaitInterval) - .setFlushMode(this.flushMode) - .setMutationBufferMaxOps(this.mutationBufferMaxOps) - .finish(); + .setFieldTypes(this.fieldTypes); + KuduOutputFormat kuduOutputFormat = builder.finish(); RichSinkFunction richSinkFunction = new OutputFormatSinkFunction(kuduOutputFormat); - DataStreamSink dataStreamSink = dataStream.addSink(richSinkFunction); - dataStreamSink.name(tableName); - if (parallelism > 0) { - dataStreamSink.setParallelism(parallelism); - } - return dataStreamSink; + dataStream.addSink(richSinkFunction); } @Override @@ -102,6 +78,7 @@ public TableSink> configure(String[] fieldNames, TypeInform return this; } + @Override public TupleTypeInfo> getOutputType() { return new TupleTypeInfo(org.apache.flink.table.api.Types.BOOLEAN(), getRecordType()); diff --git a/kudu/kudu-sink/src/main/java/com/dtstack/flink/sql/sink/kudu/table/KuduSinkParser.java b/kudu/kudu-sink/src/main/java/com/dtstack/flink/sql/sink/kudu/table/KuduSinkParser.java index ac0c26900..f304c14b5 100644 --- a/kudu/kudu-sink/src/main/java/com/dtstack/flink/sql/sink/kudu/table/KuduSinkParser.java +++ b/kudu/kudu-sink/src/main/java/com/dtstack/flink/sql/sink/kudu/table/KuduSinkParser.java @@ -1,20 +1,15 @@ package com.dtstack.flink.sql.sink.kudu.table; -import com.dtstack.flink.sql.constant.PluginParamConsts; import com.dtstack.flink.sql.sink.kudu.KuduOutputFormat; -import com.dtstack.flink.sql.table.AbstractTableInfo; -import com.dtstack.flink.sql.table.AbstractTableParser; +import com.dtstack.flink.sql.table.AbsTableParser; +import com.dtstack.flink.sql.table.TableInfo; import com.dtstack.flink.sql.util.MathUtil; -import java.math.BigDecimal; -import java.sql.Date; -import java.sql.Timestamp; import java.util.Map; -import java.util.Objects; -import static com.dtstack.flink.sql.table.AbstractTableInfo.PARALLELISM_KEY; +import static com.dtstack.flink.sql.table.TableInfo.PARALLELISM_KEY; -public class KuduSinkParser extends AbstractTableParser { +public class KuduSinkParser extends AbsTableParser { public static final String KUDU_MASTERS = "kuduMasters"; @@ -26,20 +21,10 @@ public class KuduSinkParser extends AbstractTableParser { public static final String OPERATION_TIMEOUT_MS = "defaultOperationTimeoutMs"; - public static final String BATCH_SIZE_KEY = "batchSize"; - - public static final Integer DEFAULT_BATCH_SIZE = 1000; - - public static final String BATCH_WAIT_INTERVAL_KEY = "batchWaitInterval"; - - public static final String BUFFER_MAX_KEY = "mutationBufferMaxOps"; - - public static final Integer DEFAULT_BATCH_WAIT_INTERVAL = 60 * 1000; - - public static final String SESSION_FLUSH_MODE_KEY = "flushMode"; + public static final String SOCKET_READ_TIMEOUT_MS = "defaultSocketReadTimeoutMs"; @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { + public TableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { KuduTableInfo kuduTableInfo = new KuduTableInfo(); kuduTableInfo.setName(tableName); parseFieldsInfo(fieldsInfo, kuduTableInfo); @@ -50,31 +35,7 @@ public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map 1) { - kuduTableInfo.setFlushMode(KuduTableInfo.KuduFlushMode.MANUAL_FLUSH.name()); - } else { - kuduTableInfo.setFlushMode(KuduTableInfo.KuduFlushMode.AUTO_FLUSH_SYNC.name()); - } - } else { - kuduTableInfo.setFlushMode(MathUtil.getString(props.get(SESSION_FLUSH_MODE_KEY.toLowerCase()))); - } - - kuduTableInfo.setPrincipal( - MathUtil.getString(props.get(PluginParamConsts.PRINCIPAL)) - ); - kuduTableInfo.setKeytab( - MathUtil.getString(props.get(PluginParamConsts.KEYTAB)) - ); - kuduTableInfo.setKrb5conf( - MathUtil.getString(props.get(PluginParamConsts.KRB5_CONF)) - ); - kuduTableInfo.judgeKrbEnable(); - + kuduTableInfo.setDefaultSocketReadTimeoutMs(MathUtil.getIntegerVal(props.get(SOCKET_READ_TIMEOUT_MS.toLowerCase()))); return kuduTableInfo; } @@ -84,46 +45,10 @@ private KuduOutputFormat.WriteMode transWriteMode(String writeMode) { return KuduOutputFormat.WriteMode.INSERT; case "update": return KuduOutputFormat.WriteMode.UPDATE; - default: + case "upsert": return KuduOutputFormat.WriteMode.UPSERT; - } - } - - @Override - public Class dbTypeConvertToJavaType(String fieldType) { - switch (fieldType.toLowerCase()) { - case "boolean": - case "bool": - return Boolean.class; - case "int8": - return Byte.class; - case "int16": - return Short.class; - case "int": - case "int32": - return Integer.class; - case "long": - case "int64": - return Long.class; - case "varchar": - case "string": - return String.class; - case "float": - return Float.class; - case "double": - return Double.class; - case "date": - return Date.class; - case "unixtime_micros": - case "timestamp": - return Timestamp.class; - case "decimal": - return BigDecimal.class; - case "binary": - return byte[].class; default: + return KuduOutputFormat.WriteMode.UPSERT; } - - throw new RuntimeException("不支持 " + fieldType + " 类型"); } } diff --git a/kudu/kudu-sink/src/main/java/com/dtstack/flink/sql/sink/kudu/table/KuduTableInfo.java b/kudu/kudu-sink/src/main/java/com/dtstack/flink/sql/sink/kudu/table/KuduTableInfo.java index 3483c6e89..ed0b956a7 100644 --- a/kudu/kudu-sink/src/main/java/com/dtstack/flink/sql/sink/kudu/table/KuduTableInfo.java +++ b/kudu/kudu-sink/src/main/java/com/dtstack/flink/sql/sink/kudu/table/KuduTableInfo.java @@ -1,11 +1,10 @@ package com.dtstack.flink.sql.sink.kudu.table; -import com.dtstack.flink.sql.krb.KerberosTable; import com.dtstack.flink.sql.sink.kudu.KuduOutputFormat; -import com.dtstack.flink.sql.table.AbstractTargetTableInfo; -import com.google.common.base.Preconditions; +import com.dtstack.flink.sql.table.TargetTableInfo; +import org.apache.flink.calcite.shaded.com.google.common.base.Preconditions; -public class KuduTableInfo extends AbstractTargetTableInfo implements KerberosTable { +public class KuduTableInfo extends TargetTableInfo { private static final String CURR_TYPE = "kudu"; @@ -15,33 +14,21 @@ public class KuduTableInfo extends AbstractTargetTableInfo implements KerberosTa private KuduOutputFormat.WriteMode writeMode; + +// private KuduOutputFormat.Consistency consistency = KuduOutputFormat.Consistency.STRONG; + + private Integer workerCount; private Integer defaultOperationTimeoutMs; - private Integer mutationBufferMaxOps; - - /** - * kerberos - */ - private String principal; - private String keytab; - private String krb5conf; - boolean enableKrb; - /** - * batchSize - */ - private Integer batchSize; - private Integer batchWaitInterval; - /** - * kudu session flush mode - */ - private String flushMode; + private Integer defaultSocketReadTimeoutMs; public KuduTableInfo() { setType(CURR_TYPE); } + public String getKuduMasters() { return kuduMasters; } @@ -82,93 +69,24 @@ public void setDefaultOperationTimeoutMs(Integer defaultOperationTimeoutMs) { this.defaultOperationTimeoutMs = defaultOperationTimeoutMs; } - public Integer getMutationBufferMaxOps() { - return mutationBufferMaxOps; + public Integer getDefaultSocketReadTimeoutMs() { + return defaultSocketReadTimeoutMs; } - public void setMutationBufferMaxOps(Integer mutationBufferMaxOps) { - this.mutationBufferMaxOps = mutationBufferMaxOps; + public void setDefaultSocketReadTimeoutMs(Integer defaultSocketReadTimeoutMs) { + this.defaultSocketReadTimeoutMs = defaultSocketReadTimeoutMs; } @Override public boolean check() { - Preconditions.checkNotNull(kuduMasters, "kudu field of kuduMasters is required"); - Preconditions.checkNotNull(tableName, "kudu field of tableName is required"); + Preconditions.checkNotNull(kuduMasters, "Cassandra field of kuduMasters is required"); + Preconditions.checkNotNull(tableName, "Cassandra field of tableName is required"); return true; } @Override public String getType() { + // return super.getType().toLowerCase() + TARGET_SUFFIX; return super.getType().toLowerCase(); } - - @Override - public String getPrincipal() { - return principal; - } - - @Override - public void setPrincipal(String principal) { - this.principal = principal; - } - - @Override - public String getKeytab() { - return keytab; - } - - @Override - public void setKeytab(String keytab) { - this.keytab = keytab; - } - - @Override - public String getKrb5conf() { - return krb5conf; - } - - @Override - public void setKrb5conf(String krb5conf) { - this.krb5conf = krb5conf; - } - - @Override - public boolean isEnableKrb() { - return enableKrb; - } - - @Override - public void setEnableKrb(boolean enableKrb) { - this.enableKrb = enableKrb; - } - - public Integer getBatchSize() { - return batchSize; - } - - public void setBatchSize(Integer batchSize) { - this.batchSize = batchSize; - } - - public Integer getBatchWaitInterval() { - return batchWaitInterval; - } - - public void setBatchWaitInterval(Integer batchWaitInterval) { - this.batchWaitInterval = batchWaitInterval; - } - - public String getFlushMode() { - return flushMode; - } - - public void setFlushMode(String flushMode) { - this.flushMode = flushMode; - } - - public enum KuduFlushMode { - AUTO_FLUSH_SYNC, - AUTO_FLUSH_BACKGROUND, - MANUAL_FLUSH - } } diff --git a/kudu/kudu-sink/src/test/java/com/dtstack/flink/sql/sink/kudu/KuduOutputFormatTest.java b/kudu/kudu-sink/src/test/java/com/dtstack/flink/sql/sink/kudu/KuduOutputFormatTest.java deleted file mode 100644 index 8ba362123..000000000 --- a/kudu/kudu-sink/src/test/java/com/dtstack/flink/sql/sink/kudu/KuduOutputFormatTest.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.kudu; - -import com.dtstack.flink.sql.outputformat.AbstractDtRichOutputFormat; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.metrics.Counter; -import org.apache.flink.types.Row; -import org.apache.kudu.client.*; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.InjectMocks; -import org.mockito.MockitoAnnotations; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import org.powermock.reflect.Whitebox; - -import java.io.IOException; - -import static org.mockito.Mockito.mock; -import static org.powermock.api.mockito.PowerMockito.when; -import static org.powermock.api.mockito.PowerMockito.whenNew; -import static org.powermock.api.support.membermodification.MemberModifier.suppress; - -/** - * @author: chuixue - * @create: 2020-08-10 10:24 - * @description: - **/ -//@RunWith(PowerMockRunner.class) -//@PrepareForTest({ -// KuduOutputFormat.class -// , AsyncKuduClient.AsyncKuduClientBuilder.class -// , AsyncKuduClient.class -// , KuduClient.class -// , AbstractDtRichOutputFormat.class}) -public class KuduOutputFormatTest { - - @InjectMocks - private KuduOutputFormat kuduOutputFormat; - private AsyncKuduClient client = mock(AsyncKuduClient.class); - private Counter outRecords = mock(Counter.class); - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - Whitebox.setInternalState(kuduOutputFormat, "client", client); - Whitebox.setInternalState(kuduOutputFormat, "outRecords", outRecords); - } - -// @Test - public void testOpen() throws Exception { - AsyncKuduClient.AsyncKuduClientBuilder asyncKuduClientBuilder = mock(AsyncKuduClient.AsyncKuduClientBuilder.class); - KuduClient syncClient = mock(KuduClient.class); - - whenNew(AsyncKuduClient.AsyncKuduClientBuilder.class).withArguments("ip1,ip2,ip3").thenReturn(asyncKuduClientBuilder); - suppress(AbstractDtRichOutputFormat.class.getMethod("initMetric")); - when(asyncKuduClientBuilder.build()).thenReturn(client); - when(client.syncClient()).thenReturn(syncClient); - when(syncClient.tableExists("tableName")).thenReturn(true); - - Whitebox.setInternalState(kuduOutputFormat, "tableName", "tableName"); - Whitebox.setInternalState(kuduOutputFormat, "kuduMasters", "ip1,ip2,ip3"); - Whitebox.setInternalState(kuduOutputFormat, "workerCount", 2); - Whitebox.setInternalState(kuduOutputFormat, "defaultSocketReadTimeoutMs", 600000); - Whitebox.setInternalState(kuduOutputFormat, "defaultOperationTimeoutMs", 600000); - kuduOutputFormat.open(10, 10); - } - -// @Test - public void testWriteRecord() throws IOException { - KuduTable table = mock(KuduTable.class); - Upsert operation = mock(Upsert.class); - PartialRow partialRow = mock(PartialRow.class); - AsyncKuduSession session = mock(AsyncKuduSession.class); - String[] fieldNames = new String[]{"a", "b", "C", "d"}; - TypeInformation[] fieldTypes = new TypeInformation[]{TypeInformation.of(Integer.class), TypeInformation.of(String.class), TypeInformation.of(Float.class), TypeInformation.of(Long.class)}; - - Row row = new Row(4); - row.setField(0, 1); - row.setField(1, "ddd"); - row.setField(2, 10f); - row.setField(3, 12L); - Tuple2 record = new Tuple2(); - record.f0 = true; - record.f1 = row; - - Whitebox.setInternalState(kuduOutputFormat, "writeMode", KuduOutputFormat.WriteMode.UPSERT); - Whitebox.setInternalState(kuduOutputFormat, "fieldNames", fieldNames); - Whitebox.setInternalState(kuduOutputFormat, "table", table); - Whitebox.setInternalState(kuduOutputFormat, "fieldTypes", fieldTypes); - - when(table.newUpsert()).thenReturn(operation); - when(operation.getRow()).thenReturn(partialRow); - when(client.newSession()).thenReturn(session); - - kuduOutputFormat.writeRecord(record); - } - -// @Test - public void testClose(){ - kuduOutputFormat.close(); - } -} diff --git a/kudu/kudu-sink/src/test/java/com/dtstack/flink/sql/sink/kudu/KuduSinkTest.java b/kudu/kudu-sink/src/test/java/com/dtstack/flink/sql/sink/kudu/KuduSinkTest.java deleted file mode 100644 index b9388ff6e..000000000 --- a/kudu/kudu-sink/src/test/java/com/dtstack/flink/sql/sink/kudu/KuduSinkTest.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.kudu; - -import com.dtstack.flink.sql.sink.kudu.table.KuduTableInfo; -import org.apache.flink.streaming.api.datastream.DataStream; -import org.apache.flink.streaming.api.datastream.DataStreamSink; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.modules.junit4.PowerMockRunner; -import org.powermock.reflect.Whitebox; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.powermock.api.mockito.PowerMockito.when; - -/** - * @author: chuixue - * @create: 2020-08-10 10:09 - * @description: - **/ -@RunWith(PowerMockRunner.class) -public class KuduSinkTest { - KuduSink kuduSink; - - @Before - public void setUp() { - kuduSink = new KuduSink(); - } - - @Test - public void testGenStreamSink() { - KuduTableInfo kuduTableInfo = mock(KuduTableInfo.class); - when(kuduTableInfo.getKuduMasters()).thenReturn("ip1,ip2,ip3"); - when(kuduTableInfo.getTableName()).thenReturn("impala::default.test"); - kuduSink.genStreamSink(kuduTableInfo); - } - - @Test - public void testeEmitDataStream() { - DataStream dataStream = mock(DataStream.class); - DataStreamSink dataStreamSink = mock(DataStreamSink.class); - when(dataStream.addSink(any())).thenReturn(dataStreamSink); - Whitebox.setInternalState(kuduSink, "tableName", "tableName"); - Whitebox.setInternalState(kuduSink, "kuduMasters", "kuduMasters"); - kuduSink.emitDataStream(dataStream); - } -} diff --git a/kudu/kudu-sink/src/test/java/com/dtstack/flink/sql/sink/kudu/table/KuduSinkParserTest.java b/kudu/kudu-sink/src/test/java/com/dtstack/flink/sql/sink/kudu/table/KuduSinkParserTest.java deleted file mode 100644 index 456a9ac5a..000000000 --- a/kudu/kudu-sink/src/test/java/com/dtstack/flink/sql/sink/kudu/table/KuduSinkParserTest.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.kudu.table; - -import com.google.common.collect.Maps; -import org.junit.Test; - -import java.util.Map; - -import static org.junit.Assert.assertEquals; - -/** - * @author: chuixue - * @create: 2020-08-10 11:17 - * @description: - **/ -public class KuduSinkParserTest { - private KuduSinkParser parser = new KuduSinkParser(); - - @Test - public void testGetTableInfo() { - Map props = Maps.newHashMap(); - props.put("parallelism", "12"); - props.put("kuduMasters", "localhost"); - props.put("tableName", "tableName"); - props.put("writemode", "update"); - props.put("workerCount", "12"); - props.put("defaultOperationTimeoutMs", "111"); - props.put("defaultSocketReadTimeoutMs", "333"); - - parser.getTableInfo("Mykafka", " mid int , mbb varchar, sid varchar, sbb varchar ", props); - - assertEquals(parser, parser); - } - - @Test - public void testDbTypeConvertToJavaType() { - String[] types = new String[]{"boolean", "int8", "int16", "int32", "long", "string", "float", "double", "date", "unixtime_micros", "decimal", "binary"}; - for (String type : types) { - parser.dbTypeConvertToJavaType(type); - } - } -} diff --git a/kudu/pom.xml b/kudu/pom.xml index b8afac87f..e29c233c1 100644 --- a/kudu/pom.xml +++ b/kudu/pom.xml @@ -19,6 +19,12 @@ + + junit + junit + 3.8.1 + test + com.dtstack.flink @@ -30,7 +36,7 @@ org.apache.kudu kudu-client - 1.10.1 + 1.9.0 diff --git a/launcher/job/sideSql.txt b/launcher/job/sideSql.txt index c4bb76a32..35a4be1e7 100644 --- a/launcher/job/sideSql.txt +++ b/launcher/job/sideSql.txt @@ -1,35 +1,72 @@ -CREATE TABLE STREAM_FIELD20( - after.id int AS id, - after.field02 varchar AS field02, - after.field03 varchar AS field03, - after.field04 varchar AS field04, - after.field05 varchar AS field05, - after.field06 varchar AS field06 +CREATE TABLE MyTable( + name string, + channel STRING, + pv INT, + xctime bigint, + CHARACTER_LENGTH(channel) AS timeLeng )WITH( - type ='kafka10', - bootstrapServers ='172.16.101.247:9092', - zookeeperQuorum ='172.16.101.247:2181,172.16.101.141:2181,172.16.100.214:2181/kafka', + type ='kafka09', + bootstrapServers ='172.16.8.198:9092', + zookeeperQuorum ='172.16.8.198:2181/kafka', offsetReset ='latest', - topic ='toutiantest', - timezone='Asia/Shanghai', - topicIsPattern ='false', + topic ='nbTest1', parallelism ='1' ); -CREATE TABLE RESULT_FIELD20( - id INT, - field02 VARCHAR, - PRIMARY KEY(id) +CREATE TABLE MyResult( + channel VARCHAR, + pv VARCHAR )WITH( - type='console' + type ='mysql', + url ='jdbc:mysql://172.16.8.104:3306/test?charset=utf8', + userName ='dtstack', + password ='abc123', + tableName ='pv2', + parallelism ='1' + ); + +CREATE TABLE workerinfo( + cast(logtime as TIMESTAMP)AS rtime, + cast(logtime)AS rtime + )WITH( + type ='hbase', + zookeeperQuorum ='rdos1:2181', + tableName ='workerinfo', + rowKey ='ce,de', + parallelism ='1', + zookeeperParent ='/hbase' ); +CREATE TABLE sideTable( + cf:name String as name, + cf:info String as info, + PRIMARY KEY(name), + PERIOD FOR SYSTEM_TIME + )WITH( + type ='hbase', + zookeeperQuorum ='rdos1:2181', + zookeeperParent ='/hbase', + tableName ='workerinfo', + cache ='LRU', + cacheSize ='10000', + cacheTTLMs ='60000', + parallelism ='1' + ); insert into - RESULT_FIELD20 - SELECT - a.id AS id, - a.field02 as field02 + MyResult + select + d.channel, + d.info from - STREAM_FIELD20 a \ No newline at end of file + ( select + a.*,b.info + from + MyTable a + join + sideTable b + on a.channel=b.name + where + a.channel = 'xc2' + and a.pv=10 ) as d diff --git a/launcher/pom.xml b/launcher/pom.xml index 7722bb203..4c6334411 100644 --- a/launcher/pom.xml +++ b/launcher/pom.xml @@ -10,6 +10,7 @@ 4.0.0 sql.launcher + com.dtstack.flink @@ -30,10 +31,11 @@ - org.slf4j - slf4j-log4j12 - 1.6.1 + com.alibaba + fastjson + 1.2.25 + diff --git a/launcher/src/main/java/com/dtstack/flink/sql/launcher/ClusterClientFactory.java b/launcher/src/main/java/com/dtstack/flink/sql/launcher/ClusterClientFactory.java new file mode 100644 index 000000000..ffabc7002 --- /dev/null +++ b/launcher/src/main/java/com/dtstack/flink/sql/launcher/ClusterClientFactory.java @@ -0,0 +1,279 @@ +/** + * 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 com.dtstack.flink.sql.launcher; + +import com.dtstack.flink.sql.option.Options; +import com.dtstack.flink.sql.util.PluginUtil; +import com.dtstack.flink.sql.yarn.JobParameter; +import com.dtstack.flink.sql.yarn.YarnClusterConfiguration; +import org.apache.commons.io.Charsets; +import org.apache.commons.lang.StringUtils; +import org.apache.flink.client.program.ClusterClient; +import org.apache.flink.client.program.MiniClusterClient; +import org.apache.flink.configuration.ConfigConstants; +import org.apache.flink.configuration.Configuration; +import org.apache.flink.configuration.GlobalConfiguration; +import org.apache.flink.configuration.JobManagerOptions; +import org.apache.flink.core.fs.FileSystem; +import org.apache.flink.runtime.akka.AkkaUtils; +import org.apache.flink.runtime.minicluster.MiniCluster; +import org.apache.flink.runtime.minicluster.MiniClusterConfiguration; +import org.apache.flink.runtime.util.LeaderConnectionInfo; +import org.apache.flink.yarn.AbstractYarnClusterDescriptor; +import org.apache.flink.yarn.YarnClusterDescriptor; +import org.apache.hadoop.fs.Path; +import org.apache.hadoop.yarn.api.records.ApplicationId; +import org.apache.hadoop.yarn.api.records.ApplicationReport; +import org.apache.hadoop.yarn.api.records.YarnApplicationState; +import org.apache.hadoop.yarn.client.api.YarnClient; +import org.apache.hadoop.yarn.client.api.YarnClientApplication; +import org.apache.hadoop.yarn.conf.YarnConfiguration; +import java.io.File; +import java.net.InetSocketAddress; +import java.net.URLDecoder; +import java.util.*; + +import com.dtstack.flink.sql.enums.ClusterMode; +import org.apache.hadoop.yarn.exceptions.YarnException; +import org.apache.hadoop.yarn.util.StringHelper; + +import java.io.IOException; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import static java.util.Objects.requireNonNull; + +/** + * @author sishu.yss + */ +public class ClusterClientFactory { + + public static ClusterClient createClusterClient(Options launcherOptions) throws Exception { + String mode = launcherOptions.getMode(); + if(mode.equals(ClusterMode.standalone.name())) { + return createStandaloneClient(launcherOptions); + } else if(mode.equals(ClusterMode.yarn.name())) { + return createYarnClient(launcherOptions,mode); + } + throw new IllegalArgumentException("Unsupported cluster client type: "); + } + + public static ClusterClient createStandaloneClient(Options launcherOptions) throws Exception { + String flinkConfDir = launcherOptions.getFlinkconf(); + Configuration config = GlobalConfiguration.loadConfiguration(flinkConfDir); + MiniClusterConfiguration.Builder configBuilder = new MiniClusterConfiguration.Builder(); + configBuilder.setConfiguration(config); + MiniCluster miniCluster = new MiniCluster(configBuilder.build()); + MiniClusterClient clusterClient = new MiniClusterClient(config, miniCluster); + LeaderConnectionInfo connectionInfo = clusterClient.getClusterConnectionInfo(); + InetSocketAddress address = AkkaUtils.getInetSocketAddressFromAkkaURL(connectionInfo.getAddress()); + config.setString(JobManagerOptions.ADDRESS, address.getAddress().getHostName()); + config.setInteger(JobManagerOptions.PORT, address.getPort()); + clusterClient.setDetached(true); + return clusterClient; + } + + public static ClusterClient createYarnClient(Options launcherOptions, String mode) { + String flinkConfDir = launcherOptions.getFlinkconf(); + Configuration flinkConf = GlobalConfiguration.loadConfiguration(flinkConfDir); + String yarnConfDir = launcherOptions.getYarnconf(); + YarnConfiguration yarnConf; + if(StringUtils.isNotBlank(yarnConfDir)) { + try { + flinkConf.setString(ConfigConstants.PATH_HADOOP_CONFIG, yarnConfDir); + FileSystem.initialize(flinkConf); + + File dir = new File(yarnConfDir); + if(dir.exists() && dir.isDirectory()) { + yarnConf = loadYarnConfiguration(yarnConfDir); + + YarnClient yarnClient = YarnClient.createYarnClient(); + haYarnConf(yarnConf); + yarnClient.init(yarnConf); + yarnClient.start(); + + String confProp = launcherOptions.getConfProp(); + confProp = URLDecoder.decode(confProp, Charsets.UTF_8.toString()); + System.out.println("confProp="+confProp); + Properties confProperties = PluginUtil.jsonStrToObject(confProp, Properties.class); + + ApplicationId applicationId = null; + ClusterClient clusterClient = null; + if(mode.equals(ClusterMode.yarn.name())) {//on yarn cluster mode + String yarnSessionConf = launcherOptions.getYarnSessionConf(); + yarnSessionConf = URLDecoder.decode(yarnSessionConf, Charsets.UTF_8.toString()); + Properties yarnSessionConfProperties = PluginUtil.jsonStrToObject(yarnSessionConf, Properties.class); + String yid = yarnSessionConfProperties.get("yid").toString(); + if(StringUtils.isNotBlank(yid)){ + applicationId = toApplicationId(yid); + }else{ + applicationId = getYarnClusterApplicationId(yarnClient); + } + System.out.println("applicationId="+applicationId.toString()); + + AbstractYarnClusterDescriptor clusterDescriptor = new YarnClusterDescriptor( + flinkConf, yarnConf, ".", yarnClient, false); + clusterClient = clusterDescriptor.retrieve(applicationId); + + System.out.println("applicationId="+applicationId.toString()+" has retrieve!"); + } else {//on yarn per-job mode + applicationId = createApplication(yarnClient); + System.out.println("applicationId="+applicationId.toString()); + + YarnClusterConfiguration clusterConf = getYarnClusterConfiguration(flinkConf,yarnConf,flinkConfDir); + //jobmanager+taskmanager param + JobParameter appConf = new JobParameter(confProperties); + + com.dtstack.flink.sql.yarn.YarnClusterDescriptor clusterDescriptor = new com.dtstack.flink.sql.yarn.YarnClusterDescriptor( + clusterConf, yarnClient, appConf,applicationId, launcherOptions.getName(),null ); + clusterClient = clusterDescriptor.deploy(); + + System.out.println("applicationId="+applicationId.toString()+" has deploy!"); + } + clusterClient.setDetached(true); + yarnClient.stop(); + return clusterClient; + } + } catch(Exception e) { + throw new RuntimeException(e); + } + } + throw new UnsupportedOperationException("Haven't been developed yet!"); + } + + private static YarnConfiguration loadYarnConfiguration(String yarnConfDir) + { + org.apache.hadoop.conf.Configuration hadoopConf = new org.apache.hadoop.conf.Configuration(); + hadoopConf.set("fs.hdfs.impl", "org.apache.hadoop.hdfs.DistributedFileSystem"); + + Stream.of("yarn-site.xml", "core-site.xml", "hdfs-site.xml").forEach(file -> { + File site = new File(requireNonNull(yarnConfDir, "ENV HADOOP_CONF_DIR is not setting"), file); + if (site.exists() && site.isFile()) { + hadoopConf.addResource(new org.apache.hadoop.fs.Path(site.toURI())); + } + else { + throw new RuntimeException(site + " not exists"); + } + }); + + YarnConfiguration yarnConf = new YarnConfiguration(hadoopConf); + // try (PrintWriter pw = new PrintWriter(new FileWriter(yarnSite))) { //write local file + // yarnConf.writeXml(pw); + // } + return yarnConf; + } + + public static YarnClusterConfiguration getYarnClusterConfiguration(Configuration flinkConf,YarnConfiguration yarnConf,String flinkConfDir) + { + Path flinkJar = new Path(getFlinkJarFile(flinkConfDir).toURI()); + @SuppressWarnings("ConstantConditions") final Set resourcesToLocalize = Stream + .of("flink-conf.yaml", "log4j.properties") + .map(x -> new Path(new File(flinkConfDir, x).toURI())) + .collect(Collectors.toSet()); + + return new YarnClusterConfiguration(flinkConf, yarnConf, "", flinkJar, resourcesToLocalize); + } + + public static final String FLINK_DIST = "flink-dist"; + private static File getFlinkJarFile(String flinkConfDir) + { + String errorMessage = "error not search " + FLINK_DIST + "*.jar"; + File[] files = requireNonNull(new File(flinkConfDir, "/../lib").listFiles(), errorMessage); + Optional file = Arrays.stream(files) + .filter(f -> f.getName().startsWith(FLINK_DIST)).findFirst(); + return file.orElseThrow(() -> new IllegalArgumentException(errorMessage)); + } + + private static ApplicationId createApplication(YarnClient yarnClient)throws IOException, YarnException { + YarnClientApplication app = yarnClient.createApplication(); + return app.getApplicationSubmissionContext().getApplicationId(); + } + private static ApplicationId getYarnClusterApplicationId(YarnClient yarnClient) throws Exception{ + ApplicationId applicationId = null; + + Set set = new HashSet<>(); + set.add("Apache Flink"); + EnumSet enumSet = EnumSet.noneOf(YarnApplicationState.class); + enumSet.add(YarnApplicationState.RUNNING); + List reportList = yarnClient.getApplications(set, enumSet); + + int maxMemory = -1; + int maxCores = -1; + for(ApplicationReport report : reportList) { + if(!report.getName().startsWith("Flink session")){ + continue; + } + + if(!report.getYarnApplicationState().equals(YarnApplicationState.RUNNING)) { + continue; + } + + int thisMemory = report.getApplicationResourceUsageReport().getNeededResources().getMemory(); + int thisCores = report.getApplicationResourceUsageReport().getNeededResources().getVirtualCores(); + if(thisMemory > maxMemory || thisMemory == maxMemory && thisCores > maxCores) { + maxMemory = thisMemory; + maxCores = thisCores; + applicationId = report.getApplicationId(); + } + + } + + if(StringUtils.isEmpty(applicationId.toString())) { + throw new RuntimeException("No flink session found on yarn cluster."); + } + return applicationId; + } + + /** + * 处理yarn HA的配置项 + */ + private static org.apache.hadoop.conf.Configuration haYarnConf(org.apache.hadoop.conf.Configuration yarnConf) { + Iterator> iterator = yarnConf.iterator(); + while(iterator.hasNext()) { + Map.Entry entry = iterator.next(); + String key = entry.getKey(); + String value = entry.getValue(); + if(key.startsWith("yarn.resourcemanager.hostname.")) { + String rm = key.substring("yarn.resourcemanager.hostname.".length()); + String addressKey = "yarn.resourcemanager.address." + rm; + if(yarnConf.get(addressKey) == null) { + yarnConf.set(addressKey, value + ":" + YarnConfiguration.DEFAULT_RM_PORT); + } + } + } + return yarnConf; + } + + private static ApplicationId toApplicationId(String appIdStr) { + Iterator it = StringHelper._split(appIdStr).iterator(); + if (!(it.next()).equals("application")) { + throw new IllegalArgumentException("Invalid ApplicationId prefix: " + appIdStr + ". The valid ApplicationId should start with prefix " + "application"); + } else { + try { + return toApplicationId(it); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("Invalid AppAttemptId: " + appIdStr, e); + } + } + } + + private static ApplicationId toApplicationId(Iterator it) throws NumberFormatException { + return ApplicationId.newInstance(Long.parseLong(it.next()), Integer.parseInt(it.next())); + } + +} \ No newline at end of file diff --git a/launcher/src/main/java/com/dtstack/flink/sql/launcher/LauncherMain.java b/launcher/src/main/java/com/dtstack/flink/sql/launcher/LauncherMain.java index 9d0b1eed4..0edd01434 100644 --- a/launcher/src/main/java/com/dtstack/flink/sql/launcher/LauncherMain.java +++ b/launcher/src/main/java/com/dtstack/flink/sql/launcher/LauncherMain.java @@ -16,36 +16,37 @@ * limitations under the License. */ + package com.dtstack.flink.sql.launcher; +import com.google.common.collect.Lists; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.TypeReference; -import com.dtstack.flink.sql.Main; -import com.dtstack.flink.sql.dirtyManager.manager.DirtyDataManager; import com.dtstack.flink.sql.enums.ClusterMode; -import com.dtstack.flink.sql.launcher.entity.JobParamsInfo; -import com.dtstack.flink.sql.launcher.executor.StandaloneExecutor; -import com.dtstack.flink.sql.launcher.executor.YarnJobClusterExecutor; -import com.dtstack.flink.sql.launcher.executor.YarnSessionClusterExecutor; +import com.dtstack.flink.sql.Main; +import com.dtstack.flink.sql.launcher.perjob.PerJobSubmitter; import com.dtstack.flink.sql.option.OptionParser; import com.dtstack.flink.sql.option.Options; import com.dtstack.flink.sql.util.PluginUtil; -import org.apache.commons.io.Charsets; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.apache.commons.lang.BooleanUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.flink.client.program.ClusterClient; +import org.apache.flink.client.program.PackagedProgram; +import org.apache.flink.client.program.PackagedProgramUtils; +import org.apache.flink.configuration.Configuration; +import org.apache.flink.configuration.GlobalConfiguration; +import org.apache.flink.runtime.jobgraph.JobGraph; +import org.apache.flink.runtime.jobgraph.SavepointRestoreSettings; import java.io.BufferedReader; +import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; -import java.net.URLDecoder; -import java.nio.charset.StandardCharsets; import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.Objects; -import java.util.Properties; /** * Date: 2017/2/20 @@ -54,104 +55,85 @@ */ public class LauncherMain { + private static final String CORE_JAR = "core"; + + private static String SP = File.separator; - private static final Logger LOG = LoggerFactory.getLogger(LauncherMain.class); - @SuppressWarnings("unchecked") - public static JobParamsInfo parseArgs(String[] args) throws Exception { - if (args.length == 1 && args[0].endsWith(".json")) { + private static String getLocalCoreJarPath(String localSqlRootJar) throws Exception { + String jarPath = PluginUtil.getCoreJarFileName(localSqlRootJar, CORE_JAR); + String corePath = localSqlRootJar + SP + jarPath; + return corePath; + } + + public static void main(String[] args) throws Exception { + if (args.length == 1 && args[0].endsWith(".json")){ args = parseJson(args); } OptionParser optionParser = new OptionParser(args); Options launcherOptions = optionParser.getOptions(); - List programExeArgList = optionParser.getProgramExeArgList(); - String[] execArgs = programExeArgList.toArray(new String[0]); - - String name = launcherOptions.getName(); String mode = launcherOptions.getMode(); - String localPluginRoot = launcherOptions.getLocalSqlPluginPath(); - String flinkConfDir = launcherOptions.getFlinkconf(); - String flinkJarPath = launcherOptions.getFlinkJarPath(); - String yarnConfDir = launcherOptions.getYarnconf(); - String udfJar = launcherOptions.getAddjar(); - String queue = launcherOptions.getQueue(); - String pluginLoadMode = launcherOptions.getPluginLoadMode(); - String addShipfile = launcherOptions.getAddShipfile(); - String dirtyStr = launcherOptions.getDirtyProperties(); - - String yarnSessionConf = URLDecoder.decode(launcherOptions.getYarnSessionConf(), Charsets.UTF_8.toString()); - Properties yarnSessionConfProperties = PluginUtil.jsonStrToObject(yarnSessionConf, Properties.class); - - String confProp = URLDecoder.decode(launcherOptions.getConfProp(), Charsets.UTF_8.toString()); - Properties confProperties = PluginUtil.jsonStrToObject(confProp, Properties.class); - Map dirtyProperties = PluginUtil.jsonStrToObject(Objects.isNull(dirtyStr) ? - DirtyDataManager.buildDefaultDirty() : dirtyStr, Map.class); - - return JobParamsInfo.builder() - .setExecArgs(execArgs) - .setName(name) - .setMode(mode) - .setUdfJar(udfJar) - .setLocalPluginRoot(localPluginRoot) - .setFlinkConfDir(flinkConfDir) - .setYarnConfDir(yarnConfDir) - .setConfProperties(confProperties) - .setYarnSessionConfProperties(yarnSessionConfProperties) - .setFlinkJarPath(flinkJarPath) - .setPluginLoadMode(pluginLoadMode) - .setQueue(queue) - .setDirtyProperties(dirtyProperties) - .setAddShipfile(addShipfile) - .build(); + List argList = optionParser.getProgramExeArgList(); + + if(mode.equals(ClusterMode.local.name())) { + String[] localArgs = argList.toArray(new String[argList.size()]); + Main.main(localArgs); + return; + } + + String pluginRoot = launcherOptions.getLocalSqlPluginPath(); + File jarFile = new File(getLocalCoreJarPath(pluginRoot)); + String[] remoteArgs = argList.toArray(new String[argList.size()]); + PackagedProgram program = new PackagedProgram(jarFile, Lists.newArrayList(), remoteArgs); + + if(StringUtils.isNotBlank(launcherOptions.getSavePointPath())){ + program.setSavepointRestoreSettings(SavepointRestoreSettings.forPath(launcherOptions.getSavePointPath(), BooleanUtils.toBoolean(launcherOptions.getAllowNonRestoredState()))); + } + + if(mode.equals(ClusterMode.yarnPer.name())){ + String flinkConfDir = launcherOptions.getFlinkconf(); + Configuration config = GlobalConfiguration.loadConfiguration(flinkConfDir); + JobGraph jobGraph = PackagedProgramUtils.createJobGraph(program, config, 1); + PerJobSubmitter.submit(launcherOptions, jobGraph); + } else { + ClusterClient clusterClient = ClusterClientFactory.createClusterClient(launcherOptions); + clusterClient.run(program, 1); + clusterClient.shutdown(); + } + } private static String[] parseJson(String[] args) { - StringBuilder lastStr = new StringBuilder(); - try { - try (FileInputStream fileInputStream = new FileInputStream(args[0])) { - try (InputStreamReader inputStreamReader = - new InputStreamReader(fileInputStream, StandardCharsets.UTF_8)) { - try (BufferedReader reader = new BufferedReader(inputStreamReader)) { - String tempString; - while ((tempString = reader.readLine()) != null) { - lastStr.append(tempString); - } - } + BufferedReader reader = null; + String lastStr = ""; + try{ + FileInputStream fileInputStream = new FileInputStream(args[0]); + InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, "UTF-8"); + reader = new BufferedReader(inputStreamReader); + String tempString = null; + while((tempString = reader.readLine()) != null){ + lastStr += tempString; + } + reader.close(); + }catch(IOException e){ + e.printStackTrace(); + }finally{ + if(reader != null){ + try { + reader.close(); + } catch (IOException e) { + e.printStackTrace(); } } - } catch (IOException e) { - LOG.error("", e); } - - Map map = JSON.parseObject(lastStr.toString(), new TypeReference>() {}); + Map map = JSON.parseObject(lastStr, new TypeReference>(){} ); List list = new LinkedList<>(); for (Map.Entry entry : map.entrySet()) { list.add("-" + entry.getKey()); list.add(entry.getValue().toString()); } - return list.toArray(new String[0]); - } - - public static void main(String[] args) throws Exception { - JobParamsInfo jobParamsInfo = parseArgs(args); - ClusterMode execMode = ClusterMode.valueOf(jobParamsInfo.getMode()); - - switch (execMode) { - case local: - Main.main(jobParamsInfo.getExecArgs()); - break; - case yarn: - new YarnSessionClusterExecutor(jobParamsInfo).exec(); - break; - case yarnPer: - new YarnJobClusterExecutor(jobParamsInfo).exec(); - break; - case standalone: - new StandaloneExecutor(jobParamsInfo).exec(); - break; - default: - throw new RuntimeException("Unsupported operating mode, please use local,yarn,yarnPer"); - } + String[] array = list.toArray(new String[list.size()]); + return array; } } diff --git a/launcher/src/main/java/com/dtstack/flink/sql/launcher/YarnConfLoader.java b/launcher/src/main/java/com/dtstack/flink/sql/launcher/YarnConfLoader.java new file mode 100644 index 000000000..717da24fa --- /dev/null +++ b/launcher/src/main/java/com/dtstack/flink/sql/launcher/YarnConfLoader.java @@ -0,0 +1,85 @@ +/* + * 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 com.dtstack.flink.sql.launcher; + +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.yarn.conf.YarnConfiguration; + +import java.io.File; +import java.util.Iterator; +import java.util.Map; + +/** + * load yarn conf from specify dir + * Date: 2018/11/17 + * Company: www.dtstack.com + * @author xuchao + */ + +public class YarnConfLoader { + + public static YarnConfiguration getYarnConf(String yarnConfDir) { + YarnConfiguration yarnConf = new YarnConfiguration(); + try { + + File dir = new File(yarnConfDir); + if(dir.exists() && dir.isDirectory()) { + + File[] xmlFileList = new File(yarnConfDir).listFiles((dir1, name) -> { + if(name.endsWith(".xml")){ + return true; + } + return false; + }); + + if(xmlFileList != null) { + for(File xmlFile : xmlFileList) { + yarnConf.addResource(xmlFile.toURI().toURL()); + } + } + } + + } catch(Exception e) { + throw new RuntimeException(e); + } + + haYarnConf(yarnConf); + return yarnConf; + } + + /** + * deal yarn HA conf + */ + private static Configuration haYarnConf(Configuration yarnConf) { + Iterator> iterator = yarnConf.iterator(); + while(iterator.hasNext()) { + Map.Entry entry = iterator.next(); + String key = entry.getKey(); + String value = entry.getValue(); + if(key.startsWith("yarn.resourcemanager.hostname.")) { + String rm = key.substring("yarn.resourcemanager.hostname.".length()); + String addressKey = "yarn.resourcemanager.address." + rm; + if(yarnConf.get(addressKey) == null) { + yarnConf.set(addressKey, value + ":" + YarnConfiguration.DEFAULT_RM_PORT); + } + } + } + return yarnConf; + } +} diff --git a/launcher/src/main/java/com/dtstack/flink/sql/launcher/entity/JobParamsInfo.java b/launcher/src/main/java/com/dtstack/flink/sql/launcher/entity/JobParamsInfo.java deleted file mode 100644 index 4c5fad002..000000000 --- a/launcher/src/main/java/com/dtstack/flink/sql/launcher/entity/JobParamsInfo.java +++ /dev/null @@ -1,264 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.launcher.entity; - -import java.util.Arrays; -import java.util.Map; -import java.util.Properties; - -/** - * parse the original mission parameters - * Date: 2020/3/4 - * Company: www.dtstack.com - * - * @author maqi - */ -public class JobParamsInfo { - - private final String mode; - private final String name; - private final String queue; - private final String localPluginRoot; - private final String flinkConfDir; - private final String flinkJarPath; - private final String yarnConfDir; - private final String pluginLoadMode; - private final String udfJar; - private final String[] execArgs; - private final Properties confProperties; - private final Properties yarnSessionConfProperties; - private final String addShipFile; - private final Map dirtyProperties; - - private JobParamsInfo( - String mode - , String name - , String queue - , String localPluginRoot - , String flinkConfDir - , String yarnConfDir - , String pluginLoadMode - , String[] execArgs - , Properties confProperties - , Properties yarnSessionConfProperties - , String udfJar - , String flinkJarPath - , String addShipFile - , Map dirtyProperties) { - this.mode = mode; - this.name = name; - this.queue = queue; - this.localPluginRoot = localPluginRoot; - this.flinkConfDir = flinkConfDir; - this.yarnConfDir = yarnConfDir; - this.pluginLoadMode = pluginLoadMode; - this.execArgs = execArgs; - this.confProperties = confProperties; - this.yarnSessionConfProperties = yarnSessionConfProperties; - this.udfJar = udfJar; - this.flinkJarPath = flinkJarPath; - this.addShipFile = addShipFile; - this.dirtyProperties = dirtyProperties; - } - - public static JobParamsInfo.Builder builder() { - return new JobParamsInfo.Builder(); - } - - public String getMode() { - return mode; - } - - public String getName() { - return name; - } - - public String getQueue() { - return queue; - } - - public String getLocalPluginRoot() { - return localPluginRoot; - } - - public String getFlinkConfDir() { - return flinkConfDir; - } - - public String getYarnConfDir() { - return yarnConfDir; - } - - public String getPluginLoadMode() { - return pluginLoadMode; - } - - public String[] getExecArgs() { - return execArgs; - } - - public Properties getConfProperties() { - return confProperties; - } - - public Properties getYarnSessionConfProperties() { - return yarnSessionConfProperties; - } - - public String getUdfJar() { - return udfJar; - } - - public String getFlinkJarPath() { - return flinkJarPath; - } - - public String getAddShipFile() { - return addShipFile; - } - - public Map getDirtyProperties() { - return dirtyProperties; - } - - public static class Builder { - private String mode; - private String name; - private String queue; - private String localPluginRoot; - private String flinkConfDir; - private String flinkJarPath; - private String yarnConfDir; - private String pluginLoadMode; - private String[] execArgs; - private String udfJar; - private Properties confProperties; - private Properties yarnSessionConfProperties; - private String addShipfile; - private Map dirtyProperties; - - public JobParamsInfo.Builder setMode(String mode) { - this.mode = mode; - return this; - } - - public JobParamsInfo.Builder setName(String name) { - this.name = name; - return this; - } - - public JobParamsInfo.Builder setQueue(String queue) { - this.queue = queue; - return this; - } - - public JobParamsInfo.Builder setLocalPluginRoot(String localPluginRoot) { - this.localPluginRoot = localPluginRoot; - return this; - } - - public JobParamsInfo.Builder setFlinkConfDir(String flinkConfDir) { - this.flinkConfDir = flinkConfDir; - return this; - } - - public JobParamsInfo.Builder setYarnConfDir(String yarnConfDir) { - this.yarnConfDir = yarnConfDir; - return this; - } - - public JobParamsInfo.Builder setPluginLoadMode(String pluginLoadMode) { - this.pluginLoadMode = pluginLoadMode; - return this; - } - - public JobParamsInfo.Builder setExecArgs(String[] execArgs) { - this.execArgs = execArgs; - return this; - } - - public JobParamsInfo.Builder setConfProperties(Properties confProperties) { - this.confProperties = confProperties; - return this; - } - - public JobParamsInfo.Builder setYarnSessionConfProperties(Properties yarnSessionConfProperties) { - this.yarnSessionConfProperties = yarnSessionConfProperties; - return this; - } - - public JobParamsInfo.Builder setUdfJar(String udfJar) { - this.udfJar = udfJar; - return this; - } - - public JobParamsInfo.Builder setFlinkJarPath(String flinkJarPath) { - this.flinkJarPath = flinkJarPath; - return this; - } - - public JobParamsInfo.Builder setAddShipfile(String addShipfile) { - this.addShipfile = addShipfile; - return this; - } - - public JobParamsInfo.Builder setDirtyProperties(Map dirtyProperties) { - this.dirtyProperties = dirtyProperties; - return this; - } - - public JobParamsInfo build() { - return new JobParamsInfo( - mode - , name - , queue - , localPluginRoot - , flinkConfDir - , yarnConfDir - , pluginLoadMode - , execArgs - , confProperties - , yarnSessionConfProperties - , udfJar - , flinkJarPath - , addShipfile - , dirtyProperties); - } - } - - @Override - public String toString() { - return "JobParamsInfo{" + - "mode='" + mode + '\'' + - ", name='" + name + '\'' + - ", queue='" + queue + '\'' + - ", localPluginRoot='" + localPluginRoot + '\'' + - ", flinkConfDir='" + flinkConfDir + '\'' + - ", flinkJarPath='" + flinkJarPath + '\'' + - ", yarnConfDir='" + yarnConfDir + '\'' + - ", pluginLoadMode='" + pluginLoadMode + '\'' + - ", udfJar='" + udfJar + '\'' + - ", execArgs=" + Arrays.toString(execArgs) + - ", confProperties=" + confProperties + - ", yarnSessionConfProperties=" + yarnSessionConfProperties + - ", addShipFile='" + addShipFile + '\'' + - ", dirtyProperties=" + dirtyProperties + - '}'; - } -} diff --git a/launcher/src/main/java/com/dtstack/flink/sql/launcher/executor/StandaloneExecutor.java b/launcher/src/main/java/com/dtstack/flink/sql/launcher/executor/StandaloneExecutor.java deleted file mode 100644 index 085812a25..000000000 --- a/launcher/src/main/java/com/dtstack/flink/sql/launcher/executor/StandaloneExecutor.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.launcher.executor; - -import com.dtstack.flink.sql.enums.EPluginLoadMode; -import com.dtstack.flink.sql.launcher.LauncherMain; -import com.dtstack.flink.sql.launcher.entity.JobParamsInfo; -import com.dtstack.flink.sql.launcher.factory.StandaloneClientFactory; -import com.dtstack.flink.sql.launcher.utils.JobGraphBuildUtil; -import org.apache.commons.lang3.StringUtils; -import org.apache.flink.api.common.JobExecutionResult; -import org.apache.flink.client.ClientUtils; -import org.apache.flink.client.deployment.ClusterDescriptor; -import org.apache.flink.client.deployment.StandaloneClusterId; -import org.apache.flink.client.program.ClusterClient; -import org.apache.flink.client.program.ClusterClientProvider; -import org.apache.flink.configuration.Configuration; -import org.apache.flink.runtime.jobgraph.JobGraph; -import org.apache.flink.util.Preconditions; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Date: 2020/3/6 - * Company: www.dtstack.com - * @author maqi - */ -public class StandaloneExecutor { - - private static final Logger LOG = LoggerFactory.getLogger(StandaloneExecutor.class); - - JobParamsInfo jobParamsInfo; - - public StandaloneExecutor(JobParamsInfo jobParamsInfo) { - this.jobParamsInfo = jobParamsInfo; - } - - public void exec() throws Exception { - - Preconditions.checkArgument(StringUtils.equalsIgnoreCase(jobParamsInfo.getPluginLoadMode(), EPluginLoadMode.CLASSPATH.name()), - "standalone only supports classpath mode"); - - JobGraph jobGraph = JobGraphBuildUtil.buildJobGraph(jobParamsInfo); - Configuration flinkConfiguration = JobGraphBuildUtil.getFlinkConfiguration(jobParamsInfo.getFlinkConfDir(), jobParamsInfo.getConfProperties()); - - if (!StringUtils.isBlank(jobParamsInfo.getUdfJar())) { - JobGraphBuildUtil.fillUserJarForJobGraph(jobParamsInfo.getUdfJar(), jobGraph); - } - - JobGraphBuildUtil.fillJobGraphClassPath(jobGraph); - - ClusterDescriptor clusterDescriptor = StandaloneClientFactory.INSTANCE.createClusterDescriptor("", flinkConfiguration); - - try { - ClusterClientProvider clusterClientProvider = clusterDescriptor.retrieve(StandaloneClusterId.getInstance()); - ClusterClient clusterClient = clusterClientProvider.getClusterClient(); - - JobExecutionResult jobExecutionResult = ClientUtils.submitJob(clusterClient, jobGraph); - String jobId = jobExecutionResult.getJobID().toString(); - LOG.info("jobID:" + jobId); - } finally { - try { - clusterDescriptor.close(); - } catch (Exception e) { - LOG.info("Could not properly close the yarn cluster descriptor.", e); - } - } - - } -} diff --git a/launcher/src/main/java/com/dtstack/flink/sql/launcher/executor/YarnJobClusterExecutor.java b/launcher/src/main/java/com/dtstack/flink/sql/launcher/executor/YarnJobClusterExecutor.java deleted file mode 100644 index c125101b3..000000000 --- a/launcher/src/main/java/com/dtstack/flink/sql/launcher/executor/YarnJobClusterExecutor.java +++ /dev/null @@ -1,217 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.launcher.executor; - -import com.dtstack.flink.sql.enums.EPluginLoadMode; -import com.dtstack.flink.sql.launcher.entity.JobParamsInfo; -import com.dtstack.flink.sql.launcher.factory.YarnClusterClientFactory; -import com.dtstack.flink.sql.launcher.utils.JobGraphBuildUtil; -import org.apache.commons.lang3.StringUtils; -import org.apache.flink.client.deployment.ClusterSpecification; -import org.apache.flink.client.program.ClusterClientProvider; -import org.apache.flink.configuration.Configuration; -import org.apache.flink.configuration.SecurityOptions; -import org.apache.flink.configuration.TaskManagerOptions; -import org.apache.flink.runtime.jobgraph.JobGraph; -import org.apache.flink.yarn.YarnClusterDescriptor; -import org.apache.flink.yarn.configuration.YarnConfigOptions; -import org.apache.flink.yarn.configuration.YarnConfigOptionsInternal; -import org.apache.hadoop.fs.Path; -import org.apache.hadoop.yarn.api.records.ApplicationId; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.net.MalformedURLException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Optional; -import java.util.stream.Stream; - - -/** - * Date: 2020/3/4 - * Company: www.dtstack.com - * @author maqi - */ -public class YarnJobClusterExecutor { - private static final Logger LOG = LoggerFactory.getLogger(YarnJobClusterExecutor.class); - - private static final String CONFIG_FILE_LOGBACK_NAME = "logback.xml"; - private static final String CONFIG_FILE_LOG4J_NAME = "log4j.properties"; - private static final String DEFAULT_TOTAL_PROCESS_MEMORY = "1024m"; - - JobParamsInfo jobParamsInfo; - - public YarnJobClusterExecutor(JobParamsInfo jobParamsInfo) { - this.jobParamsInfo = jobParamsInfo; - } - - public void exec() throws Exception { - JobGraph jobGraph = JobGraphBuildUtil.buildJobGraph(jobParamsInfo); - if (!StringUtils.isBlank(jobParamsInfo.getUdfJar())) { - JobGraphBuildUtil.fillUserJarForJobGraph(jobParamsInfo.getUdfJar(), jobGraph); - } - - Configuration flinkConfiguration = JobGraphBuildUtil.getFlinkConfiguration(jobParamsInfo.getFlinkConfDir(), jobParamsInfo.getConfProperties()); - appendApplicationConfig(flinkConfiguration, jobParamsInfo); - - YarnClusterDescriptor clusterDescriptor = (YarnClusterDescriptor) YarnClusterClientFactory.INSTANCE - .createClusterDescriptor(jobParamsInfo.getYarnConfDir(), flinkConfiguration); - - try { - List shipFiles = getShipFiles(jobParamsInfo.getFlinkJarPath(), jobParamsInfo.getPluginLoadMode(), jobGraph, clusterDescriptor); - - if (jobParamsInfo.getAddShipFile() != null) { - List addShipFilesPath = parsePathFromStr(jobParamsInfo.getAddShipFile()); - for (String path : addShipFilesPath) { - shipFiles.add(getAddShipFile(path)); - } - } - - dumpSameKeytab(flinkConfiguration, shipFiles); - clusterDescriptor.addShipFiles(shipFiles); - - ClusterSpecification clusterSpecification = YarnClusterClientFactory.INSTANCE.getClusterSpecification(flinkConfiguration); - ClusterClientProvider applicationIdClusterClientProvider = clusterDescriptor.deployJobCluster(clusterSpecification, jobGraph, true); - - String applicationId = applicationIdClusterClientProvider.getClusterClient().getClusterId().toString(); - String flinkJobId = jobGraph.getJobID().toString(); - - LOG.info(String.format("deploy per_job with appId: %s, jobId: %s", applicationId, flinkJobId)); - } finally { - try { - clusterDescriptor.close(); - } catch (Exception e) { - LOG.info("Could not properly close the yarn cluster descriptor.", e); - } - } - } - - private void dumpSameKeytab(Configuration flinkConfiguration, List shipFiles) { - Optional.ofNullable(flinkConfiguration.getString(SecurityOptions.KERBEROS_LOGIN_KEYTAB)) - .ifPresent(x -> - shipFiles.removeIf(f -> - f.getName().equals(Stream - .of(x.split(File.separator)) - .reduce((a, b) -> b) - .get()))); - } - private void appendApplicationConfig(Configuration flinkConfig, JobParamsInfo jobParamsInfo) { - if (!StringUtils.isEmpty(jobParamsInfo.getName())) { - flinkConfig.setString(YarnConfigOptions.APPLICATION_NAME, jobParamsInfo.getName()); - } - - if (!StringUtils.isEmpty(jobParamsInfo.getQueue())) { - flinkConfig.setString(YarnConfigOptions.APPLICATION_QUEUE, jobParamsInfo.getQueue()); - } - - if (!StringUtils.isEmpty(jobParamsInfo.getFlinkConfDir())) { - discoverLogConfigFile(jobParamsInfo.getFlinkConfDir()).ifPresent(file -> - flinkConfig.setString(YarnConfigOptionsInternal.APPLICATION_LOG_CONFIG_FILE, file.getPath())); - } - - if (!flinkConfig.contains(TaskManagerOptions.TOTAL_PROCESS_MEMORY)) { - flinkConfig.setString(TaskManagerOptions.TOTAL_PROCESS_MEMORY.key(), DEFAULT_TOTAL_PROCESS_MEMORY); - } - } - - protected List getShipFiles(String flinkJarPath, String pluginLoadMode, JobGraph jobGraph, YarnClusterDescriptor clusterDescriptor) - throws MalformedURLException { - - List shipFiles = new ArrayList<>(); - dealFlinkLibJar(flinkJarPath, clusterDescriptor, shipFiles); - dealUserJarByPluginLoadMode(pluginLoadMode, jobGraph, shipFiles); - return shipFiles; - } - - private File getAddShipFile(String addShipFile) { - if (StringUtils.isEmpty(addShipFile) || !new File(addShipFile).exists()) { - throw new RuntimeException("path " + addShipFile + " is not exist"); - } - File shipFile = new File(addShipFile); - if (shipFile.isFile()) { - return shipFile; - } else { - throw new RuntimeException("addShipfile only supports file path,E.g : {\\\"a.keytab\\\",\\\"b.txt\\\"}"); - } - } - - private void dealFlinkLibJar(String flinkJarPath, YarnClusterDescriptor clusterDescriptor, List shipFiles) throws MalformedURLException { - if (StringUtils.isEmpty(flinkJarPath) || !new File(flinkJarPath).exists()) { - throw new RuntimeException("path " + flinkJarPath + " is not exist"); - } - File[] jars = new File(flinkJarPath).listFiles(); - - if (jars == null || jars.length == 0) { - throw new RuntimeException(flinkJarPath + " no file exist !"); - } - - for (File file : jars) { - if (file.toURI().toURL().toString().contains("flink-dist")) { - clusterDescriptor.setLocalJarPath(new Path(file.toURI().toURL().toString())); - } else { - shipFiles.add(file); - } - } - } - - private void dealUserJarByPluginLoadMode(String pluginLoadMode, JobGraph jobGraph, List shipFiles) throws MalformedURLException { - // classpath , all node need contain plugin jar - if (StringUtils.equalsIgnoreCase(pluginLoadMode, EPluginLoadMode.CLASSPATH.name())) { - JobGraphBuildUtil.fillJobGraphClassPath(jobGraph); - } else if (StringUtils.equalsIgnoreCase(pluginLoadMode, EPluginLoadMode.SHIPFILE.name())) { - List pluginPaths = JobGraphBuildUtil.getPluginPathToShipFiles(jobGraph); - shipFiles.addAll(pluginPaths); - } else { - throw new IllegalArgumentException("Unsupported plugin loading mode " + pluginLoadMode - + " Currently only classpath and shipfile are supported."); - } - } - - - private Optional discoverLogConfigFile(final String configurationDirectory) { - Optional logConfigFile = Optional.empty(); - - final File log4jFile = new File(configurationDirectory + File.separator + CONFIG_FILE_LOG4J_NAME); - if (log4jFile.exists()) { - logConfigFile = Optional.of(log4jFile); - } - - final File logbackFile = new File(configurationDirectory + File.separator + CONFIG_FILE_LOGBACK_NAME); - if (logbackFile.exists()) { - if (logConfigFile.isPresent()) { - LOG.warn("The configuration directory ('" + configurationDirectory + "') already contains a LOG4J config file." + - "If you want to use logback, then please delete or rename the log configuration file."); - } else { - logConfigFile = Optional.of(logbackFile); - } - } - return logConfigFile; - } - - private static List parsePathFromStr(String pathStr) { - if (pathStr.length() > 2) { - pathStr = pathStr.substring(1, pathStr.length() - 1).replace("\"", ""); - } - - return Arrays.asList(pathStr.split(",")); - } -} diff --git a/launcher/src/main/java/com/dtstack/flink/sql/launcher/executor/YarnSessionClusterExecutor.java b/launcher/src/main/java/com/dtstack/flink/sql/launcher/executor/YarnSessionClusterExecutor.java deleted file mode 100644 index 6cb613589..000000000 --- a/launcher/src/main/java/com/dtstack/flink/sql/launcher/executor/YarnSessionClusterExecutor.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.launcher.executor; - - -import com.dtstack.flink.sql.enums.EPluginLoadMode; -import com.dtstack.flink.sql.launcher.entity.JobParamsInfo; -import com.dtstack.flink.sql.launcher.factory.YarnClusterClientFactory; -import com.dtstack.flink.sql.launcher.utils.JobGraphBuildUtil; -import org.apache.commons.lang.StringUtils; -import org.apache.flink.api.common.JobExecutionResult; -import org.apache.flink.client.ClientUtils; -import org.apache.flink.client.deployment.ClusterDescriptor; -import org.apache.flink.client.program.ClusterClient; -import org.apache.flink.client.program.ClusterClientProvider; -import org.apache.flink.configuration.Configuration; -import org.apache.flink.runtime.jobgraph.JobGraph; -import org.apache.hadoop.yarn.api.records.ApplicationId; -import org.apache.hadoop.yarn.util.ConverterUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - - -/** - * Date: 2020/3/4 - * Company: www.dtstack.com - * @author maqi - */ -public class YarnSessionClusterExecutor { - - private static final Logger LOG = LoggerFactory.getLogger(YarnJobClusterExecutor.class); - - JobParamsInfo jobParamsInfo; - - public YarnSessionClusterExecutor(JobParamsInfo jobParamsInfo) { - this.jobParamsInfo = jobParamsInfo; - } - - public void exec() throws Exception { - JobGraph jobGraph = JobGraphBuildUtil.buildJobGraph(jobParamsInfo); - Configuration flinkConfiguration = JobGraphBuildUtil.getFlinkConfiguration(jobParamsInfo.getFlinkConfDir(), jobParamsInfo.getConfProperties()); - ClusterDescriptor clusterDescriptor = YarnClusterClientFactory.INSTANCE.createClusterDescriptor(jobParamsInfo.getYarnConfDir(), flinkConfiguration); - - try { - Object yid = jobParamsInfo.getYarnSessionConfProperties().get("yid"); - if (null == yid) { - throw new RuntimeException("yarnSessionMode yid is required"); - } - - ApplicationId applicationId = ConverterUtils.toApplicationId(yid.toString()); - ClusterClientProvider retrieve = clusterDescriptor.retrieve(applicationId); - ClusterClient clusterClient = retrieve.getClusterClient(); - - if (StringUtils.equalsIgnoreCase(jobParamsInfo.getPluginLoadMode(), EPluginLoadMode.SHIPFILE.name())) { - jobGraph.getUserArtifacts().clear(); - } else { - JobGraphBuildUtil.fillJobGraphClassPath(jobGraph); - } - - if (!StringUtils.isEmpty(jobParamsInfo.getUdfJar())) { - JobGraphBuildUtil.fillUserJarForJobGraph(jobParamsInfo.getUdfJar(), jobGraph); - } - - JobExecutionResult jobExecutionResult = ClientUtils.submitJob(clusterClient, jobGraph); - String jobId = jobExecutionResult.getJobID().toString(); - LOG.info("jobID:" + jobId); - } finally { - try { - clusterDescriptor.close(); - } catch (Exception e) { - LOG.info("Could not properly close the yarn cluster descriptor.", e); - } - } - - - } - - -} diff --git a/launcher/src/main/java/com/dtstack/flink/sql/launcher/factory/AbstractClusterClientFactory.java b/launcher/src/main/java/com/dtstack/flink/sql/launcher/factory/AbstractClusterClientFactory.java deleted file mode 100644 index 29bb513f7..000000000 --- a/launcher/src/main/java/com/dtstack/flink/sql/launcher/factory/AbstractClusterClientFactory.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.launcher.factory; - -import org.apache.flink.client.deployment.ClusterDescriptor; -import org.apache.flink.client.deployment.ClusterSpecification; -import org.apache.flink.configuration.Configuration; -import org.apache.flink.configuration.ConfigurationUtils; -import org.apache.flink.configuration.TaskManagerOptions; -import org.apache.flink.runtime.clusterframework.TaskExecutorProcessUtils; - -import static org.apache.flink.util.Preconditions.checkNotNull; - - -/** - * Date: 2020/3/4 - * Company: www.dtstack.com - * @author maqi - */ -public interface AbstractClusterClientFactory { - - default ClusterSpecification getClusterSpecification(Configuration configuration) { - checkNotNull(configuration); - - final int jobManagerMemoryMb = ConfigurationUtils - .getJobManagerHeapMemory(configuration) - .getMebiBytes(); - - final int taskManagerMemoryMb = TaskExecutorProcessUtils - .processSpecFromConfig(TaskExecutorProcessUtils.getConfigurationMapLegacyTaskManagerHeapSizeToConfigOption( - configuration, TaskManagerOptions.TOTAL_PROCESS_MEMORY)) - .getTotalProcessMemorySize() - .getMebiBytes(); - - int slotsPerTaskManager = configuration.getInteger(TaskManagerOptions.NUM_TASK_SLOTS); - - return new ClusterSpecification.ClusterSpecificationBuilder() - .setMasterMemoryMB(jobManagerMemoryMb) - .setTaskManagerMemoryMB(taskManagerMemoryMb) - .setSlotsPerTaskManager(slotsPerTaskManager) - .createClusterSpecification(); - } - - /** - * create ClusterDescriptor - * @param clusterConfPath cluster configuration path , E.g. yarn conf dir - * @param flinkConfig - * @return - */ - abstract ClusterDescriptor createClusterDescriptor(String clusterConfPath, Configuration flinkConfig); - -} diff --git a/launcher/src/main/java/com/dtstack/flink/sql/launcher/factory/StandaloneClientFactory.java b/launcher/src/main/java/com/dtstack/flink/sql/launcher/factory/StandaloneClientFactory.java deleted file mode 100644 index ceb134b68..000000000 --- a/launcher/src/main/java/com/dtstack/flink/sql/launcher/factory/StandaloneClientFactory.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.launcher.factory; - -import org.apache.flink.client.deployment.ClusterDescriptor; -import org.apache.flink.client.deployment.StandaloneClusterDescriptor; -import org.apache.flink.configuration.Configuration; - -import static org.apache.flink.util.Preconditions.checkNotNull; - -/** - * Date: 2020/3/6 - * Company: www.dtstack.com - * @author maqi - */ -public enum StandaloneClientFactory implements AbstractClusterClientFactory { - INSTANCE; - - @Override - public ClusterDescriptor createClusterDescriptor(String clusterConfPath, Configuration flinkConfig) { - checkNotNull(flinkConfig); - return new StandaloneClusterDescriptor(flinkConfig); - } -} diff --git a/launcher/src/main/java/com/dtstack/flink/sql/launcher/factory/YarnClusterClientFactory.java b/launcher/src/main/java/com/dtstack/flink/sql/launcher/factory/YarnClusterClientFactory.java deleted file mode 100644 index 58d32cfac..000000000 --- a/launcher/src/main/java/com/dtstack/flink/sql/launcher/factory/YarnClusterClientFactory.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.launcher.factory; - -import org.apache.commons.lang.StringUtils; -import org.apache.flink.client.deployment.ClusterDescriptor; -import org.apache.flink.configuration.ConfigConstants; -import org.apache.flink.configuration.Configuration; -import org.apache.flink.core.fs.FileSystem; -import org.apache.flink.runtime.security.SecurityConfiguration; -import org.apache.flink.runtime.security.SecurityUtils; -import org.apache.flink.util.FileUtils; -import org.apache.flink.util.function.FunctionUtils; -import org.apache.flink.yarn.YarnClientYarnClusterInformationRetriever; -import org.apache.flink.yarn.YarnClusterDescriptor; -import org.apache.hadoop.yarn.client.api.YarnClient; -import org.apache.hadoop.yarn.conf.YarnConfiguration; - -import java.io.File; -import java.io.IOException; -import java.util.Iterator; -import java.util.Map; - - -/** - * Date: 2020/3/4 - * Company: www.dtstack.com - * @author maqi - */ -public enum YarnClusterClientFactory implements AbstractClusterClientFactory { - INSTANCE; - - private static final String XML_FILE_EXTENSION = "xml"; - - @Override - public ClusterDescriptor createClusterDescriptor(String yarnConfDir, Configuration flinkConfig) { - - if (StringUtils.isNotBlank(yarnConfDir)) { - try { - flinkConfig.setString(ConfigConstants.PATH_HADOOP_CONFIG, yarnConfDir); - FileSystem.initialize(flinkConfig, null); - - SecurityUtils.install(new SecurityConfiguration(flinkConfig)); - - YarnConfiguration yarnConf = getYarnConf(yarnConfDir); - YarnClient yarnClient = YarnClient.createYarnClient(); - yarnClient.init(yarnConf); - yarnClient.start(); - - YarnClusterDescriptor clusterDescriptor = new YarnClusterDescriptor( - flinkConfig, - yarnConf, - yarnClient, - YarnClientYarnClusterInformationRetriever.create(yarnClient), - false); - - return clusterDescriptor; - } catch (Exception e) { - throw new RuntimeException(e); - } - } else { - throw new RuntimeException("yarn mode must set param of 'yarnconf'!!!"); - } - } - - private YarnConfiguration getYarnConf(String yarnConfDir) throws IOException { - YarnConfiguration yarnConf = new YarnConfiguration(); - FileUtils.listFilesInDirectory(new File(yarnConfDir).toPath(), this::isXmlFile) - .stream() - .map(FunctionUtils.uncheckedFunction(FileUtils::toURL)) - .forEach(yarnConf::addResource); - - haYarnConf(yarnConf); - return yarnConf; - } - - /** - * deal yarn HA conf - */ - private org.apache.hadoop.conf.Configuration haYarnConf(org.apache.hadoop.conf.Configuration yarnConf) { - Iterator> iterator = yarnConf.iterator(); - iterator.forEachRemaining((Map.Entry entry) -> { - String key = entry.getKey(); - String value = entry.getValue(); - if (key.startsWith("yarn.resourcemanager.hostname.")) { - String rm = key.substring("yarn.resourcemanager.hostname.".length()); - String addressKey = "yarn.resourcemanager.address." + rm; - if (yarnConf.get(addressKey) == null) { - yarnConf.set(addressKey, value + ":" + YarnConfiguration.DEFAULT_RM_PORT); - } - } - }); - - return yarnConf; - } - - private boolean isXmlFile(java.nio.file.Path file) { - return XML_FILE_EXTENSION.equals(org.apache.flink.shaded.guava18.com.google.common.io.Files.getFileExtension(file.toString())); - } -} diff --git a/launcher/src/main/java/com/dtstack/flink/sql/launcher/perjob/FLinkPerJobResourceUtil.java b/launcher/src/main/java/com/dtstack/flink/sql/launcher/perjob/FLinkPerJobResourceUtil.java new file mode 100644 index 000000000..468039cb2 --- /dev/null +++ b/launcher/src/main/java/com/dtstack/flink/sql/launcher/perjob/FLinkPerJobResourceUtil.java @@ -0,0 +1,80 @@ +/** + * 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 com.dtstack.flink.sql.launcher.perjob; + + +import com.dtstack.flink.sql.util.MathUtil; +import org.apache.flink.client.deployment.ClusterSpecification; + +import java.util.Properties; + +/** + * company: www.dtstack.com + * author xuchao + * create: 2018/7/5 + */ +public class FLinkPerJobResourceUtil { + + public final static int MIN_JM_MEMORY = 768; // the minimum memory should be higher than the min heap cutoff + public final static int MIN_TM_MEMORY = 768; + + public final static String JOBMANAGER_MEMORY_MB = "jobmanager.memory.mb"; + public final static String TASKMANAGER_MEMORY_MB = "taskmanager.memory.mb"; + public final static String NUMBER_TASK_MANAGERS = "taskmanager.num"; + public final static String SLOTS_PER_TASKMANAGER = "taskmanager.slots"; + + public static ClusterSpecification createClusterSpecification(Properties confProperties) { + int jobmanagerMemoryMb = 768; + int taskmanagerMemoryMb = 768; + int numberTaskManagers = 1; + int slotsPerTaskManager = 1; + + if (confProperties != null) { + if (confProperties.containsKey(JOBMANAGER_MEMORY_MB)){ + jobmanagerMemoryMb = MathUtil.getIntegerVal(confProperties.get(JOBMANAGER_MEMORY_MB)); + if (jobmanagerMemoryMb < MIN_JM_MEMORY) { + jobmanagerMemoryMb = MIN_JM_MEMORY; + } + } + + if (confProperties.containsKey(TASKMANAGER_MEMORY_MB)){ + taskmanagerMemoryMb = MathUtil.getIntegerVal(confProperties.get(TASKMANAGER_MEMORY_MB)); + if (taskmanagerMemoryMb < MIN_TM_MEMORY) { + taskmanagerMemoryMb = MIN_TM_MEMORY; + } + } + + if (confProperties.containsKey(NUMBER_TASK_MANAGERS)){ + numberTaskManagers = MathUtil.getIntegerVal(confProperties.get(NUMBER_TASK_MANAGERS)); + } + + if (confProperties.containsKey(SLOTS_PER_TASKMANAGER)){ + slotsPerTaskManager = MathUtil.getIntegerVal(confProperties.get(SLOTS_PER_TASKMANAGER)); + } + } + + return new ClusterSpecification.ClusterSpecificationBuilder() + .setMasterMemoryMB(jobmanagerMemoryMb) + .setTaskManagerMemoryMB(taskmanagerMemoryMb) + .setNumberTaskManagers(numberTaskManagers) + .setSlotsPerTaskManager(slotsPerTaskManager) + .createClusterSpecification(); + } + +} diff --git a/launcher/src/main/java/com/dtstack/flink/sql/launcher/perjob/PerJobClusterClientBuilder.java b/launcher/src/main/java/com/dtstack/flink/sql/launcher/perjob/PerJobClusterClientBuilder.java new file mode 100644 index 000000000..5dc0971bc --- /dev/null +++ b/launcher/src/main/java/com/dtstack/flink/sql/launcher/perjob/PerJobClusterClientBuilder.java @@ -0,0 +1,144 @@ +/** + * 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 com.dtstack.flink.sql.launcher.perjob; + +import com.dtstack.flink.sql.enums.EPluginLoadMode; +import com.dtstack.flink.sql.launcher.YarnConfLoader; +import com.dtstack.flink.sql.option.Options; +import org.apache.commons.lang3.StringUtils; +import org.apache.flink.api.common.cache.DistributedCache; +import org.apache.flink.configuration.Configuration; +import com.google.common.base.Strings; +import org.apache.flink.runtime.jobgraph.JobGraph; +import org.apache.flink.yarn.AbstractYarnClusterDescriptor; +import org.apache.flink.yarn.YarnClusterDescriptor; +import org.apache.hadoop.fs.Path; +import org.apache.hadoop.yarn.client.api.YarnClient; +import org.apache.hadoop.yarn.conf.YarnConfiguration; + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +/** + * Reason: + * Date: 2018/11/16 + * Company: www.dtstack.com + * @author xuchao + */ + +public class PerJobClusterClientBuilder { + private YarnClient yarnClient; + + private YarnConfiguration yarnConf; + + public void init(String yarnConfDir){ + if(Strings.isNullOrEmpty(yarnConfDir)) { + throw new RuntimeException("parameters of yarn is required"); + } + + yarnConf = YarnConfLoader.getYarnConf(yarnConfDir); + yarnClient = YarnClient.createYarnClient(); + yarnClient.init(yarnConf); + yarnClient.start(); + + System.out.println("----init yarn success ----"); + } + + public AbstractYarnClusterDescriptor createPerJobClusterDescriptor(Properties confProp, String flinkJarPath, Options launcherOptions, JobGraph jobGraph) throws MalformedURLException { + Configuration newConf = new Configuration(); + confProp.forEach((key, val) -> newConf.setString(key.toString(), val.toString())); + + AbstractYarnClusterDescriptor clusterDescriptor = getClusterDescriptor(newConf, yarnConf, "."); + + if (StringUtils.isNotBlank(flinkJarPath)) { + if (!new File(flinkJarPath).exists()) { + throw new RuntimeException("The Flink jar path is not exist"); + } + } + + List shipFiles = new ArrayList<>(); + if (flinkJarPath != null) { + File[] jars = new File(flinkJarPath).listFiles(); + for (File file : jars) { + if (file.toURI().toURL().toString().contains("flink-dist")) { + clusterDescriptor.setLocalJarPath(new Path(file.toURI().toURL().toString())); + } else { + shipFiles.add(file); + } + } + } else { + throw new RuntimeException("The Flink jar path is null"); + } + // classpath , all node need contain plugin jar + String pluginLoadMode = launcherOptions.getPluginLoadMode(); + if (StringUtils.equalsIgnoreCase(pluginLoadMode, EPluginLoadMode.CLASSPATH.name())) { + fillJobGraphClassPath(jobGraph); + } else if (StringUtils.equalsIgnoreCase(pluginLoadMode, EPluginLoadMode.SHIPFILE.name())) { + List pluginPaths = getPluginPathToShipFiles(jobGraph); + shipFiles.addAll(pluginPaths); + } else { + throw new IllegalArgumentException("Unsupported plugin loading mode " + pluginLoadMode + + " Currently only classpath and shipfile are supported."); + } + + clusterDescriptor.addShipFiles(shipFiles); + String queue = launcherOptions.getQueue(); + if (!Strings.isNullOrEmpty(queue)) { + clusterDescriptor.setQueue(queue); + } + return clusterDescriptor; + } + + private static void fillJobGraphClassPath(JobGraph jobGraph) throws MalformedURLException { + Map jobCacheFileConfig = jobGraph.getUserArtifacts(); + for(Map.Entry tmp : jobCacheFileConfig.entrySet()){ + if(tmp.getKey().startsWith("class_path")){ + jobGraph.getClasspaths().add(new URL("file:" + tmp.getValue().filePath)); + } + } + } + + private List getPluginPathToShipFiles(JobGraph jobGraph) { + List shipFiles = new ArrayList<>(); + Map jobCacheFileConfig = jobGraph.getUserArtifacts(); + for(Map.Entry tmp : jobCacheFileConfig.entrySet()){ + if(tmp.getKey().startsWith("class_path")){ + shipFiles.add(new File(tmp.getValue().filePath)); + } + } + return shipFiles; + } + + private AbstractYarnClusterDescriptor getClusterDescriptor( + Configuration configuration, + YarnConfiguration yarnConfiguration, + String configurationDirectory) { + return new YarnClusterDescriptor( + configuration, + yarnConfiguration, + configurationDirectory, + yarnClient, + false); + } +} diff --git a/launcher/src/main/java/com/dtstack/flink/sql/launcher/perjob/PerJobSubmitter.java b/launcher/src/main/java/com/dtstack/flink/sql/launcher/perjob/PerJobSubmitter.java new file mode 100644 index 000000000..55b55be2f --- /dev/null +++ b/launcher/src/main/java/com/dtstack/flink/sql/launcher/perjob/PerJobSubmitter.java @@ -0,0 +1,89 @@ +/* + * 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 com.dtstack.flink.sql.launcher.perjob; + +import com.dtstack.flink.sql.option.Options; +import com.dtstack.flink.sql.util.PluginUtil; +import org.apache.commons.io.Charsets; +import org.apache.commons.lang3.StringUtils; +import org.apache.flink.client.deployment.ClusterSpecification; +import org.apache.flink.client.program.ClusterClient; +import org.apache.flink.core.fs.Path; +import org.apache.flink.runtime.jobgraph.JobGraph; +import org.apache.flink.yarn.AbstractYarnClusterDescriptor; +import org.apache.hadoop.yarn.api.records.ApplicationId; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.net.URLDecoder; +import java.util.Arrays; +import java.util.List; +import java.util.Properties; + +/** + * per job mode submitter + * Date: 2018/11/17 + * Company: www.dtstack.com + * @author xuchao + */ + +public class PerJobSubmitter { + + private static final Logger LOG = LoggerFactory.getLogger(PerJobSubmitter.class); + + public static String submit(Options launcherOptions, JobGraph jobGraph) throws Exception { + if (!StringUtils.isBlank(launcherOptions.getAddjar())) { + String addjarPath = URLDecoder.decode(launcherOptions.getAddjar(), Charsets.UTF_8.toString()); + List paths = getJarPaths(addjarPath); + paths.forEach( path -> { + jobGraph.addJar(new Path("file://" + path)); + }); + } + + String confProp = launcherOptions.getConfProp(); + confProp = URLDecoder.decode(confProp, Charsets.UTF_8.toString()); + Properties confProperties = PluginUtil.jsonStrToObject(confProp, Properties.class); + ClusterSpecification clusterSpecification = FLinkPerJobResourceUtil.createClusterSpecification(confProperties); + + PerJobClusterClientBuilder perJobClusterClientBuilder = new PerJobClusterClientBuilder(); + perJobClusterClientBuilder.init(launcherOptions.getYarnconf()); + + String flinkJarPath = launcherOptions.getFlinkJarPath(); + + AbstractYarnClusterDescriptor yarnClusterDescriptor = perJobClusterClientBuilder.createPerJobClusterDescriptor(confProperties, flinkJarPath, launcherOptions, jobGraph); + ClusterClient clusterClient = yarnClusterDescriptor.deployJobCluster(clusterSpecification, jobGraph,true); + + String applicationId = clusterClient.getClusterId().toString(); + String flinkJobId = jobGraph.getJobID().toString(); + + String tips = String.format("deploy per_job with appId: %s, jobId: %s", applicationId, flinkJobId); + System.out.println(tips); + LOG.info(tips); + + return applicationId; + } + + private static List getJarPaths(String addjarPath) { + if (addjarPath.length() > 2) { + addjarPath = addjarPath.substring(1,addjarPath.length()-1).replace("\"",""); + } + List paths = Arrays.asList(addjarPath.split(",")); + return paths; + } + +} diff --git a/launcher/src/main/java/com/dtstack/flink/sql/launcher/utils/JobGraphBuildUtil.java b/launcher/src/main/java/com/dtstack/flink/sql/launcher/utils/JobGraphBuildUtil.java deleted file mode 100644 index f05ed41ab..000000000 --- a/launcher/src/main/java/com/dtstack/flink/sql/launcher/utils/JobGraphBuildUtil.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.launcher.utils; - -import com.dtstack.flink.sql.constrant.ConfigConstrant; -import com.dtstack.flink.sql.launcher.entity.JobParamsInfo; -import com.dtstack.flink.sql.util.MathUtil; -import com.dtstack.flink.sql.util.PluginUtil; -import org.apache.commons.io.Charsets; -import org.apache.commons.lang.BooleanUtils; -import org.apache.commons.lang.StringUtils; -import org.apache.flink.api.common.cache.DistributedCache; -import org.apache.flink.client.program.PackagedProgram; -import org.apache.flink.client.program.PackagedProgramUtils; -import org.apache.flink.configuration.Configuration; -import org.apache.flink.configuration.GlobalConfiguration; -import org.apache.flink.core.fs.Path; -import org.apache.flink.runtime.jobgraph.JobGraph; -import org.apache.flink.runtime.jobgraph.SavepointRestoreSettings; -import org.apache.flink.util.function.FunctionUtils; - -import java.io.File; -import java.io.UnsupportedEncodingException; -import java.net.URL; -import java.net.URLDecoder; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.stream.Collectors; - -/** - * build JobGraph by JobParamsInfo - * Date: 2020/3/4 - * Company: www.dtstack.com - * @author maqi - */ -public class JobGraphBuildUtil { - - private static final String SP = File.separator; - private static final String CORE_JAR = "core"; - - private static String findLocalCoreJarPath(String localSqlRootJar, String pluginLoadMode) throws Exception { - String jarPath = PluginUtil.getCoreJarFileName(localSqlRootJar, CORE_JAR, pluginLoadMode); - return localSqlRootJar + SP + jarPath; - } - - public static JobGraph buildJobGraph(JobParamsInfo jobParamsInfo) throws Exception { - Properties confProperties = jobParamsInfo.getConfProperties(); - int parallelism = MathUtil.getIntegerVal(confProperties.getProperty(ConfigConstrant.SQL_ENV_PARALLELISM, "1")); - String flinkConfDir = jobParamsInfo.getFlinkConfDir(); - - String[] execArgs = jobParamsInfo.getExecArgs(); - File coreJarFile = new File(findLocalCoreJarPath(jobParamsInfo.getLocalPluginRoot(), jobParamsInfo.getPluginLoadMode())); - SavepointRestoreSettings savepointRestoreSettings = dealSavepointRestoreSettings(jobParamsInfo.getConfProperties()); - - PackagedProgram program = PackagedProgram.newBuilder() - .setJarFile(coreJarFile) - .setArguments(execArgs) - .setSavepointRestoreSettings(savepointRestoreSettings) - .build(); - - Configuration flinkConfig = getFlinkConfiguration(flinkConfDir, confProperties); - JobGraph jobGraph = PackagedProgramUtils.createJobGraph(program, flinkConfig, parallelism, false); - return jobGraph; - } - - - protected static SavepointRestoreSettings dealSavepointRestoreSettings(Properties confProperties) { - SavepointRestoreSettings savepointRestoreSettings = SavepointRestoreSettings.none(); - String savePointPath = confProperties.getProperty(ConfigConstrant.SAVE_POINT_PATH_KEY); - if (StringUtils.isNotBlank(savePointPath)) { - String allowNonRestoredState = confProperties.getOrDefault(ConfigConstrant.ALLOW_NON_RESTORED_STATE_KEY, "false").toString(); - savepointRestoreSettings = SavepointRestoreSettings.forPath(savePointPath, BooleanUtils.toBoolean(allowNonRestoredState)); - } - return savepointRestoreSettings; - } - - public static Configuration getFlinkConfiguration(String flinkConfDir, Properties confProperties) { - Configuration flinkConfig = StringUtils.isEmpty(flinkConfDir) ? new Configuration() : GlobalConfiguration.loadConfiguration(flinkConfDir); - - confProperties.forEach((key, val) -> flinkConfig.setString(key.toString(), val.toString())); - return flinkConfig; - } - - public static void fillUserJarForJobGraph(String jarPath, JobGraph jobGraph) throws UnsupportedEncodingException { - String addjarPath = URLDecoder.decode(jarPath, Charsets.UTF_8.toString()); - if (addjarPath.length() > 2) { - addjarPath = addjarPath.substring(1, addjarPath.length() - 1).replace("\"", ""); - } - List paths = Arrays.asList(addjarPath.split(",")); - paths.forEach(path -> jobGraph.addJar(new Path("file://" + path))); - } - - public static void fillJobGraphClassPath(JobGraph jobGraph) { - Map jobCacheFileConfig = jobGraph.getUserArtifacts(); - List classPath = jobCacheFileConfig.entrySet().stream() - .filter(tmp -> tmp.getKey().startsWith("class_path")) - .map(FunctionUtils.uncheckedFunction(tmp -> new URL("file:" + tmp.getValue().filePath))) - .collect(Collectors.toList()); - - jobGraph.getUserArtifacts().clear(); - jobGraph.setClasspaths(classPath); - } - - public static List getPluginPathToShipFiles(JobGraph jobGraph) { - List shipFiles = jobGraph.getUserArtifacts() - .entrySet() - .stream() - .filter(tmp -> tmp.getKey().startsWith("class_path")) - .map(tmp -> new File(tmp.getValue().filePath)) - .collect(Collectors.toList()); - - jobGraph.getUserArtifacts().clear(); - return shipFiles; - } -} diff --git a/launcher/src/main/java/com/dtstack/flink/sql/yarn/JobParameter.java b/launcher/src/main/java/com/dtstack/flink/sql/yarn/JobParameter.java new file mode 100644 index 000000000..abfa0a8ad --- /dev/null +++ b/launcher/src/main/java/com/dtstack/flink/sql/yarn/JobParameter.java @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2018 The Sylph Authors + * + * Licensed 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 com.dtstack.flink.sql.yarn; + +import java.util.Objects; +import java.util.Properties; + +public class JobParameter +{ + private int parallelism = 1; + private String queue = "default"; + private int taskManagerMemoryMb = 1024; + private int taskManagerCount = 1; + private int taskManagerSlots = 1; + private int jobManagerMemoryMb = 1024; + + public JobParameter() {} + + public JobParameter(Properties confProperties) { + this.parallelism = confProperties.getProperty("parallelism")==null?parallelism:Integer.parseInt(confProperties.getProperty("parallelism")); + this.queue = confProperties.getProperty("queue")==null?queue:confProperties.getProperty("queue"); + this.taskManagerMemoryMb = confProperties.getProperty("taskManagerMemoryMb")==null?taskManagerMemoryMb:Integer.parseInt(confProperties.getProperty("taskManagerMemoryMb")); + this.taskManagerCount = confProperties.getProperty("taskManagerCount")==null?taskManagerCount:Integer.parseInt(confProperties.getProperty("taskManagerCount")); + this.taskManagerSlots = confProperties.getProperty("taskManagerSlots")==null?taskManagerSlots:Integer.parseInt(confProperties.getProperty("taskManagerSlots")); + this.jobManagerMemoryMb = confProperties.getProperty("jobManagerMemoryMb")==null?jobManagerMemoryMb:Integer.parseInt(confProperties.getProperty("jobManagerMemoryMb")); + } + + public JobParameter(int parallelism, String queue, int taskManagerMemoryMb, int taskManagerCount, int taskManagerSlots, int jobManagerMemoryMb) { + this.parallelism = parallelism; + this.queue = queue; + this.taskManagerMemoryMb = taskManagerMemoryMb; + this.taskManagerCount = taskManagerCount; + this.taskManagerSlots = taskManagerSlots; + this.jobManagerMemoryMb = jobManagerMemoryMb; + } + + public void setQueue(String queue) + { + this.queue = queue; + } + + public void setTaskManagerCount(int taskManagerCount) + { + this.taskManagerCount = taskManagerCount; + } + + public void setTaskManagerMemoryMb(int taskManagerMemoryMb) + { + this.taskManagerMemoryMb = taskManagerMemoryMb; + } + + public void setTaskManagerSlots(int taskManagerSlots) + { + this.taskManagerSlots = taskManagerSlots; + } + + public void setJobManagerMemoryMb(int jobManagerMemoryMb) + { + this.jobManagerMemoryMb = jobManagerMemoryMb; + } + + public void setParallelism(int parallelism) + { + this.parallelism = parallelism; + } + + public int getParallelism() + { + return parallelism; + } + + public String getQueue() + { + return queue; + } + + public int getJobManagerMemoryMb() + { + return jobManagerMemoryMb; + } + + public int getTaskManagerSlots() + { + return taskManagerSlots; + } + + public int getTaskManagerCount() + { + return taskManagerCount; + } + + public int getTaskManagerMemoryMb() + { + return taskManagerMemoryMb; + } + + @Override + public boolean equals(Object o) + { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + JobParameter jobParameter = (JobParameter) o; + return Objects.equals(this.queue, jobParameter.queue) && + Objects.equals(this.taskManagerCount, jobParameter.taskManagerCount) && + Objects.equals(this.taskManagerMemoryMb, jobParameter.taskManagerMemoryMb); + } + + @Override + public int hashCode() + { + return Objects.hash(queue, taskManagerMemoryMb, taskManagerCount); + } +} diff --git a/launcher/src/main/java/com/dtstack/flink/sql/yarn/YarnClusterConfiguration.java b/launcher/src/main/java/com/dtstack/flink/sql/yarn/YarnClusterConfiguration.java new file mode 100644 index 000000000..2189e9a9a --- /dev/null +++ b/launcher/src/main/java/com/dtstack/flink/sql/yarn/YarnClusterConfiguration.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2018 The Sylph Authors + * + * Licensed 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 com.dtstack.flink.sql.yarn; + +import org.apache.flink.configuration.Configuration; +import org.apache.hadoop.fs.Path; +import org.apache.hadoop.yarn.conf.YarnConfiguration; + +import java.util.Set; + +public class YarnClusterConfiguration { + /** + * The configuration used by YARN (i.e.,
yarn-site.xml
). + */ + private final YarnConfiguration yarnConf; + + /** + * The home directory of all job where all the temporary files for each jobs are stored. + */ + private final String appRootDir; + + /** + * Thepublic YarnClusterConfiguration(Configuration , YarnConfiguration , String , Path , Set ) { + } location of the Flink jar. + */ + private final Path flinkJar; + + /** + * Additional resources to be localized for both JobManager and TaskManager. + * They will NOT be added into the classpaths. + */ + private final Set resourcesToLocalize; + + /** + * flink conf + */ + private final Configuration flinkConfiguration; + + public YarnClusterConfiguration( + Configuration flinkConf, + YarnConfiguration conf, + String appRootDir, + Path flinkJar, + Set resourcesToLocalize) { + this.flinkConfiguration = flinkConf; + this.yarnConf = conf; + this.appRootDir = appRootDir; + this.flinkJar = flinkJar; + this.resourcesToLocalize = resourcesToLocalize; + } + + + + YarnConfiguration yarnConf() { + return yarnConf; + } + + public String appRootDir() { + return appRootDir; + } + + public Configuration flinkConfiguration() { + return flinkConfiguration; + } + + public Path flinkJar() { + return flinkJar; + } + + public Set resourcesToLocalize() { + return resourcesToLocalize; + } + +} diff --git a/launcher/src/main/java/com/dtstack/flink/sql/yarn/YarnClusterDescriptor.java b/launcher/src/main/java/com/dtstack/flink/sql/yarn/YarnClusterDescriptor.java new file mode 100644 index 000000000..989a4400a --- /dev/null +++ b/launcher/src/main/java/com/dtstack/flink/sql/yarn/YarnClusterDescriptor.java @@ -0,0 +1,396 @@ +/* + * Copyright (C) 2018 The Sylph Authors + * + * Licensed 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 com.dtstack.flink.sql.yarn; + +import org.apache.flink.client.deployment.ClusterDeploymentException; +import org.apache.flink.client.deployment.ClusterSpecification; +import org.apache.flink.client.program.ClusterClient; +import org.apache.flink.client.program.rest.RestClusterClient; +import org.apache.flink.configuration.Configuration; +import org.apache.flink.configuration.JobManagerOptions; +import org.apache.flink.runtime.jobgraph.JobGraph; +import org.apache.flink.yarn.*; +import org.apache.flink.yarn.entrypoint.YarnSessionClusterEntrypoint; +import org.apache.hadoop.fs.FileStatus; +import org.apache.hadoop.fs.FileSystem; +import org.apache.hadoop.fs.Path; +import org.apache.hadoop.security.UserGroupInformation; +import org.apache.hadoop.yarn.api.records.*; +import org.apache.hadoop.yarn.client.api.YarnClient; +import org.apache.hadoop.yarn.exceptions.YarnException; +import org.apache.hadoop.yarn.util.ConverterUtils; +import org.apache.hadoop.yarn.util.Records; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.*; +import java.util.concurrent.*; +import java.util.stream.Collectors; + +import static java.util.Objects.requireNonNull; +import static org.apache.hadoop.yarn.api.records.YarnApplicationState.NEW; + +public class YarnClusterDescriptor + extends AbstractYarnClusterDescriptor +{ + private static final String APPLICATION_TYPE = "58_FLINK"; + private static final Logger LOG = LoggerFactory.getLogger(YarnClusterDescriptor.class); + private static final int MAX_ATTEMPT = 1; + private static final long DEPLOY_TIMEOUT_MS = 600 * 1000; + private static final long RETRY_DELAY_MS = 250; + private static final ScheduledExecutorService YARN_POLL_EXECUTOR = Executors.newSingleThreadScheduledExecutor(); + + private final YarnClusterConfiguration clusterConf; + private final YarnClient yarnClient; + private final JobParameter appConf; + private final Path homedir; + private final ApplicationId yarnAppId; + private final String jobName; + private final Iterable userProvidedJars; + private Path flinkJar; + + public YarnClusterDescriptor( + final YarnClusterConfiguration clusterConf, + final YarnClient yarnClient, + final JobParameter appConf, + ApplicationId yarnAppId, + String jobName, + Iterable userProvidedJars) + { + super(clusterConf.flinkConfiguration(), clusterConf.yarnConf(), clusterConf.appRootDir(), yarnClient, false); + this.jobName = jobName; + this.clusterConf = clusterConf; + this.yarnClient = yarnClient; + this.appConf = appConf; + this.yarnAppId = yarnAppId; + this.userProvidedJars = userProvidedJars; + this.homedir = new Path(clusterConf.appRootDir(), yarnAppId.toString()); + } + + @Override + protected String getYarnSessionClusterEntrypoint() + { + return YarnSessionClusterEntrypoint.class.getName(); + } + + /** + * 提交到yarn时 任务启动入口类 + */ + @Override + protected String getYarnJobClusterEntrypoint() + { + return YarnSessionClusterEntrypoint.class.getName(); + } + + @Override + protected ClusterClient createYarnClusterClient(AbstractYarnClusterDescriptor descriptor, int numberTaskManagers, int slotsPerTaskManager, ApplicationReport report, Configuration flinkConfiguration, boolean perJobCluster) + throws Exception + { + return new RestClusterClient<>( + flinkConfiguration, + report.getApplicationId()); + } + + @Override + public YarnClient getYarnClient() + { + return this.yarnClient; + } + + public RestClusterClient deploy() + { + ApplicationSubmissionContext context = Records.newRecord(ApplicationSubmissionContext.class); + context.setApplicationId(yarnAppId); + try { + ApplicationReport report = startAppMaster(context); + + Configuration conf = getFlinkConfiguration(); + conf.setString(JobManagerOptions.ADDRESS.key(), report.getHost()); + conf.setInteger(JobManagerOptions.PORT.key(), report.getRpcPort()); + + /*return new RestClusterClient(this, + appConf.getTaskManagerCount(), + appConf.getTaskManagerSlots(), + report, conf, false);*/ + return new RestClusterClient<>( + conf, + report.getApplicationId()); + } + catch (Exception e) { + throw new RuntimeException(e); + } + } + + private ApplicationReport startAppMaster(ApplicationSubmissionContext appContext) + throws Exception + { + ApplicationId appId = appContext.getApplicationId(); + appContext.setMaxAppAttempts(MAX_ATTEMPT); + + Map localResources = new HashMap<>(); + Set shippedPaths = new HashSet<>(); + collectLocalResources(localResources, shippedPaths); + + final ContainerLaunchContext amContainer = setupApplicationMasterContainer( + getYarnJobClusterEntrypoint(), + false, + true, + false, + appConf.getJobManagerMemoryMb() + ); + + amContainer.setLocalResources(localResources); + + final String classPath = String.join(File.pathSeparator, localResources.keySet()); + + final String shippedFiles = shippedPaths.stream() + .map(path -> path.getName() + "=" + path) + .collect(Collectors.joining(",")); + + // Setup CLASSPATH and environment variables for ApplicationMaster + final Map appMasterEnv = setUpAmEnvironment( + appId, + classPath,shippedFiles, + //"","", + getDynamicPropertiesEncoded() + ); + + amContainer.setEnvironment(appMasterEnv); + + // Set up resource type requirements for ApplicationMaster + Resource capability = Records.newRecord(Resource.class); + capability.setMemory(appConf.getJobManagerMemoryMb()); //设置jobManneger + capability.setVirtualCores(1); //默认是1 + + appContext.setApplicationName(jobName); + appContext.setApplicationType(APPLICATION_TYPE); + appContext.setAMContainerSpec(amContainer); + appContext.setResource(capability); + //appContext.setApplicationTags(appConf.getAppTags()); + if (appConf.getQueue() != null) { + appContext.setQueue(appConf.getQueue()); + } + + LOG.info("Submitting application master {}", appId); + yarnClient.submitApplication(appContext); + + PollDeploymentStatus poll = new PollDeploymentStatus(appId); + YARN_POLL_EXECUTOR.submit(poll); + try { + return poll.result.get(); + } + catch (ExecutionException e) { + LOG.warn("Failed to deploy {}, cause: {}", appId.toString(), e.getCause()); + yarnClient.killApplication(appId); + throw (Exception) e.getCause(); + } + } + + private void collectLocalResources( + Map resources, + Set shippedPaths + ) + throws IOException, URISyntaxException + { + if(clusterConf.flinkJar() != null) { + Path flinkJar = clusterConf.flinkJar(); + LocalResource flinkJarResource = setupLocalResource(flinkJar, homedir, ""); //放到 Appid/根目录下 + this.flinkJar = ConverterUtils.getPathFromYarnURL(flinkJarResource.getResource()); + resources.put("flink.jar", flinkJarResource); + } + if(clusterConf.resourcesToLocalize() != null) { + for (Path p : clusterConf.resourcesToLocalize()) { //主要是 flink.jar log4f.propors 和 flink.yaml 三个文件 + LocalResource resource = setupLocalResource(p, homedir, ""); //这些需要放到根目录下 + resources.put(p.getName(), resource); + if ("log4j.properties".equals(p.getName())) { + shippedPaths.add(ConverterUtils.getPathFromYarnURL(resource.getResource())); + } + } + } + if(userProvidedJars != null) { + for (Path p : userProvidedJars) { + String name = p.getName(); + if (resources.containsKey(name)) { //这里当jar 有重复的时候 会抛出异常 + LOG.warn("Duplicated name in the shipped files {}", p); + } else { + LocalResource resource = setupLocalResource(p, homedir, "jars"); //这些放到 jars目录下 + resources.put(name, resource); + shippedPaths.add(ConverterUtils.getPathFromYarnURL(resource.getResource())); + } + } + } + } + + private LocalResource registerLocalResource(FileSystem fs, Path remoteRsrcPath) + throws IOException + { + LocalResource localResource = Records.newRecord(LocalResource.class); + FileStatus jarStat = fs.getFileStatus(remoteRsrcPath); + localResource.setResource(ConverterUtils.getYarnUrlFromURI(remoteRsrcPath.toUri())); + localResource.setSize(jarStat.getLen()); + localResource.setTimestamp(jarStat.getModificationTime()); + localResource.setType(LocalResourceType.FILE); + localResource.setVisibility(LocalResourceVisibility.APPLICATION); + return localResource; + } + + private LocalResource setupLocalResource( + Path localSrcPath, + Path homedir, + String relativeTargetPath) + throws IOException + { + if (new File(localSrcPath.toUri().getPath()).isDirectory()) { + throw new IllegalArgumentException("File to copy must not be a directory: " + + localSrcPath); + } + + // copy resource to HDFS + String suffix = "." + (relativeTargetPath.isEmpty() ? "" : "/" + relativeTargetPath) + + "/" + localSrcPath.getName(); + + Path dst = new Path(homedir, suffix); + + LOG.info("Uploading {}", dst); + + FileSystem hdfs = FileSystem.get(clusterConf.yarnConf()); + hdfs.copyFromLocalFile(false, true, localSrcPath, dst); + + // now create the resource instance + LocalResource resource = registerLocalResource(hdfs, dst); + return resource; + } + + private Map setUpAmEnvironment( + ApplicationId appId, + String amClassPath, + String shipFiles, + String dynamicProperties) + throws IOException, URISyntaxException + { + final Map appMasterEnv = new HashMap<>(); + + // set Flink app class path + appMasterEnv.put(YarnConfigKeys.ENV_FLINK_CLASSPATH, amClassPath); + + // set Flink on YARN internal configuration values + appMasterEnv.put(YarnConfigKeys.ENV_TM_COUNT, String.valueOf(appConf.getTaskManagerCount())); + appMasterEnv.put(YarnConfigKeys.ENV_TM_MEMORY, String.valueOf(appConf.getTaskManagerMemoryMb())); + appMasterEnv.put(YarnConfigKeys.ENV_SLOTS, String.valueOf(appConf.getTaskManagerSlots())); + appMasterEnv.put(YarnConfigKeys.FLINK_JAR_PATH, flinkJar.toString()); + appMasterEnv.put(YarnConfigKeys.ENV_APP_ID, appId.toString()); + appMasterEnv.put(YarnConfigKeys.ENV_CLIENT_HOME_DIR, homedir.toString()); //$home/.flink/appid 这个目录里面存放临时数据 + appMasterEnv.put(YarnConfigKeys.ENV_CLIENT_SHIP_FILES, shipFiles); + + appMasterEnv.put(YarnConfigKeys.ENV_DETACHED, String.valueOf(true)); //是否分离 分离就cluser模式 否则是client模式 + + appMasterEnv.put(YarnConfigKeys.ENV_HADOOP_USER_NAME, + UserGroupInformation.getCurrentUser().getUserName()); + + if (dynamicProperties != null) { + appMasterEnv.put(YarnConfigKeys.ENV_DYNAMIC_PROPERTIES, dynamicProperties); + } + + // set classpath from YARN configuration + Utils.setupYarnClassPath(clusterConf.yarnConf(), appMasterEnv); + + return appMasterEnv; + } + + /** + * flink 1.5 add + */ + @Override + public ClusterClient deployJobCluster(ClusterSpecification clusterSpecification, JobGraph jobGraph, boolean detached) + throws ClusterDeploymentException + { + throw new UnsupportedOperationException("this method have't support!"); + } + + private final class PollDeploymentStatus + implements Runnable + { + private final CompletableFuture result = new CompletableFuture<>(); + private final ApplicationId appId; + private YarnApplicationState lastAppState = NEW; + private long startTime; + + private PollDeploymentStatus(ApplicationId appId) + { + this.appId = appId; + } + + @Override + public void run() + { + if (startTime == 0) { + startTime = System.currentTimeMillis(); + } + + try { + ApplicationReport report = poll(); + if (report == null) { + YARN_POLL_EXECUTOR.schedule(this, RETRY_DELAY_MS, TimeUnit.MILLISECONDS); + } + else { + result.complete(report); + } + } + catch (YarnException | IOException e) { + result.completeExceptionally(e); + } + } + + private ApplicationReport poll() + throws IOException, YarnException + { + ApplicationReport report; + report = yarnClient.getApplicationReport(appId); + YarnApplicationState appState = report.getYarnApplicationState(); + LOG.debug("Application State: {}", appState); + + switch (appState) { + case FAILED: + case FINISHED: + //TODO: the finished state may be valid in flip-6 + case KILLED: + throw new IOException("The YARN application unexpectedly switched to state " + + appState + " during deployment. \n" + + "Diagnostics from YARN: " + report.getDiagnostics() + "\n" + + "If log aggregation is enabled on your cluster, use this command to further investigate the issue:\n" + + "yarn logs -applicationId " + appId); + //break .. + case RUNNING: + LOG.info("YARN application has been deployed successfully."); + break; + default: + if (appState != lastAppState) { + LOG.info("Deploying cluster, current state " + appState); + } + lastAppState = appState; + if (System.currentTimeMillis() - startTime > DEPLOY_TIMEOUT_MS) { + throw new RuntimeException(String.format("Deployment took more than %d seconds. " + + "Please check if the requested resources are available in the YARN cluster", DEPLOY_TIMEOUT_MS)); + } + return null; + } + return report; + } + } +} diff --git a/launcher/src/main/resources/log4j.properties b/launcher/src/main/resources/log4j.properties deleted file mode 100644 index 44e3a5ef2..000000000 --- a/launcher/src/main/resources/log4j.properties +++ /dev/null @@ -1,7 +0,0 @@ -#控制台输出: -log4j.rootLogger = INFO,consoleAppender -log4j.appender.consoleAppender = org.apache.log4j.ConsoleAppender -log4j.appender.console.Target = System.out -log4j.appender.consoleAppender.layout = org.apache.log4j.PatternLayout -log4j.appender.consoleAppender.layout.ConversionPattern =%d %-5p %m %n -log4j.appender.consoleAppender.ImmediateFlush = true \ No newline at end of file diff --git a/launcher/src/main/test/java/com/dtstack/flink/sql/launcher/LauncherMainTest.java b/launcher/src/main/test/java/com/dtstack/flink/sql/launcher/LauncherMainTest.java deleted file mode 100644 index 6bcb87e0f..000000000 --- a/launcher/src/main/test/java/com/dtstack/flink/sql/launcher/LauncherMainTest.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.launcher; - - -import org.junit.Test; - -/** - * yarnPer提交任务时指定pluginLoadMode - * Date: 2019/11/6 - * Company: www.dtstack.com - * @author maqi - */ -public class LauncherMainTest { - @Test(expected = Exception.class) - public void testRocSql() throws Exception{ - String[] sql = new String[]{"-mode", "local", "-sql", "/Users/roc/Documents/flink_sql/sql/zy_sql/hbase_side.sql", "-name", "roc", - "-localSqlPluginPath", "/Users/roc/workspace/git_code/flinkStreamSQL/plugins", - "-remoteSqlPluginPath", "/Users/roc/workspace/git_code/flinkStreamSQL/plugins", - "-flinkconf", "/Users/roc/Documents/flink_sql/flinkconf", - "-confProp", "{\"sql.checkpoint.cleanup.mode\":\"false\",\"sql.checkpoint.interval\":10000,\"time.characteristic\":\"EventTime\"}", - "-yarnconf", "/Users/roc/Documents/flink_sql/yarnconf", - "-flinkJarPath", "/Users/roc/Documents/flink_sql/flinkJarPath", "-queue", "c", "-pluginLoadMode", "classpath"}; - System.setProperty("HADOOP_USER_NAME", "admin"); - LauncherMain.main(sql); - } -} diff --git a/launcher/src/main/test/java/com/dtstack/flink/sql/launcher/PluginLoadModeTest.java b/launcher/src/main/test/java/com/dtstack/flink/sql/launcher/PluginLoadModeTest.java index ad3ec3d15..0a153d018 100644 --- a/launcher/src/main/test/java/com/dtstack/flink/sql/launcher/PluginLoadModeTest.java +++ b/launcher/src/main/test/java/com/dtstack/flink/sql/launcher/PluginLoadModeTest.java @@ -48,22 +48,8 @@ public static void testClasspathMode() throws Exception { LauncherMain.main(sql); } - - public static void testRocSql() throws Exception{ - String[] sql = new String[]{"-mode", "local", "-sql", "/Users/roc/Documents/flink_sql/sql/simpleInsert.sql", "-name", "roc", - "-localSqlPluginPath", "/Users/roc/workspace/git_code/flinkStreamSQL/sqlplugins", - "-remoteSqlPluginPath", "/Users/roc/workspace/git_code/flinkStreamSQL/sqlplugins", - "-flinkconf", "/Users/roc/Documents/flink_sql/flinkconf", - "-confProp", "{\"sql.checkpoint.cleanup.mode\":\"false\",\"sql.checkpoint.interval\":10000,\"time.characteristic\":\"EventTime\"}", - "-yarnconf", "/Users/roc/Documents/flink_sql/yarnconf", - "-flinkJarPath", "/Users/roc/Documents/flink_sql/flinkJarPath", "-queue", "c", "-pluginLoadMode", "classpath"}; - System.setProperty("HADOOP_USER_NAME", "admin"); - LauncherMain.main(sql); - } - public static void main(String[] args) throws Exception { - testRocSql(); -// testShipfileMode(); + testShipfileMode(); // testClasspathMode(); } } diff --git a/launcher/src/main/test/java/com/dtstack/flink/sql/launcher/YarnConfLoaderTest.java b/launcher/src/main/test/java/com/dtstack/flink/sql/launcher/YarnConfLoaderTest.java deleted file mode 100644 index ceaf5ec00..000000000 --- a/launcher/src/main/test/java/com/dtstack/flink/sql/launcher/YarnConfLoaderTest.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.dtstack.flink.sql.launcher; - -import org.junit.Test; - -public class YarnConfLoaderTest { - - @Test - public void testGetYarnConf(){ - - - } -} diff --git a/localTest/pom.xml b/localTest/pom.xml deleted file mode 100644 index 52dbbea70..000000000 --- a/localTest/pom.xml +++ /dev/null @@ -1,331 +0,0 @@ - - - - flink.sql - com.dtstack.flink - 1.0-SNAPSHOT - - 4.0.0 - - sql.localTest - pom - - - 1.0-SNAPSHOT - - - - - - org.slf4j - slf4j-api - 1.6.3 - compile - - - - ch.qos.logback - logback-classic - 1.2.0 - compile - - - - junit - junit - 4.12 - test - - - - com.dtstack.flink - sql.core - ${sql.core.version} - - - - com.dtstack.flink - sql.source.kafka-base - 1.0-SNAPSHOT - - - - com.dtstack.flink - sql.source.file - 1.0-SNAPSHOT - - - - - - - - - - - - - - - - - - - - - - com.dtstack.flink - dirtyConsumer.console - 1.0-SNAPSHOT - - - - com.dtstack.flink - dirtyConsumer.mysql - 1.0-SNAPSHOT - - - - com.dtstack.flink - sql.source.kafka11 - 1.0-SNAPSHOT - - - - com.dtstack.flink - sql.kudu - 1.0-SNAPSHOT - - - - com.dtstack.flink - sql.side.all.kudu - 1.0-SNAPSHOT - - - - com.dtstack.flink - sql.http - 1.0-SNAPSHOT - - - - com.dtstack.flink - sql.sink.http - 1.0-SNAPSHOT - - - - com.dtstack.flink - sql.sink.kudu - 1.0-SNAPSHOT - - - - com.dtstack.flink - sql.side.async.kudu - 1.0-SNAPSHOT - - - - - com.dtstack.flink - sql.postgresql - 1.0-SNAPSHOT - - - - com.dtstack.flink - sql.side.all.postgresql - 1.0-SNAPSHOT - - - - com.dtstack.flink - sql.sink.postgresql - 1.0-SNAPSHOT - - - - com.dtstack.flink - sql.side.async.postgresql - 1.0-SNAPSHOT - - - - - com.dtstack.flink - sql.hbase - 1.0-SNAPSHOT - - - - com.dtstack.flink - sql.side.all.hbase - 1.0-SNAPSHOT - - - - com.dtstack.flink - sql.sink.hbase - 1.0-SNAPSHOT - - - - com.dtstack.flink - sql.side.async.hbase - 1.0-SNAPSHOT - - - - - com.dtstack.flink - sql.redis - 1.0-SNAPSHOT - - - - com.dtstack.flink - sql.side.all.redis - 1.0-SNAPSHOT - - - - com.dtstack.flink - sql.sink.redis - 1.0-SNAPSHOT - - - - com.dtstack.flink - sql.side.async.redis - 1.0-SNAPSHOT - - - - com.dtstack.flink - sql.impala - 1.0-SNAPSHOT - - - - com.dtstack.flink - sql.side.all.impala - 1.0-SNAPSHOT - - - - com.dtstack.flink - sql.sink.impala - 1.0-SNAPSHOT - - - - com.dtstack.flink - sql.side.async.impala - 1.0-SNAPSHOT - - - - - com.dtstack.flink - sql.mysql - 1.0-SNAPSHOT - - - - com.dtstack.flink - sql.side.all.mysql - 1.0-SNAPSHOT - - - - com.dtstack.flink - sql.sink.mysql - 1.0-SNAPSHOT - - - - com.dtstack.flink - sql.side.async.mysql - 1.0-SNAPSHOT - - - - com.dtstack.flink - sql.mongo - 1.0-SNAPSHOT - - - - com.dtstack.flink - sql.side.all.mongo - 1.0-SNAPSHOT - - - - com.dtstack.flink - sql.sink.mongo - 1.0-SNAPSHOT - - - - com.dtstack.flink - sql.side.async.mongo - 1.0-SNAPSHOT - - - - com.dtstack.flink - sql.oracle - 1.0-SNAPSHOT - - - - com.dtstack.flink - sql.side.all.oracle - 1.0-SNAPSHOT - - - - com.dtstack.flink - sql.sink.oracle - 1.0-SNAPSHOT - - - - com.dtstack.flink - sql.side.async.oracle - 1.0-SNAPSHOT - - - - com.dtstack.flink - sql.console - 1.0-SNAPSHOT - - - - com.dtstack.flink - console-sink - 1.0-SNAPSHOT - - - - com.alibaba - fastjson - 1.2.76 - compile - - - com.alibaba - fastjson - 1.2.70 - compile - - - - - \ No newline at end of file diff --git a/localTest/src/main/java/com/dtstack/flink/sql/localTest/LocalTest.java b/localTest/src/main/java/com/dtstack/flink/sql/localTest/LocalTest.java deleted file mode 100644 index 7d593c505..000000000 --- a/localTest/src/main/java/com/dtstack/flink/sql/localTest/LocalTest.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.localTest; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.LoggerContext; -import com.alibaba.fastjson.JSONObject; -import com.dtstack.flink.sql.Main; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.TimeZone; - -/** - * @author tiezhu - * @Date 2020/7/8 Wed - * Company dtstack - */ -public class LocalTest { - - private static final Logger LOG = LoggerFactory.getLogger(LocalTest.class); - - public static void main(String[] args) throws Exception { - - setLogLevel("INFO"); - - List propertiesList = new ArrayList<>(); - String sqlPath = "/Users/wtz/dtstack/sql/test/FileDemoOne.sql"; - Map conf = new HashMap<>(); - JSONObject properties = new JSONObject(); - - //其他参数配置 - properties.put("time.characteristic", "eventTime"); - properties.put("timezone", TimeZone.getDefault()); - properties.put("early.trigger", "1"); - - // 任务配置参数 - conf.put("-sql", URLEncoder.encode(readSQL(sqlPath), StandardCharsets.UTF_8.name())); - conf.put("-mode", "local"); - conf.put("-name", "flinkStreamSQLLocalTest"); - conf.put("-confProp", properties.toString()); - conf.put("-pluginLoadMode", "LocalTest"); -// conf.put("-checkResource", "true"); - conf.put("-dirtyProperties", buildDirtyStr()); - - for (Map.Entry keyValue : conf.entrySet()) { - propertiesList.add(keyValue.getKey()); - propertiesList.add(keyValue.getValue().toString()); - } - - Main.main(propertiesList.toArray(new String[0])); - } - - private static String buildDirtyStr() { - JSONObject jsonObject = new JSONObject(); - jsonObject.put("type", "console"); - // 多少条数据打印一次 - jsonObject.put("printLimit", "100"); - jsonObject.put("url", "jdbc:mysql://localhost:3306/tiezhu"); - jsonObject.put("userName", "root"); - jsonObject.put("password", "abc123"); - jsonObject.put("isCreateTable", "false"); - // 多少条数据写入一次 - jsonObject.put("batchSize", "1"); - jsonObject.put("tableName", "dirtyData"); - - return jsonObject.toJSONString(); - - } - - private static String readSQL(String sqlPath) { - try { - byte[] array = Files.readAllBytes(Paths.get(sqlPath)); - return new String(array, StandardCharsets.UTF_8); - } catch (IOException ioe) { - LOG.error("Can not get the job info !!!", ioe); - throw new RuntimeException(ioe); - } - } - - private static void setLogLevel(String level) { - LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory(); - ch.qos.logback.classic.Logger logger = loggerContext.getLogger("root"); - logger.setLevel(Level.toLevel(level)); - } -} diff --git a/localTest/src/test/java/com/dtstack/flink/sql/localTest/TestLocalTest.java b/localTest/src/test/java/com/dtstack/flink/sql/localTest/TestLocalTest.java deleted file mode 100644 index d1612c363..000000000 --- a/localTest/src/test/java/com/dtstack/flink/sql/localTest/TestLocalTest.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.localTest; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -/** - * @author tiezhu - * @Date 2020/7/8 Wed - * Company dtstack - */ -public class TestLocalTest { - - @Test - public void testReadSQL() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { - String result = "this is a test"; - String sqlPath = "/Users/wtz4680/Desktop/ideaProject/flinkStreamSQL/localTest/src/test/resources/test.txt"; - Class testClass = LocalTest.class; - Method method = testClass.getDeclaredMethod("readSQL", String.class); - method.setAccessible(true); - Assert.assertEquals(result, method.invoke(new LocalTest(), sqlPath)); - } -} diff --git a/localTest/src/test/resources/test.txt b/localTest/src/test/resources/test.txt deleted file mode 100644 index a8a940627..000000000 --- a/localTest/src/test/resources/test.txt +++ /dev/null @@ -1 +0,0 @@ -this is a test \ No newline at end of file diff --git a/mongo/mongo-side/mongo-all-side/pom.xml b/mongo/mongo-side/mongo-all-side/pom.xml index 9af432abb..87709ec4e 100644 --- a/mongo/mongo-side/mongo-all-side/pom.xml +++ b/mongo/mongo-side/mongo-all-side/pom.xml @@ -69,14 +69,14 @@ - + - + diff --git a/mongo/mongo-side/mongo-all-side/src/main/java/com/dtstack/flink/sql/side/mongo/MongoAllReqRow.java b/mongo/mongo-side/mongo-all-side/src/main/java/com/dtstack/flink/sql/side/mongo/MongoAllReqRow.java index 8e4292438..4dc7c26b4 100644 --- a/mongo/mongo-side/mongo-all-side/src/main/java/com/dtstack/flink/sql/side/mongo/MongoAllReqRow.java +++ b/mongo/mongo-side/mongo-all-side/src/main/java/com/dtstack/flink/sql/side/mongo/MongoAllReqRow.java @@ -18,18 +18,16 @@ package com.dtstack.flink.sql.side.mongo; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.BaseAllReqRow; +import com.dtstack.flink.sql.side.AllReqRow; import com.dtstack.flink.sql.side.FieldInfo; import com.dtstack.flink.sql.side.JoinInfo; +import com.dtstack.flink.sql.side.SideTableInfo; import com.dtstack.flink.sql.side.mongo.table.MongoSideTableInfo; -import com.dtstack.flink.sql.side.mongo.utils.MongoUtil; -import com.dtstack.flink.sql.util.RowDataComplete; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; import com.mongodb.BasicDBObject; import com.mongodb.MongoClient; -import com.mongodb.MongoClientURI; +import com.mongodb.MongoClientOptions; +import com.mongodb.MongoCredential; +import com.mongodb.ServerAddress; import com.mongodb.client.FindIterable; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoCursor; @@ -38,14 +36,18 @@ import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.table.dataformat.BaseRow; -import org.apache.flink.table.dataformat.GenericRow; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import org.apache.flink.table.typeutils.TimeIndicatorTypeInfo; +import org.apache.flink.types.Row; import org.apache.flink.util.Collector; import org.bson.Document; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.sql.SQLException; +import java.sql.Timestamp; +import java.util.ArrayList; import java.util.Calendar; import java.util.List; import java.util.Map; @@ -57,7 +59,7 @@ * * @author xuqianjin */ -public class MongoAllReqRow extends BaseAllReqRow { +public class MongoAllReqRow extends AllReqRow { private static final long serialVersionUID = -675332795591842778L; @@ -73,10 +75,36 @@ public class MongoAllReqRow extends BaseAllReqRow { private AtomicReference>>> cacheRef = new AtomicReference<>(); - public MongoAllReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { + public MongoAllReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, SideTableInfo sideTableInfo) { super(new MongoAllSideInfo(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo)); } + @Override + public Row fillData(Row input, Object sideInput) { + Map cacheInfo = (Map) sideInput; + Row row = new Row(sideInfo.getOutFieldInfoList().size()); + for (Map.Entry entry : sideInfo.getInFieldIndex().entrySet()) { + Object obj = input.getField(entry.getValue()); + boolean isTimeIndicatorTypeInfo = TimeIndicatorTypeInfo.class.isAssignableFrom(sideInfo.getRowTypeInfo().getTypeAt(entry.getValue()).getClass()); + + //Type information for indicating event or processing time. However, it behaves like a regular SQL timestamp but is serialized as Long. + if (obj instanceof Timestamp && isTimeIndicatorTypeInfo) { + obj = ((Timestamp) obj).getTime(); + } + row.setField(entry.getKey(), obj); + } + + for (Map.Entry entry : sideInfo.getSideFieldNameIndex().entrySet()) { + if (cacheInfo == null) { + row.setField(entry.getKey(), null); + } else { + row.setField(entry.getKey(), cacheInfo.get(entry.getValue())); + } + } + + return row; + } + @Override protected void initCache() throws SQLException { Map>> newCache = Maps.newConcurrentMap(); @@ -99,18 +127,14 @@ protected void reloadCache() { } @Override - public void flatMap(BaseRow input, Collector out) throws Exception { - GenericRow genericRow = (GenericRow) input; + public void flatMap(Row value, Collector out) throws Exception { List inputParams = Lists.newArrayList(); for (Integer conValIndex : sideInfo.getEqualValIndex()) { - Object equalObj = genericRow.getField(conValIndex); + Object equalObj = value.getField(conValIndex); if (equalObj == null) { - if (sideInfo.getJoinType() == JoinType.LEFT) { - BaseRow data = fillData(input, null); - RowDataComplete.collectBaseRow(out, data); - } - return; + out.collect(null); } + inputParams.add(equalObj); } @@ -118,8 +142,8 @@ public void flatMap(BaseRow input, Collector out) throws Exception { List> cacheList = cacheRef.get().get(key); if (CollectionUtils.isEmpty(cacheList)) { if (sideInfo.getJoinType() == JoinType.LEFT) { - BaseRow row = fillData(input, null); - RowDataComplete.collectBaseRow(out, row); + Row row = fillData(value, null); + out.collect(row); } else { return; } @@ -128,8 +152,7 @@ public void flatMap(BaseRow input, Collector out) throws Exception { } for (Map one : cacheList) { - BaseRow row = fillData(input, one); - RowDataComplete.collectBaseRow(out, row); + out.collect(fillData(value, one)); } } @@ -151,14 +174,34 @@ private String buildKey(Map val, List equalFieldList) { return sb.toString(); } - private MongoCollection getConn(String host, String userName, String password, String database, String tableName) { - + private MongoCollection getConn(String address, String userName, String password, String database, String tableName) { MongoCollection dbCollection; - mongoClient = new MongoClient(new MongoClientURI(getConnectionUrl(host, userName, password))); - db = mongoClient.getDatabase(database); - dbCollection = db.getCollection(tableName, Document.class); - return dbCollection; - + try { + MongoCredential credential; + String[] servers = address.split(","); + String host; + Integer port; + String[] hostAndPort; + List lists = new ArrayList<>(); + for (String server : servers) { + hostAndPort = server.split(":"); + host = hostAndPort[0]; + port = Integer.parseInt(hostAndPort[1]); + lists.add(new ServerAddress(host, port)); + } + if (!StringUtils.isEmpty(userName) || !StringUtils.isEmpty(password)) { + credential = MongoCredential.createCredential(userName, database, password.toCharArray()); + // To connect to mongodb server + mongoClient = new MongoClient(lists, credential, new MongoClientOptions.Builder().build()); + } else { + mongoClient = new MongoClient(lists); + } + db = mongoClient.getDatabase(database); + dbCollection = db.getCollection(tableName, Document.class); + return dbCollection; + } catch (Exception e) { + throw new RuntimeException("[connMongoDB]:" + e.getMessage()); + } } private void loadData(Map>> tmpCache) throws SQLException { @@ -179,35 +222,20 @@ private void loadData(Map>> tmpCache) throws SQ try { String connInfo = "url:" + tableInfo.getAddress() + ";userName:" + tableInfo.getUserName() + ",pwd:" + tableInfo.getPassword(); LOG.warn("get conn fail, wait for 5 sec and try again, connInfo:" + connInfo); - Thread.sleep(LOAD_DATA_ERROR_SLEEP_TIME); + Thread.sleep(5 * 1000); } catch (InterruptedException e1) { - LOG.error("", e1); + e1.printStackTrace(); } } } //load data from table - String[] sideFieldNames = StringUtils.split(sideInfo.getSideSelectFields(), ","); + String[] sideFieldNames = sideInfo.getSideSelectFields().split(","); BasicDBObject basicDBObject = new BasicDBObject(); for (String selectField : sideFieldNames) { basicDBObject.append(selectField, 1); } - BasicDBObject filterObject = new BasicDBObject(); - try { - // 填充谓词 - sideInfo.getSideTableInfo().getPredicateInfoes().stream().map(info -> { - BasicDBObject filterCondition = MongoUtil.buildFilterObject(info); - if (null != filterCondition) { - filterObject.append(info.getFieldName(), filterCondition); - } - return info; - }).count(); - } catch (Exception e) { - LOG.info("add predicate infoes error ", e); - } - - - FindIterable findIterable = dbCollection.find(filterObject).projection(basicDBObject).limit(FETCH_SIZE); + FindIterable findIterable = dbCollection.find().projection(basicDBObject).limit(FETCH_SIZE); MongoCursor mongoCursor = findIterable.iterator(); while (mongoCursor.hasNext()) { Document doc = mongoCursor.next(); @@ -222,19 +250,13 @@ private void loadData(Map>> tmpCache) throws SQ } catch (Exception e) { LOG.error("", e); } finally { - if (mongoClient != null) { - mongoClient.close(); + try { + if (mongoClient != null) { + mongoClient.close(); + } + } catch (Exception e) { + throw new RuntimeException("[closeMongoDB]:" + e.getMessage()); } } } - private String getConnectionUrl(String address, String userName, String password){ - if(address.startsWith("mongodb://") || address.startsWith("mongodb+srv://")){ - return address; - } - if (StringUtils.isNotBlank(userName) && StringUtils.isNotBlank(password)) { - return String.format("mongodb://%s:%s@%s", userName, password, address); - } - return String.format("mongodb://%s", address); - } - } diff --git a/mongo/mongo-side/mongo-all-side/src/main/java/com/dtstack/flink/sql/side/mongo/MongoAllSideInfo.java b/mongo/mongo-side/mongo-all-side/src/main/java/com/dtstack/flink/sql/side/mongo/MongoAllSideInfo.java index 4a33f1a69..6191114b5 100644 --- a/mongo/mongo-side/mongo-all-side/src/main/java/com/dtstack/flink/sql/side/mongo/MongoAllSideInfo.java +++ b/mongo/mongo-side/mongo-all-side/src/main/java/com/dtstack/flink/sql/side/mongo/MongoAllSideInfo.java @@ -20,8 +20,9 @@ import com.dtstack.flink.sql.side.FieldInfo; import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.BaseSideInfo; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; +import com.dtstack.flink.sql.side.SideInfo; +import com.dtstack.flink.sql.side.SideTableInfo; +import com.dtstack.flink.sql.side.mongo.table.MongoSideTableInfo; import com.dtstack.flink.sql.util.ParseUtils; import org.apache.calcite.sql.SqlNode; import org.apache.commons.collections.CollectionUtils; @@ -36,16 +37,21 @@ * * @author xuqianjin */ -public class MongoAllSideInfo extends BaseSideInfo { +public class MongoAllSideInfo extends SideInfo{ private static final long serialVersionUID = -1696860430075523841L; - public MongoAllSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { + public MongoAllSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, SideTableInfo sideTableInfo) { super(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); } @Override - public void buildEqualInfo(JoinInfo joinInfo, AbstractSideTableInfo sideTableInfo) { + public void buildEqualInfo(JoinInfo joinInfo, SideTableInfo sideTableInfo) { + MongoSideTableInfo MongoSideTableInfo = (MongoSideTableInfo) sideTableInfo; + + sqlCondition = "select ${selectField} from ${tableName} "; + sqlCondition = sqlCondition.replace("${tableName}", MongoSideTableInfo.getTableName()).replace("${selectField}", sideSelectFields); + System.out.println("---------side_exe_sql-----\n" + sqlCondition); } @Override diff --git a/mongo/mongo-side/mongo-all-side/src/test/java/com/dtstack/flink/sql/side/mongo/MongoAllReqRowTest.java b/mongo/mongo-side/mongo-all-side/src/test/java/com/dtstack/flink/sql/side/mongo/MongoAllReqRowTest.java deleted file mode 100644 index 0070bbdc9..000000000 --- a/mongo/mongo-side/mongo-all-side/src/test/java/com/dtstack/flink/sql/side/mongo/MongoAllReqRowTest.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.mongo; - -import com.dtstack.flink.sql.side.BaseAllReqRow; -import com.dtstack.flink.sql.side.BaseSideInfo; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.PredicateInfo; -import com.dtstack.flink.sql.side.mongo.table.MongoSideTableInfo; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import org.apache.calcite.sql.JoinType; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.table.dataformat.BaseRow; -import org.apache.flink.table.dataformat.GenericRow; -import org.apache.flink.types.Row; -import org.apache.flink.util.Collector; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import org.powermock.reflect.Whitebox; - -import java.sql.Timestamp; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicReference; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.powermock.api.support.membermodification.MemberMatcher.constructor; -import static org.powermock.api.support.membermodification.MemberModifier.suppress; - -/** - * @author: chuixue - * @create: 2020-07-27 10:03 - * @description: - **/ -@RunWith(PowerMockRunner.class) -@PrepareForTest({BaseAllReqRow.class, - MongoAllSideInfo.class}) -public class MongoAllReqRowTest { - - private MongoAllReqRow mongoAllReqRow; - private RowTypeInfo rowTypeInfo; - private JoinInfo joinInfo; - private List outFieldInfoList = new ArrayList<>(); - private MongoSideTableInfo sideTableInfo; - private BaseSideInfo sideInfo; - AtomicReference>>> cacheRef = new AtomicReference<>(); - Map>> map = Maps.newHashMap(); - - @Before - public void setUp() { - rowTypeInfo = PowerMockito.mock(RowTypeInfo.class); - joinInfo = PowerMockito.mock(JoinInfo.class); - sideTableInfo = PowerMockito.mock(MongoSideTableInfo.class); - sideInfo = PowerMockito.mock(MongoAllSideInfo.class); - - cacheRef.set(map); - - suppress(constructor(BaseAllReqRow.class)); - suppress(constructor(MongoAllSideInfo.class)); - mongoAllReqRow = new MongoAllReqRow(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); - Whitebox.setInternalState(mongoAllReqRow, "sideInfo", sideInfo); - Whitebox.setInternalState(mongoAllReqRow, "cacheRef", cacheRef); - } - - @Test - public void testReloadCache() throws Exception { - List predicateInfos = Lists.newArrayList(); - when(sideInfo.getSideTableInfo()).thenReturn(sideTableInfo); - when(sideInfo.getSideSelectFields()).thenReturn("_id,channel,name"); - when(sideTableInfo.getPredicateInfoes()).thenReturn(predicateInfos); - when(sideTableInfo.getAddress()).thenReturn("10.10.10.10:27017"); - when(sideTableInfo.getUserName()).thenReturn("username"); - when(sideTableInfo.getPassword()).thenReturn("getPassword"); - when(sideTableInfo.getDatabase()).thenReturn("dtstack"); - when(sideTableInfo.getTableName()).thenReturn("userInfo"); - - mongoAllReqRow.reloadCache(); - } - - @Test - public void testFlatMap() throws Exception { - List equalFieldList = Lists.newArrayList(); - equalFieldList.add("rowkey"); - List equalValIndex = Lists.newArrayList(); - equalValIndex.add(0); - GenericRow row = new GenericRow(3); - row.setField(0, 1); - row.setField(1, "bbbbbb"); - row.setField(2, "2020-07-14 01:27:43.969"); - Collector out = mock(Collector.class); - - List outFieldInfoList = Lists.newArrayList(); - FieldInfo fieldInfo = new FieldInfo(); - fieldInfo.setTable("m"); - fieldInfo.setFieldName("id"); - fieldInfo.setTypeInformation(TypeInformation.of(Integer.class)); - outFieldInfoList.add(fieldInfo); - outFieldInfoList.add(fieldInfo); - outFieldInfoList.add(fieldInfo); - outFieldInfoList.add(fieldInfo); - - Map inFieldIndex = Maps.newHashMap(); - inFieldIndex.put(0, 0); - inFieldIndex.put(1, 1); - - - Map sideFieldIndex = Maps.newHashMap(); - sideFieldIndex.put(2, 0); - sideFieldIndex.put(3, 1); - - Map sideFieldNameIndex = Maps.newHashMap(); - sideFieldNameIndex.put(2, "rowkey"); - sideFieldNameIndex.put(3, "channel"); - - RowTypeInfo rowTypeInfo = new RowTypeInfo(new TypeInformation[]{TypeInformation.of(Integer.class), TypeInformation.of(String.class), TypeInformation.of(Timestamp.class)}, new String[]{"id", "bb", "PROCTIME"}); - - when(sideInfo.getEqualValIndex()).thenReturn(equalValIndex); - when(sideInfo.getJoinType()).thenReturn(JoinType.LEFT); - when(sideInfo.getOutFieldInfoList()).thenReturn(outFieldInfoList); - when(sideInfo.getInFieldIndex()).thenReturn(inFieldIndex); - when(sideInfo.getRowTypeInfo()).thenReturn(rowTypeInfo); - when(sideInfo.getSideFieldNameIndex()).thenReturn(sideFieldNameIndex); - mongoAllReqRow.flatMap(row, out); - } -} diff --git a/mongo/mongo-side/mongo-all-side/src/test/java/com/dtstack/flink/sql/side/mongo/MongoAllSideInfoTest.java b/mongo/mongo-side/mongo-all-side/src/test/java/com/dtstack/flink/sql/side/mongo/MongoAllSideInfoTest.java deleted file mode 100644 index 4eaeeb100..000000000 --- a/mongo/mongo-side/mongo-all-side/src/test/java/com/dtstack/flink/sql/side/mongo/MongoAllSideInfoTest.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.mongo; - -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.BaseSideInfo; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.util.ParseUtils; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import org.apache.calcite.sql.SqlBasicCall; -import org.apache.calcite.sql.SqlNode; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.InjectMocks; -import org.mockito.MockitoAnnotations; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import org.powermock.reflect.Whitebox; - -import java.util.List; -import java.util.Map; - -import static org.mockito.Mockito.mock; -import static org.powermock.api.mockito.PowerMockito.mockStatic; -import static org.powermock.api.support.membermodification.MemberMatcher.constructor; -import static org.powermock.api.support.membermodification.MemberMatcher.method; -import static org.powermock.api.support.membermodification.MemberModifier.suppress; -import static org.mockito.Mockito.when; - -/** - * @author: chuixue - * @create: 2020-07-27 11:08 - * @description: - **/ -@RunWith(PowerMockRunner.class) -@PrepareForTest({MongoAllSideInfo.class - , ParseUtils.class - , JoinInfo.class - , SqlBasicCall.class - , BaseSideInfo.class}) -public class MongoAllSideInfoTest { - - private MongoAllSideInfo mongoAllSideInfo; - private JoinInfo joinInfo; - private AbstractSideTableInfo sideTableInfo; - - @Before - public void setUp() { - joinInfo = mock(JoinInfo.class); - sideTableInfo = mock(AbstractSideTableInfo.class); - - List outFieldInfoList = Lists.newArrayList(); - FieldInfo fieldInfo = new FieldInfo(); - fieldInfo.setTable("m"); - fieldInfo.setFieldName("_id"); - fieldInfo.setTypeInformation(TypeInformation.of(String.class)); - outFieldInfoList.add(fieldInfo); - - FieldInfo fieldInfo2 = new FieldInfo(); - fieldInfo2.setTable("s"); - fieldInfo2.setFieldName("name"); - fieldInfo2.setTypeInformation(TypeInformation.of(String.class)); - outFieldInfoList.add(fieldInfo2); - - Map sideFieldIndex = Maps.newHashMap(); - Map sideFieldNameIndex = Maps.newHashMap(); - RowTypeInfo rowTypeInfo = new RowTypeInfo(new TypeInformation[]{TypeInformation.of(Integer.class), TypeInformation.of(String.class), TypeInformation.of(Integer.class)}, new String[]{"id", "bb", "PROCTIME"}); - Map inFieldIndex = Maps.newHashMap(); - List equalFieldList = Lists.newArrayList(); - equalFieldList.add("_id"); - - suppress(constructor(BaseSideInfo.class)); - mongoAllSideInfo = new MongoAllSideInfo(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); - - Whitebox.setInternalState(mongoAllSideInfo, "outFieldInfoList", outFieldInfoList); - Whitebox.setInternalState(mongoAllSideInfo, "sideFieldIndex", sideFieldIndex); - Whitebox.setInternalState(mongoAllSideInfo, "sideFieldNameIndex", sideFieldNameIndex); - Whitebox.setInternalState(mongoAllSideInfo, "rowTypeInfo", rowTypeInfo); - Whitebox.setInternalState(mongoAllSideInfo, "inFieldIndex", inFieldIndex); - Whitebox.setInternalState(mongoAllSideInfo, "equalFieldList", equalFieldList); - } - - @Test - public void testParseSelectFields() { - mockStatic(ParseUtils.class); - - SqlBasicCall conditionNode = mock(SqlBasicCall.class); - - when(joinInfo.getSideTableName()).thenReturn("s"); - when(joinInfo.getNonSideTable()).thenReturn("m"); - when(joinInfo.getCondition()).thenReturn(conditionNode); - suppress(method(ParseUtils.class, "parseAnd", SqlNode.class, List.class)); - mongoAllSideInfo.parseSelectFields(joinInfo); - } - -} diff --git a/mongo/mongo-side/mongo-async-side/pom.xml b/mongo/mongo-side/mongo-async-side/pom.xml index 84e58d7e0..e800be51c 100644 --- a/mongo/mongo-side/mongo-async-side/pom.xml +++ b/mongo/mongo-side/mongo-async-side/pom.xml @@ -85,14 +85,14 @@ - + - + diff --git a/mongo/mongo-side/mongo-async-side/src/main/java/com/dtstack/flink/sql/side/mongo/MongoAsyncReqRow.java b/mongo/mongo-side/mongo-async-side/src/main/java/com/dtstack/flink/sql/side/mongo/MongoAsyncReqRow.java index 9b8376cbc..150053246 100644 --- a/mongo/mongo-side/mongo-async-side/src/main/java/com/dtstack/flink/sql/side/mongo/MongoAsyncReqRow.java +++ b/mongo/mongo-side/mongo-async-side/src/main/java/com/dtstack/flink/sql/side/mongo/MongoAsyncReqRow.java @@ -20,34 +20,38 @@ package com.dtstack.flink.sql.side.mongo; import com.dtstack.flink.sql.enums.ECacheContentType; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.BaseAsyncReqRow; +import com.dtstack.flink.sql.side.AsyncReqRow; import com.dtstack.flink.sql.side.FieldInfo; import com.dtstack.flink.sql.side.JoinInfo; +import com.dtstack.flink.sql.side.SideTableInfo; import com.dtstack.flink.sql.side.cache.CacheObj; import com.dtstack.flink.sql.side.mongo.table.MongoSideTableInfo; -import com.dtstack.flink.sql.side.mongo.utils.MongoUtil; -import com.dtstack.flink.sql.util.RowDataComplete; -import com.google.common.collect.Lists; import com.mongodb.BasicDBObject; import com.mongodb.Block; -import com.mongodb.ConnectionString; -import com.mongodb.MongoClientSettings; +import com.mongodb.MongoCredential; +import com.mongodb.ServerAddress; import com.mongodb.async.SingleResultCallback; import com.mongodb.async.client.MongoClient; +import com.mongodb.async.client.MongoClientSettings; import com.mongodb.async.client.MongoClients; import com.mongodb.async.client.MongoCollection; import com.mongodb.async.client.MongoDatabase; +import com.mongodb.connection.ClusterSettings; +import com.mongodb.connection.ConnectionPoolSettings; import org.apache.commons.lang3.StringUtils; import org.apache.flink.api.java.typeutils.RowTypeInfo; +import com.google.common.collect.Lists; import org.apache.flink.configuration.Configuration; import org.apache.flink.streaming.api.functions.async.ResultFuture; -import org.apache.flink.table.dataformat.BaseRow; -import org.apache.flink.table.dataformat.GenericRow; +import org.apache.flink.table.typeutils.TimeIndicatorTypeInfo; +import org.apache.flink.types.Row; import org.bson.Document; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; @@ -59,71 +63,110 @@ * * @author xuqianjin */ -public class MongoAsyncReqRow extends BaseAsyncReqRow { +public class MongoAsyncReqRow extends AsyncReqRow { private static final long serialVersionUID = -1183158242862673706L; private static final Logger LOG = LoggerFactory.getLogger(MongoAsyncReqRow.class); + private final static int DEFAULT_MAX_DB_CONN_POOL_SIZE = 20; + private transient MongoClient mongoClient; private MongoDatabase db; - private MongoSideTableInfo mongoSideTableInfo; + private MongoSideTableInfo MongoSideTableInfo; - public MongoAsyncReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { + public MongoAsyncReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, SideTableInfo sideTableInfo) { super(new MongoAsyncSideInfo(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo)); } @Override public void open(Configuration parameters) throws Exception { super.open(parameters); - mongoSideTableInfo = (MongoSideTableInfo) sideInfo.getSideTableInfo(); - connMongoDb(); + MongoSideTableInfo = (MongoSideTableInfo) sideInfo.getSideTableInfo(); + connMongoDB(); } - public void connMongoDb() throws Exception { - ConnectionString connectionString = new ConnectionString(getConnectionUrl(mongoSideTableInfo.getAddress(), - mongoSideTableInfo.getUserName(), mongoSideTableInfo.getPassword())); - MongoClientSettings settings = MongoClientSettings.builder() - .applyConnectionString(connectionString) + public void connMongoDB() throws Exception { + MongoCredential mongoCredential; + String[] servers = MongoSideTableInfo.getAddress().split(","); + String host; + Integer port; + String[] hostAndPort; + List lists = new ArrayList<>(); + for (String server : servers) { + hostAndPort = server.split(":"); + host = hostAndPort[0]; + port = Integer.parseInt(hostAndPort[1]); + lists.add(new ServerAddress(host, port)); + } + ClusterSettings clusterSettings = ClusterSettings.builder().hosts(lists).build(); + ConnectionPoolSettings connectionPoolSettings = ConnectionPoolSettings.builder() + .maxSize(DEFAULT_MAX_DB_CONN_POOL_SIZE) .build(); - mongoClient = MongoClients.create(settings); - db = mongoClient.getDatabase(mongoSideTableInfo.getDatabase()); + if (!StringUtils.isEmpty(MongoSideTableInfo.getUserName()) || !StringUtils.isEmpty(MongoSideTableInfo.getPassword())) { + mongoCredential = MongoCredential.createCredential(MongoSideTableInfo.getUserName(), MongoSideTableInfo.getDatabase(), + MongoSideTableInfo.getPassword().toCharArray()); + MongoClientSettings settings = MongoClientSettings.builder().credential(mongoCredential) + .clusterSettings(clusterSettings) + .connectionPoolSettings(connectionPoolSettings) + .build(); + mongoClient = MongoClients.create(settings); + } else { + MongoClientSettings settings = MongoClientSettings.builder().clusterSettings(clusterSettings) + .connectionPoolSettings(connectionPoolSettings) + .build(); + mongoClient = MongoClients.create(settings); + } + db = mongoClient.getDatabase(MongoSideTableInfo.getDatabase()); } @Override - public void handleAsyncInvoke(Map inputParams, BaseRow input, ResultFuture resultFuture) throws Exception { - GenericRow genericRow = (GenericRow) input; - GenericRow inputCopy = GenericRow.copyReference(genericRow); - BasicDBObject basicDbObject = new BasicDBObject(); - try { - basicDbObject.putAll(inputParams); - // 填充谓词 - sideInfo.getSideTableInfo().getPredicateInfoes().stream().map(info -> { - BasicDBObject filterCondition = MongoUtil.buildFilterObject(info); - if (null != filterCondition) { - basicDbObject.append(info.getFieldName(), filterCondition); + public void asyncInvoke(Row input, ResultFuture resultFuture) throws Exception { + + BasicDBObject basicDBObject = new BasicDBObject(); + for (int i = 0; i < sideInfo.getEqualFieldList().size(); i++) { + Integer conValIndex = sideInfo.getEqualValIndex().get(i); + Object equalObj = input.getField(conValIndex); + if (equalObj == null) { + resultFuture.complete(null); + return; + } + basicDBObject.put(sideInfo.getEqualFieldList().get(i), equalObj); + } + String key = buildCacheKey(basicDBObject.values()); + if (openCache()) { + CacheObj val = getFromCache(key); + if (val != null) { + + if (ECacheContentType.MissVal == val.getType()) { + dealMissKey(input, resultFuture); + return; + } else if (ECacheContentType.MultiLine == val.getType()) { + List rowList = Lists.newArrayList(); + for (Object jsonArray : (List) val.getContent()) { + Row row = fillData(input, jsonArray); + rowList.add(row); + } + resultFuture.complete(rowList); + } else { + throw new RuntimeException("not support cache obj type " + val.getType()); } - return info; - }).count(); - } catch (Exception e) { - LOG.info("add predicate infoes error ", e); + return; + } } - - String key = buildCacheKey(inputParams); - AtomicInteger atomicInteger = new AtomicInteger(0); - MongoCollection dbCollection = db.getCollection(mongoSideTableInfo.getTableName(), Document.class); + MongoCollection dbCollection = db.getCollection(MongoSideTableInfo.getTableName(), Document.class); List cacheContent = Lists.newArrayList(); Block printDocumentBlock = new Block() { @Override public void apply(final Document document) { atomicInteger.incrementAndGet(); - BaseRow row = fillData(inputCopy, document); + Row row = fillData(input, document); if (openCache()) { cacheContent.add(document); } - RowDataComplete.completeBaseRow(resultFuture, row); + resultFuture.complete(Collections.singleton(row)); } }; SingleResultCallback callbackWhenFinished = new SingleResultCallback() { @@ -131,7 +174,7 @@ public void apply(final Document document) { public void onResult(final Void result, final Throwable t) { if (atomicInteger.get() <= 0) { LOG.warn("Cannot retrieve the data from the database"); - resultFuture.complete(Collections.EMPTY_LIST); + resultFuture.complete(null); } else { if (openCache()) { putCache(key, CacheObj.buildCacheObj(ECacheContentType.MultiLine, cacheContent)); @@ -139,29 +182,21 @@ public void onResult(final Void result, final Throwable t) { } } }; - dbCollection.find(basicDbObject).forEach(printDocumentBlock, callbackWhenFinished); - } - - @Override - public String buildCacheKey(Map inputParams) { - StringBuilder sb = new StringBuilder(); - for (Object ele : inputParams.values()) { - sb.append(ele.toString()) - .append("_"); - } - - return sb.toString(); + dbCollection.find(basicDBObject).forEach(printDocumentBlock, callbackWhenFinished); } @Override - public BaseRow fillData(BaseRow input, Object line) { - GenericRow genericRow = (GenericRow) input; + public Row fillData(Row input, Object line) { Document doc = (Document) line; - GenericRow row = new GenericRow(sideInfo.getOutFieldInfoList().size()); - row.setHeader(genericRow.getHeader()); + Row row = new Row(sideInfo.getOutFieldInfoList().size()); for (Map.Entry entry : sideInfo.getInFieldIndex().entrySet()) { - Object obj = genericRow.getField(entry.getValue()); - obj = convertTimeIndictorTypeInfo(entry.getValue(), obj); + Object obj = input.getField(entry.getValue()); + boolean isTimeIndicatorTypeInfo = TimeIndicatorTypeInfo.class.isAssignableFrom(sideInfo.getRowTypeInfo().getTypeAt(entry.getValue()).getClass()); + + if (obj instanceof Timestamp && isTimeIndicatorTypeInfo) { + obj = ((Timestamp) obj).getTime(); + } + row.setField(entry.getKey(), obj); } @@ -188,14 +223,14 @@ public void close() throws Exception { } } - private String getConnectionUrl(String address, String userName, String password){ - if(address.startsWith("mongodb://") || address.startsWith("mongodb+srv://")){ - return address; - } - if (StringUtils.isNotBlank(userName) && StringUtils.isNotBlank(password)) { - return String.format("mongodb://%s:%s@%s", userName, password, address); + public String buildCacheKey(Collection collection) { + StringBuilder sb = new StringBuilder(); + for (Object ele : collection) { + sb.append(ele.toString()) + .append("_"); } - return String.format("mongodb://%s", address); + + return sb.toString(); } } diff --git a/mongo/mongo-side/mongo-async-side/src/main/java/com/dtstack/flink/sql/side/mongo/MongoAsyncSideInfo.java b/mongo/mongo-side/mongo-async-side/src/main/java/com/dtstack/flink/sql/side/mongo/MongoAsyncSideInfo.java index 1ceea3e30..365026972 100644 --- a/mongo/mongo-side/mongo-async-side/src/main/java/com/dtstack/flink/sql/side/mongo/MongoAsyncSideInfo.java +++ b/mongo/mongo-side/mongo-async-side/src/main/java/com/dtstack/flink/sql/side/mongo/MongoAsyncSideInfo.java @@ -20,15 +20,16 @@ import com.dtstack.flink.sql.side.FieldInfo; import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.BaseSideInfo; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; +import com.dtstack.flink.sql.side.SideInfo; +import com.dtstack.flink.sql.side.SideTableInfo; +import com.dtstack.flink.sql.side.mongo.table.MongoSideTableInfo; import com.dtstack.flink.sql.util.ParseUtils; -import com.google.common.collect.Lists; import org.apache.calcite.sql.SqlBasicCall; import org.apache.calcite.sql.SqlIdentifier; import org.apache.calcite.sql.SqlKind; import org.apache.calcite.sql.SqlNode; import org.apache.flink.api.java.typeutils.RowTypeInfo; +import com.google.common.collect.Lists; import java.util.List; @@ -38,16 +39,18 @@ * * @author xuqianjin */ -public class MongoAsyncSideInfo extends BaseSideInfo { +public class MongoAsyncSideInfo extends SideInfo { private static final long serialVersionUID = -3694857194254465989L; - public MongoAsyncSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { + public MongoAsyncSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, SideTableInfo sideTableInfo) { super(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); } @Override - public void buildEqualInfo(JoinInfo joinInfo, AbstractSideTableInfo sideTableInfo) { + public void buildEqualInfo(JoinInfo joinInfo, SideTableInfo sideTableInfo) { + MongoSideTableInfo MongoSideTableInfo = (MongoSideTableInfo) sideTableInfo; + String sideTableName = joinInfo.getSideTableName(); SqlNode conditionNode = joinInfo.getCondition(); @@ -58,6 +61,72 @@ public void buildEqualInfo(JoinInfo joinInfo, AbstractSideTableInfo sideTableInf for(SqlNode sqlNode : sqlNodeList){ dealOneEqualCon(sqlNode, sideTableName); } + + sqlCondition = "select ${selectField} from ${tableName} where "; + for(int i=0; i outFieldInfoList = new ArrayList<>(); - private MongoSideTableInfo sideTableInfo; - private BaseSideInfo sideInfo; - private MongoClient mongoClient; - private MongoDatabase db; - @Captor - private ArgumentCaptor> cb; - @Captor - private ArgumentCaptor> eb; - - @Before - public void setUp() { - rowTypeInfo = mock(RowTypeInfo.class); - joinInfo = mock(JoinInfo.class); - sideTableInfo = mock(MongoSideTableInfo.class); - sideInfo = mock(MongoAsyncSideInfo.class); - mongoClient = mock(MongoClient.class); - db = mock(MongoDatabase.class); - - suppress(constructor(MongoAsyncSideInfo.class)); - suppress(constructor(BaseAllReqRow.class)); - - mongoAsyncReqRow = new MongoAsyncReqRow(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); - - Whitebox.setInternalState(mongoAsyncReqRow, "sideInfo", sideInfo); - Whitebox.setInternalState(mongoAsyncReqRow, "mongoSideTableInfo", sideTableInfo); - Whitebox.setInternalState(mongoAsyncReqRow, "mongoClient", mongoClient); - Whitebox.setInternalState(mongoAsyncReqRow, "db", db); - } - - @Test - public void testOpen() throws Exception { - suppress(BaseAsyncReqRow.class.getMethod("open", Configuration.class)); - when(sideInfo.getSideTableInfo()).thenReturn(sideTableInfo); - when(sideTableInfo.getAddress()).thenReturn("localhost"); - when(sideTableInfo.getUserName()).thenReturn("username"); - when(sideTableInfo.getPassword()).thenReturn("password"); - when(sideTableInfo.getDatabase()).thenReturn("getDatabase"); - mongoAsyncReqRow.open(new Configuration()); - } - - @Test - public void testClose() throws Exception { - suppress(BaseAsyncReqRow.class.getMethod("close")); - mongoAsyncReqRow.close(); - } - - @Test - public void testBuildCacheKey() { - Map inputParams = Maps.newHashMap(); - inputParams.put("_id", 1); - mongoAsyncReqRow.buildCacheKey(inputParams); - } - - @Test - public void testFillData() { - GenericRow row = new GenericRow(3); - row.setField(0, 1); - row.setField(1, "bbbbbb"); - row.setField(2, "2020-07-14 01:27:43.969"); - - List outFieldInfoList = Lists.newArrayList(); - FieldInfo fieldInfo = new FieldInfo(); - fieldInfo.setTable("m"); - fieldInfo.setFieldName("id"); - FieldInfo fieldInfo2 = new FieldInfo(); - fieldInfo2.setTable("s"); - fieldInfo2.setFieldName("_id"); - outFieldInfoList.add(fieldInfo); - outFieldInfoList.add(fieldInfo2); - outFieldInfoList.add(fieldInfo); - outFieldInfoList.add(fieldInfo2); - - Map inFieldIndex = Maps.newHashMap(); - inFieldIndex.put(0, 0); - inFieldIndex.put(1, 1); - - Map sideFieldIndex = Maps.newHashMap(); - sideFieldIndex.put(2, 0); - sideFieldIndex.put(3, 1); - - RowTypeInfo rowTypeInfo = new RowTypeInfo(new TypeInformation[]{TypeInformation.of(Integer.class), TypeInformation.of(TimeIndicatorTypeInfo.class)}, new String[]{"id", "PROCTIME"}); - - when(sideInfo.getOutFieldInfoList()).thenReturn(outFieldInfoList); - when(sideInfo.getInFieldIndex()).thenReturn(inFieldIndex); - when(sideInfo.getRowTypeInfo()).thenReturn(rowTypeInfo); - when(sideInfo.getSideFieldIndex()).thenReturn(sideFieldIndex); - - mongoAsyncReqRow.fillData(row, null); - } - - // @Test - public void testHandleAsyncInvoke() throws Exception { - Map inputParams = Maps.newHashMap(); - inputParams.put("_id", 1); - GenericRow row = new GenericRow(3); - row.setField(0, 1); - row.setField(1, "bbbbbb"); - row.setField(2, "2020-07-14 01:27:43.969"); - ResultFuture resultFuture = mock(ResultFuture.class); - MongoCollection dbCollection = mock(MongoCollection.class); - BasicDBObject basicDbObject = mock(BasicDBObject.class); - Class classFindIterable = Class.forName("com.mongodb.async.client.FindIterableImpl"); - FindIterable findIterable = (FindIterable) classFindIterable.newInstance(); - - Document document = new Document(); - document.put("_id", "1"); - document.put("channel", "asdfad"); - document.put("name", "asdfasf"); - - when(sideTableInfo.getTableName()).thenReturn("cx"); - when(db.getCollection("cx", Document.class)).thenReturn(dbCollection); - when(dbCollection.find(basicDbObject)).thenReturn(findIterable); - - mongoAsyncReqRow.handleAsyncInvoke(inputParams, row, resultFuture); - - verify(findIterable).forEach(cb.capture(), eb.capture()); - cb.getValue().apply(document); - } -} diff --git a/mongo/mongo-side/mongo-async-side/src/test/java/com/dtstack/flink/sql/side/mongo/MongoAsyncSideInfoTest.java b/mongo/mongo-side/mongo-async-side/src/test/java/com/dtstack/flink/sql/side/mongo/MongoAsyncSideInfoTest.java deleted file mode 100644 index d3d5c6250..000000000 --- a/mongo/mongo-side/mongo-async-side/src/test/java/com/dtstack/flink/sql/side/mongo/MongoAsyncSideInfoTest.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.mongo; - -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.BaseSideInfo; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.mongo.table.MongoSideTableInfo; -import com.google.common.collect.Lists; -import org.apache.calcite.sql.SqlBasicCall; -import org.apache.calcite.sql.SqlBinaryOperator; -import org.apache.calcite.sql.SqlIdentifier; -import org.apache.calcite.sql.SqlNode; -import org.apache.calcite.sql.fun.SqlStdOperatorTable; -import org.apache.calcite.sql.parser.SqlParserPos; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import org.powermock.reflect.Whitebox; - -import java.util.ArrayList; -import java.util.List; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.powermock.api.support.membermodification.MemberMatcher.constructor; -import static org.powermock.api.support.membermodification.MemberModifier.suppress; - -/** - * @author: chuixue - * @create: 2020-07-27 15:11 - * @description: - **/ -@RunWith(PowerMockRunner.class) -@PrepareForTest({MongoAsyncSideInfo.class - , BaseSideInfo.class}) -public class MongoAsyncSideInfoTest { - - private MongoAsyncSideInfo mongoAsyncSideInfo; - private RowTypeInfo rowTypeInfo = new RowTypeInfo(new TypeInformation[]{TypeInformation.of(Integer.class), TypeInformation.of(String.class), TypeInformation.of(Integer.class)}, new String[]{"id", "bb", "PROCTIME"}); - private JoinInfo joinInfo; - private List outFieldInfoList = new ArrayList<>(); - private MongoSideTableInfo sideTableInfo; - private List equalFieldList = Lists.newArrayList(); - private List equalValIndex = Lists.newArrayList(); - - @Before - public void setUp() { - joinInfo = mock(JoinInfo.class); - sideTableInfo = mock(MongoSideTableInfo.class); - - suppress(constructor(BaseSideInfo.class)); - mongoAsyncSideInfo = new MongoAsyncSideInfo(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); - Whitebox.setInternalState(mongoAsyncSideInfo, "equalFieldList", equalFieldList); - Whitebox.setInternalState(mongoAsyncSideInfo, "rowTypeInfo", rowTypeInfo); - Whitebox.setInternalState(mongoAsyncSideInfo, "equalValIndex", equalValIndex); - } - - @Test - public void testBuildEqualInfo() { - JoinInfo joinInfo = mock(JoinInfo.class); - AbstractSideTableInfo sideTableInfo = mock(AbstractSideTableInfo.class); - SqlBinaryOperator equalsOperators = SqlStdOperatorTable.EQUALS; - SqlNode[] operands = new SqlNode[2]; - List one = Lists.newArrayList(); - one.add("m"); - one.add("id"); - List two = Lists.newArrayList(); - two.add("s"); - two.add("_id"); - operands[0] = new SqlIdentifier(one, new SqlParserPos(0, 0)); - operands[1] = new SqlIdentifier(two, new SqlParserPos(0, 0)); - SqlBasicCall sqlBasicCall = new SqlBasicCall(equalsOperators, operands, SqlParserPos.ZERO); - when(joinInfo.getSideTableName()).thenReturn("s"); - when(joinInfo.getCondition()).thenReturn(sqlBasicCall); - - mongoAsyncSideInfo.buildEqualInfo(joinInfo, sideTableInfo); - - RowTypeInfo rowTypeInfo2 = new RowTypeInfo(new TypeInformation[]{TypeInformation.of(Integer.class)}, new String[]{"_id"}); - Whitebox.setInternalState(mongoAsyncSideInfo, "rowTypeInfo", rowTypeInfo2); - when(joinInfo.getSideTableName()).thenReturn("m"); - mongoAsyncSideInfo.buildEqualInfo(joinInfo, sideTableInfo); - } -} diff --git a/mongo/mongo-side/mongo-side-core/src/main/java/com/dtstack/flink/sql/side/mongo/table/MongoSideParser.java b/mongo/mongo-side/mongo-side-core/src/main/java/com/dtstack/flink/sql/side/mongo/table/MongoSideParser.java index e75cf3b37..5edc12419 100644 --- a/mongo/mongo-side/mongo-side-core/src/main/java/com/dtstack/flink/sql/side/mongo/table/MongoSideParser.java +++ b/mongo/mongo-side/mongo-side-core/src/main/java/com/dtstack/flink/sql/side/mongo/table/MongoSideParser.java @@ -19,13 +19,15 @@ package com.dtstack.flink.sql.side.mongo.table; -import com.dtstack.flink.sql.table.AbstractSideTableParser; -import com.dtstack.flink.sql.table.AbstractTableInfo; +import com.dtstack.flink.sql.table.AbsSideTableParser; +import com.dtstack.flink.sql.table.TableInfo; import com.dtstack.flink.sql.util.MathUtil; import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; -import static com.dtstack.flink.sql.table.AbstractTableInfo.PARALLELISM_KEY; +import static com.dtstack.flink.sql.table.TableInfo.PARALLELISM_KEY; /** * Reason: @@ -33,7 +35,7 @@ * * @author xuqianjin */ -public class MongoSideParser extends AbstractSideTableParser { +public class MongoSideParser extends AbsSideTableParser { public static final String ADDRESS_KEY = "address"; @@ -46,7 +48,7 @@ public class MongoSideParser extends AbstractSideTableParser { public static final String DATABASE_KEY = "database"; @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { + public TableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { MongoSideTableInfo mongoSideTableInfo = new MongoSideTableInfo(); mongoSideTableInfo.setName(tableName); parseFieldsInfo(fieldsInfo, mongoSideTableInfo); @@ -60,11 +62,6 @@ public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map": - return new BasicDBObject("$gt", value); - case ">=": - return new BasicDBObject("$gte", value); - case "<": - return new BasicDBObject("$lt", value); - case "<=": - return new BasicDBObject("$lte", value); - case "<>": - return new BasicDBObject("$ne", value); - case "IN": - Object[] values = Arrays.stream(StringUtils.split(value, ",")).map(String::trim) - .collect(Collectors.toList()).toArray(); - return new BasicDBObject("$in", values); - case "NOT IN": - return new BasicDBObject("$nin", StringUtils.split(value, ",")); - case "IS NOT NULL": - return new BasicDBObject("$exists", true); - case "IS NULL": - return new BasicDBObject("$exists", false); - default: - } - return null; - } -} diff --git a/mongo/mongo-side/mongo-side-core/src/test/java/com/dtstack/flink/sql/side/mongo/table/MongoSideParserTest.java b/mongo/mongo-side/mongo-side-core/src/test/java/com/dtstack/flink/sql/side/mongo/table/MongoSideParserTest.java deleted file mode 100644 index 5471952f5..000000000 --- a/mongo/mongo-side/mongo-side-core/src/test/java/com/dtstack/flink/sql/side/mongo/table/MongoSideParserTest.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.mongo.table; - -import com.google.common.collect.Maps; -import org.junit.Test; - -import java.util.Map; - -/** - * @author: chuixue - * @create: 2020-07-27 09:26 - * @description: - **/ -public class MongoSideParserTest { - - private MongoSideParser mongoSideParser = new MongoSideParser(); - - @Test - public void testGetTableInfo() { - Map props = Maps.newHashMap(); - props.put("database", "test"); - props.put("cache", "ALL"); - props.put("address", "localhost:27017"); - props.put("type", "mongo"); - props.put("tablename", "cx"); - mongoSideParser.getTableInfo("hbaseSide", " _id int as _id, channel varchar as channel, name varchar as name, PRIMARY KEY(rowkey), PERIOD FOR SYSTEM_TIME ", props); - } - -} diff --git a/mongo/mongo-side/mongo-side-core/src/test/java/com/dtstack/flink/sql/side/mongo/utils/MongoUtilTest.java b/mongo/mongo-side/mongo-side-core/src/test/java/com/dtstack/flink/sql/side/mongo/utils/MongoUtilTest.java deleted file mode 100644 index c59aa294d..000000000 --- a/mongo/mongo-side/mongo-side-core/src/test/java/com/dtstack/flink/sql/side/mongo/utils/MongoUtilTest.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.mongo.utils; - -import com.dtstack.flink.sql.side.PredicateInfo; -import org.junit.Test; - -/** - * @author: chuixue - * @create: 2020-07-27 09:57 - * @description: - **/ -public class MongoUtilTest { - - @Test - public void testBuildFilterObject() { - PredicateInfo[] predicateInfos = new PredicateInfo[]{ - new PredicateInfo("=", null, null, null, "a,b,c") - , new PredicateInfo(">", null, null, null, "a,b,c") - , new PredicateInfo(">=", null, null, null, "a,b,c") - , new PredicateInfo("<", null, null, null, "a,b,c") - , new PredicateInfo("<=", null, null, null, "a,b,c") - , new PredicateInfo("<>", null, null, null, "a,b,c") - , new PredicateInfo("IN", null, null, null, "a,b,c") - , new PredicateInfo("NOT IN", null, null, null, "a,b,c") - , new PredicateInfo("IS NOT NULL", null, null, null, "a,b,c") - , new PredicateInfo("IS NULL", null, null, null, "a,b,c") - }; - for (PredicateInfo predicateInfo : predicateInfos) { - MongoUtil.buildFilterObject(predicateInfo); - } - } -} diff --git a/mongo/mongo-sink/pom.xml b/mongo/mongo-sink/pom.xml index f99b62e88..48bb3bef9 100644 --- a/mongo/mongo-sink/pom.xml +++ b/mongo/mongo-sink/pom.xml @@ -26,7 +26,6 @@ shade - false @@ -60,14 +59,14 @@ - + - + diff --git a/mongo/mongo-sink/src/main/java/com/dtstack/flink/sql/sink/mongo/MongoOutputFormat.java b/mongo/mongo-sink/src/main/java/com/dtstack/flink/sql/sink/mongo/MongoOutputFormat.java index df8293522..f37f5f379 100644 --- a/mongo/mongo-sink/src/main/java/com/dtstack/flink/sql/sink/mongo/MongoOutputFormat.java +++ b/mongo/mongo-sink/src/main/java/com/dtstack/flink/sql/sink/mongo/MongoOutputFormat.java @@ -19,9 +19,11 @@ package com.dtstack.flink.sql.sink.mongo; -import com.dtstack.flink.sql.outputformat.AbstractDtRichOutputFormat; +import com.dtstack.flink.sql.sink.MetricOutputFormat; import com.mongodb.MongoClient; -import com.mongodb.MongoClientURI; +import com.mongodb.MongoClientOptions; +import com.mongodb.MongoCredential; +import com.mongodb.ServerAddress; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; import com.mongodb.client.result.UpdateResult; @@ -34,8 +36,10 @@ import org.bson.types.ObjectId; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.List; /** * Reason: @@ -43,7 +47,7 @@ * * @author xuqianjin */ -public class MongoOutputFormat extends AbstractDtRichOutputFormat { +public class MongoOutputFormat extends MetricOutputFormat { private static final Logger LOG = LoggerFactory.getLogger(MongoOutputFormat.class); private String address; @@ -59,6 +63,10 @@ public class MongoOutputFormat extends AbstractDtRichOutputFormat { private static String PK = "_ID"; + private static int rowLenth = 1000; + + public final SimpleDateFormat ROWKEY_DATE_FORMAT = new SimpleDateFormat("yyyyMMddHHmmss"); + @Override public void configure(Configuration parameters) { } @@ -102,7 +110,7 @@ public void writeRecord(Tuple2 tuple2) throws IOException { dbCollection.insertOne(doc); } - if (outRecords.getCount() % ROW_PRINT_FREQUENCY == 0){ + if (outRecords.getCount()%rowLenth == 0){ LOG.info(record.toString()); } outRecords.inc(); @@ -120,9 +128,30 @@ public void close() { } private void establishConnection() { - - mongoClient = new MongoClient(new MongoClientURI(getConnectionUrl())); - db = mongoClient.getDatabase(database); + try { + MongoCredential credential; + String[] servers = address.split(","); + String host; + Integer port; + String[] hostAndPort; + List lists = new ArrayList<>(); + for (String server : servers) { + hostAndPort = server.split(":"); + host = hostAndPort[0]; + port = Integer.parseInt(hostAndPort[1]); + lists.add(new ServerAddress(host, port)); + } + if (!StringUtils.isEmpty(userName) || !StringUtils.isEmpty(password)) { + credential = MongoCredential.createCredential(userName, database, password.toCharArray()); + // To connect to mongodb server + mongoClient = new MongoClient(lists, credential, new MongoClientOptions.Builder().build()); + } else { + mongoClient = new MongoClient(lists); + } + db = mongoClient.getDatabase(database); + } catch (Exception e) { + throw new IllegalArgumentException("[connMongoDB]:" + e.getMessage()); + } } private MongoOutputFormat() { @@ -199,14 +228,5 @@ public MongoOutputFormat finish() { } } - private String getConnectionUrl(){ - if(address.startsWith("mongodb://") || address.startsWith("mongodb+srv://")){ - return address; - } - if (StringUtils.isNotBlank(userName) && StringUtils.isNotBlank(password)) { - return String.format("mongodb://%s:%s@%s", userName, password, address); - } - return String.format("mongodb://%s", address); - } } diff --git a/mongo/mongo-sink/src/main/java/com/dtstack/flink/sql/sink/mongo/MongoSink.java b/mongo/mongo-sink/src/main/java/com/dtstack/flink/sql/sink/mongo/MongoSink.java index 471e40576..4e28d8fd2 100644 --- a/mongo/mongo-sink/src/main/java/com/dtstack/flink/sql/sink/mongo/MongoSink.java +++ b/mongo/mongo-sink/src/main/java/com/dtstack/flink/sql/sink/mongo/MongoSink.java @@ -21,21 +21,18 @@ import com.dtstack.flink.sql.sink.IStreamSinkGener; import com.dtstack.flink.sql.sink.mongo.table.MongoTableInfo; -import com.dtstack.flink.sql.table.AbstractTargetTableInfo; +import com.dtstack.flink.sql.table.TargetTableInfo; import org.apache.flink.api.common.typeinfo.TypeInformation; import org.apache.flink.api.java.tuple.Tuple2; import org.apache.flink.api.java.typeutils.RowTypeInfo; import org.apache.flink.api.java.typeutils.TupleTypeInfo; import org.apache.flink.streaming.api.datastream.DataStream; -import org.apache.flink.streaming.api.datastream.DataStreamSink; import org.apache.flink.streaming.api.functions.sink.OutputFormatSinkFunction; import org.apache.flink.streaming.api.functions.sink.RichSinkFunction; import org.apache.flink.table.sinks.RetractStreamTableSink; import org.apache.flink.table.sinks.TableSink; import org.apache.flink.types.Row; -import java.util.Objects; - /** * Reason: * Date: 2018/11/6 @@ -51,34 +48,24 @@ public class MongoSink implements RetractStreamTableSink, IStreamSinkGener< protected String userName; protected String password; protected String database; - protected Integer parallelism = 1; - protected String registerTableName; public MongoSink() { // TO DO NOTHING } @Override - public MongoSink genStreamSink(AbstractTargetTableInfo targetTableInfo) { + public MongoSink genStreamSink(TargetTableInfo targetTableInfo) { MongoTableInfo mongoTableInfo = (MongoTableInfo) targetTableInfo; this.address = mongoTableInfo.getAddress(); this.tableName = mongoTableInfo.getTableName(); this.userName = mongoTableInfo.getUserName(); this.password = mongoTableInfo.getPassword(); this.database = mongoTableInfo.getDatabase(); - this.parallelism = Objects.isNull(mongoTableInfo.getParallelism()) ? - parallelism : mongoTableInfo.getParallelism(); - this.registerTableName = mongoTableInfo.getName(); return this; } @Override public void emitDataStream(DataStream> dataStream) { - consumeDataStream(dataStream); - } - - @Override - public DataStreamSink> consumeDataStream(DataStream> dataStream) { MongoOutputFormat.MongoOutputFormatBuilder builder = MongoOutputFormat.buildMongoOutputFormat(); builder.setAddress(this.address) .setDatabase(this.database) @@ -90,10 +77,7 @@ public DataStreamSink> consumeDataStream(DataStream props) { + public TableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { MongoTableInfo mongoTableInfo = new MongoTableInfo(); mongoTableInfo.setName(tableName); parseFieldsInfo(fieldsInfo, mongoTableInfo); @@ -60,7 +60,7 @@ public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map tuple = new Tuple2<>(true, row); - - mongoOutputFormat.writeRecord(tuple); - } -} diff --git a/mongo/mongo-sink/src/test/java/com/dtstack/flink/sql/sink/mongo/MongoSinkTest.java b/mongo/mongo-sink/src/test/java/com/dtstack/flink/sql/sink/mongo/MongoSinkTest.java deleted file mode 100644 index e66ab6edf..000000000 --- a/mongo/mongo-sink/src/test/java/com/dtstack/flink/sql/sink/mongo/MongoSinkTest.java +++ /dev/null @@ -1,85 +0,0 @@ -package com.dtstack.flink.sql.sink.mongo;/* - * 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. - */ - -import com.dtstack.flink.sql.sink.mongo.table.MongoTableInfo; -import org.apache.flink.streaming.api.datastream.DataStream; -import org.apache.flink.streaming.api.datastream.DataStreamSink; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.InjectMocks; -import org.mockito.MockitoAnnotations; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.api.support.membermodification.MemberModifier; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -import java.util.HashMap; -import java.util.Map; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.Mockito.when; - -/** - * @author: chuixue - * @create: 2020-07-24 16:52 - * @description: - **/ -@RunWith(PowerMockRunner.class) -@PrepareForTest({DataStream.class, - MongoSink.class}) -public class MongoSinkTest { - @InjectMocks - MongoSink mongoSink; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - } - - - @Test - public void testEmitDataStream() throws IllegalAccessException { - MemberModifier.field(MongoSink.class, "address").set(mongoSink, "localhost"); - MemberModifier.field(MongoSink.class, "database").set(mongoSink, "/hbase"); - MemberModifier.field(MongoSink.class, "tableName").set(mongoSink, "tableName"); - MemberModifier.field(MongoSink.class, "userName").set(mongoSink, "rowkey"); - MemberModifier.field(MongoSink.class, "password").set(mongoSink, "rowkey"); - - DataStream dataStream = PowerMockito.mock(DataStream.class); - - DataStreamSink dataStreamSink = PowerMockito.mock(DataStreamSink.class); - when(dataStream.addSink(any())).thenReturn(dataStreamSink); - when(dataStreamSink.setParallelism(anyInt())).thenReturn(dataStreamSink); - - mongoSink.emitDataStream(dataStream); - } - - @Test - public void testGenStreamSink() { - MongoTableInfo mongoTableInfo = new MongoTableInfo(); - mongoTableInfo.setAddress("172.16.8.193:27017"); - mongoTableInfo.setTableName("userInfo"); - mongoTableInfo.setUserName("name"); - mongoTableInfo.setPassword("pass"); - mongoTableInfo.setDatabase("dtstack"); - Assert.assertNotEquals(mongoTableInfo, mongoSink.genStreamSink(mongoTableInfo)); - } -} diff --git a/mongo/mongo-sink/src/test/java/com/dtstack/flink/sql/sink/mongo/table/MongoSinkParserTest.java b/mongo/mongo-sink/src/test/java/com/dtstack/flink/sql/sink/mongo/table/MongoSinkParserTest.java deleted file mode 100644 index 4243a2257..000000000 --- a/mongo/mongo-sink/src/test/java/com/dtstack/flink/sql/sink/mongo/table/MongoSinkParserTest.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.mongo.table; - -import org.junit.Test; - -import java.util.HashMap; -import java.util.Map; - -/** - * @author: chuixue - * @create: 2020-07-24 16:52 - * @description: - **/ -public class MongoSinkParserTest { - private MongoSinkParser mongoSinkParser; - - @Test - public void testGetTableInfo() { - mongoSinkParser = new MongoSinkParser(); - Map prop = new HashMap(); - - prop.put("type", "mongo"); - prop.put("address", "172.16.8.193:27017"); - prop.put("database", "dtstack"); - prop.put("tablename", "userInfo"); - - - mongoSinkParser.getTableInfo("userInfo", "id int,\n" + - " name VARCHAR,\n" + - " address VARCHAR,\n" + - " primary key (id)\n", prop); - } -} diff --git a/mongo/mongo-sink/src/test/java/com/dtstack/flinkx/AppTest.java b/mongo/mongo-sink/src/test/java/com/dtstack/flinkx/AppTest.java new file mode 100644 index 000000000..33a0233ac --- /dev/null +++ b/mongo/mongo-sink/src/test/java/com/dtstack/flinkx/AppTest.java @@ -0,0 +1,58 @@ +/* + * 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 com.dtstack.flinkx; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +/** + * Unit test for simple App. + */ +public class AppTest + extends TestCase +{ + /** + * Create the test case + * + * @param testName name of the test case + */ + public AppTest( String testName ) + { + super( testName ); + } + + /** + * @return the suite of tests being tested + */ + public static Test suite() + { + return new TestSuite( AppTest.class ); + } + + /** + * Rigourous Test :-) + */ + public void testApp() + { + assertTrue( true ); + } +} diff --git a/mongo/pom.xml b/mongo/pom.xml index cf3ddb895..efe8b4afb 100644 --- a/mongo/pom.xml +++ b/mongo/pom.xml @@ -17,6 +17,12 @@ + + junit + junit + 3.8.1 + test + com.dtstack.flink sql.core diff --git a/mysql/mysql-side/mysql-all-side/pom.xml b/mysql/mysql-side/mysql-all-side/pom.xml index 0949e3fb9..cc3df111d 100644 --- a/mysql/mysql-side/mysql-all-side/pom.xml +++ b/mysql/mysql-side/mysql-all-side/pom.xml @@ -40,7 +40,6 @@ shade - false @@ -74,14 +73,14 @@ - + - + diff --git a/mysql/mysql-side/mysql-all-side/src/main/java/com/dtstack/flink/sql/side/mysql/MysqlAllReqRow.java b/mysql/mysql-side/mysql-all-side/src/main/java/com/dtstack/flink/sql/side/mysql/MysqlAllReqRow.java index eb294e64e..b6b7f45cb 100644 --- a/mysql/mysql-side/mysql-all-side/src/main/java/com/dtstack/flink/sql/side/mysql/MysqlAllReqRow.java +++ b/mysql/mysql-side/mysql-all-side/src/main/java/com/dtstack/flink/sql/side/mysql/MysqlAllReqRow.java @@ -20,8 +20,8 @@ import com.dtstack.flink.sql.side.FieldInfo; import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.rdb.all.AbstractRdbAllReqRow; +import com.dtstack.flink.sql.side.SideTableInfo; +import com.dtstack.flink.sql.side.rdb.all.RdbAllReqRow; import com.dtstack.flink.sql.util.DtStringUtil; import org.apache.flink.api.java.typeutils.RowTypeInfo; import com.google.common.collect.Maps; @@ -41,7 +41,7 @@ * @author xuchao */ -public class MysqlAllReqRow extends AbstractRdbAllReqRow { +public class MysqlAllReqRow extends RdbAllReqRow { private static final long serialVersionUID = 2098635140857937717L; @@ -49,18 +49,18 @@ public class MysqlAllReqRow extends AbstractRdbAllReqRow { private static final String MYSQL_DRIVER = "com.mysql.jdbc.Driver"; - public MysqlAllReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { + public MysqlAllReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, SideTableInfo sideTableInfo) { super(new MysqlAllSideInfo(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo)); } @Override - public Connection getConn(String dbUrl, String userName, String password) { + public Connection getConn(String dbURL, String userName, String password) { try { Class.forName(MYSQL_DRIVER); //add param useCursorFetch=true Map addParams = Maps.newHashMap(); addParams.put("useCursorFetch", "true"); - String targetDbUrl = DtStringUtil.addJdbcParam(dbUrl, addParams, true); + String targetDbUrl = DtStringUtil.addJdbcParam(dbURL, addParams, true); return DriverManager.getConnection(targetDbUrl, userName, password); } catch (Exception e) { LOG.error("", e); diff --git a/mysql/mysql-side/mysql-all-side/src/main/java/com/dtstack/flink/sql/side/mysql/MysqlAllSideInfo.java b/mysql/mysql-side/mysql-all-side/src/main/java/com/dtstack/flink/sql/side/mysql/MysqlAllSideInfo.java index 503dbf9a3..81193c0f9 100644 --- a/mysql/mysql-side/mysql-all-side/src/main/java/com/dtstack/flink/sql/side/mysql/MysqlAllSideInfo.java +++ b/mysql/mysql-side/mysql-all-side/src/main/java/com/dtstack/flink/sql/side/mysql/MysqlAllSideInfo.java @@ -20,7 +20,7 @@ import com.dtstack.flink.sql.side.FieldInfo; import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; +import com.dtstack.flink.sql.side.SideTableInfo; import com.dtstack.flink.sql.side.rdb.all.RdbAllSideInfo; import org.apache.flink.api.java.typeutils.RowTypeInfo; @@ -35,12 +35,7 @@ */ public class MysqlAllSideInfo extends RdbAllSideInfo { - public MysqlAllSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { + public MysqlAllSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, SideTableInfo sideTableInfo) { super(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); } - - @Override - public String quoteIdentifier(String identifier) { - return "`" + identifier + "`"; - } } diff --git a/mysql/mysql-side/mysql-all-side/src/test/java/com/dtstack/flink/sql/side/mysql/MysqlAllReqRowTest.java b/mysql/mysql-side/mysql-all-side/src/test/java/com/dtstack/flink/sql/side/mysql/MysqlAllReqRowTest.java deleted file mode 100644 index 5e6554912..000000000 --- a/mysql/mysql-side/mysql-all-side/src/test/java/com/dtstack/flink/sql/side/mysql/MysqlAllReqRowTest.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.dtstack.flink.sql.side.mysql; - -import com.dtstack.flink.sql.side.rdb.all.RdbAllReqRowTestBase; -import org.junit.Assert; -import org.junit.Test; - -public class MysqlAllReqRowTest extends RdbAllReqRowTestBase { - - @Override - protected void init() { - clazz = MysqlAllReqRow.class; - } - - @Test - public void testFetch() { - Assert.assertTrue(Integer.MIN_VALUE == reqRow.getFetchSize()); - } - -} \ No newline at end of file diff --git a/mysql/mysql-side/mysql-async-side/pom.xml b/mysql/mysql-side/mysql-async-side/pom.xml index 00e323a30..55110ad3b 100644 --- a/mysql/mysql-side/mysql-async-side/pom.xml +++ b/mysql/mysql-side/mysql-async-side/pom.xml @@ -41,7 +41,6 @@ shade - false @@ -75,14 +74,14 @@ - + - + diff --git a/mysql/mysql-side/mysql-async-side/src/main/java/com/dtstack/flink/sql/side/mysql/MysqlAsyncReqRow.java b/mysql/mysql-side/mysql-async-side/src/main/java/com/dtstack/flink/sql/side/mysql/MysqlAsyncReqRow.java index aa81910ab..6120767ef 100644 --- a/mysql/mysql-side/mysql-async-side/src/main/java/com/dtstack/flink/sql/side/mysql/MysqlAsyncReqRow.java +++ b/mysql/mysql-side/mysql-async-side/src/main/java/com/dtstack/flink/sql/side/mysql/MysqlAsyncReqRow.java @@ -19,14 +19,19 @@ package com.dtstack.flink.sql.side.mysql; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; import com.dtstack.flink.sql.side.FieldInfo; import com.dtstack.flink.sql.side.JoinInfo; +import com.dtstack.flink.sql.side.SideTableInfo; import com.dtstack.flink.sql.side.rdb.async.RdbAsyncReqRow; import com.dtstack.flink.sql.side.rdb.table.RdbSideTableInfo; +import io.vertx.core.Vertx; +import io.vertx.core.VertxOptions; import io.vertx.core.json.JsonObject; +import io.vertx.ext.jdbc.JDBCClient; import org.apache.flink.api.java.typeutils.RowTypeInfo; import org.apache.flink.configuration.Configuration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.List; @@ -39,9 +44,12 @@ */ public class MysqlAsyncReqRow extends RdbAsyncReqRow { + + private static final Logger LOG = LoggerFactory.getLogger(MysqlAsyncReqRow.class); + private final static String MYSQL_DRIVER = "com.mysql.jdbc.Driver"; - public MysqlAsyncReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { + public MysqlAsyncReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, SideTableInfo sideTableInfo) { super(new MysqlAsyncSideInfo(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo)); } @@ -49,15 +57,11 @@ public MysqlAsyncReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { + public MysqlAsyncSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, SideTableInfo sideTableInfo) { super(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); } - - @Override - public String quoteIdentifier(String identifier) { - return "`" + identifier + "`"; - } } diff --git a/mysql/mysql-side/mysql-async-side/src/test/java/com/dtstack/flink/sql/side/mysql/MysqlAsyncReqRowTest.java b/mysql/mysql-side/mysql-async-side/src/test/java/com/dtstack/flink/sql/side/mysql/MysqlAsyncReqRowTest.java deleted file mode 100644 index 4153bf908..000000000 --- a/mysql/mysql-side/mysql-async-side/src/test/java/com/dtstack/flink/sql/side/mysql/MysqlAsyncReqRowTest.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.dtstack.flink.sql.side.mysql; - -import com.dtstack.flink.sql.side.rdb.async.RdbAsyncReqRowTestBase; - -public class MysqlAsyncReqRowTest extends RdbAsyncReqRowTestBase { - - @Override - protected void init() { - clazz = MysqlAsyncReqRow.class; - } - -} \ No newline at end of file diff --git a/mysql/mysql-side/mysql-side-core/src/main/java/com/dtstack/flink/sql/side/mysql/table/MysqlSideParser.java b/mysql/mysql-side/mysql-side-core/src/main/java/com/dtstack/flink/sql/side/mysql/table/MysqlSideParser.java index 4488ca7d7..40f68e7e4 100644 --- a/mysql/mysql-side/mysql-side-core/src/main/java/com/dtstack/flink/sql/side/mysql/table/MysqlSideParser.java +++ b/mysql/mysql-side/mysql-side-core/src/main/java/com/dtstack/flink/sql/side/mysql/table/MysqlSideParser.java @@ -19,10 +19,8 @@ package com.dtstack.flink.sql.side.mysql.table; -import com.dtstack.flink.sql.core.rdb.JdbcCheckKeys; import com.dtstack.flink.sql.side.rdb.table.RdbSideParser; -import com.dtstack.flink.sql.side.rdb.table.RdbSideTableInfo; -import com.dtstack.flink.sql.table.AbstractTableInfo; +import com.dtstack.flink.sql.table.TableInfo; import java.util.Map; @@ -39,9 +37,8 @@ public class MysqlSideParser extends RdbSideParser { private static final String CURR_TYPE = "mysql"; @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { - props.put(JdbcCheckKeys.DRIVER_NAME, "com.mysql.jdbc.Driver"); - RdbSideTableInfo mysqlTableInfo = (RdbSideTableInfo) super.getTableInfo(tableName, fieldsInfo, props); + public TableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { + TableInfo mysqlTableInfo = super.getTableInfo(tableName, fieldsInfo, props); mysqlTableInfo.setType(CURR_TYPE); return mysqlTableInfo; } diff --git a/mysql/mysql-side/mysql-side-core/src/test/java/com/dtstack/flink/sql/side/mysql/table/MysqlSideParserTest.java b/mysql/mysql-side/mysql-side-core/src/test/java/com/dtstack/flink/sql/side/mysql/table/MysqlSideParserTest.java deleted file mode 100644 index 62c54cd5b..000000000 --- a/mysql/mysql-side/mysql-side-core/src/test/java/com/dtstack/flink/sql/side/mysql/table/MysqlSideParserTest.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.dtstack.flink.sql.side.mysql.table; - -import com.dtstack.flink.sql.table.AbstractTableInfo; -import org.junit.Assert; -import org.junit.Test; - -import java.util.HashMap; -import java.util.Map; - -import static org.junit.Assert.*; - -public class MysqlSideParserTest { - -// @Test - public void getTableInfo() { - MysqlSideParser mysqlSideParser = new MysqlSideParser(); - - final String tableName = "table_foo"; - final String fieldsInfo = "id INT, name VARCHAR, PRIMARY KEY (id)"; - - Map props = new HashMap(); - props.put("url", "jdbc:mysql://foo:3306/db_foo"); - props.put("tablename", "table_foo"); - props.put("username", "foo"); - props.put("password", "foo"); - - AbstractTableInfo tableInfo= mysqlSideParser.getTableInfo(tableName, fieldsInfo, props); - - final String NORMAL_TYPE = "mysql"; - final String table_type = tableInfo.getType(); - Assert.assertTrue(NORMAL_TYPE.equals(table_type)); - } -} \ No newline at end of file diff --git a/mysql/mysql-side/pom.xml b/mysql/mysql-side/pom.xml index be98e95d4..4f104b07f 100644 --- a/mysql/mysql-side/pom.xml +++ b/mysql/mysql-side/pom.xml @@ -32,16 +32,6 @@ sql.side.rdb ${rdb.side.version} - - - - - com.dtstack.flink - sql.side.rdb - ${rdb.side.version} - test-jar - test - diff --git a/mysql/mysql-sink/pom.xml b/mysql/mysql-sink/pom.xml index ba01e57db..139a3ea53 100644 --- a/mysql/mysql-sink/pom.xml +++ b/mysql/mysql-sink/pom.xml @@ -39,7 +39,6 @@ shade - false @@ -73,14 +72,14 @@ - + - + diff --git a/mysql/mysql-sink/src/main/java/com/dtstack/flink/sql/sink/mysql/MySQLDialect.java b/mysql/mysql-sink/src/main/java/com/dtstack/flink/sql/sink/mysql/MySQLDialect.java deleted file mode 100644 index 9ce6833a8..000000000 --- a/mysql/mysql-sink/src/main/java/com/dtstack/flink/sql/sink/mysql/MySQLDialect.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.mysql; - -import com.dtstack.flink.sql.sink.rdb.dialect.JDBCDialect; - -import java.util.Arrays; -import java.util.Optional; -import java.util.stream.Collectors; - -/** - * Date: 2019/12/31 - * Company: www.dtstack.com - * @author maqi - */ -public class MySQLDialect implements JDBCDialect { - private static final long serialVersionUID = 1L; - - @Override - public boolean canHandle(String url) { - return url.startsWith("jdbc:mysql:"); - } - - @Override - public Optional defaultDriverName() { - return Optional.of("com.mysql.jdbc.Driver"); - } - - @Override - public String quoteIdentifier(String identifier) { - return "`" + identifier + "`"; - } - - /** - * 根据ALLReplace参数,选择使用replace语句还是ON DUPLICATE KEY UPDATE 语句 - * @param tableName - * @param fieldNames - * @param uniqueKeyFields - * @param allReplace - * @return - */ - @Override - public Optional getUpsertStatement(String schema, String tableName, String[] fieldNames, String[] uniqueKeyFields, boolean allReplace) { - return allReplace ? buildReplaceIntoStatement(tableName, fieldNames) : buildDuplicateUpsertStatement(tableName, fieldNames); - } - - public Optional buildDuplicateUpsertStatement(String tableName, String[] fieldNames) { - String updateClause = Arrays.stream(fieldNames).map(f -> quoteIdentifier(f) + "=IFNULL(VALUES(" + quoteIdentifier(f) + ")," + quoteIdentifier(f) + ")") - .collect(Collectors.joining(", ")); - return Optional.of(getInsertIntoStatement("", tableName, fieldNames, null) + - " ON DUPLICATE KEY UPDATE " + updateClause - ); - } - - public Optional buildReplaceIntoStatement(String tableName, String[] fieldNames) { - String columns = Arrays.stream(fieldNames) - .map(this::quoteIdentifier) - .collect(Collectors.joining(", ")); - String placeholders = Arrays.stream(fieldNames) - .map(f -> "?") - .collect(Collectors.joining(", ")); - return Optional.of("REPLACE INTO " + quoteIdentifier(tableName) + - "(" + columns + ")" + " VALUES (" + placeholders + ")"); - } -} diff --git a/mysql/mysql-sink/src/main/java/com/dtstack/flink/sql/sink/mysql/MysqlSink.java b/mysql/mysql-sink/src/main/java/com/dtstack/flink/sql/sink/mysql/MysqlSink.java index 98972f315..9ba6736be 100644 --- a/mysql/mysql-sink/src/main/java/com/dtstack/flink/sql/sink/mysql/MysqlSink.java +++ b/mysql/mysql-sink/src/main/java/com/dtstack/flink/sql/sink/mysql/MysqlSink.java @@ -21,10 +21,12 @@ import com.dtstack.flink.sql.sink.IStreamSinkGener; -import com.dtstack.flink.sql.sink.rdb.AbstractRdbSink; -import com.dtstack.flink.sql.sink.rdb.JDBCOptions; -import com.dtstack.flink.sql.sink.rdb.format.JDBCUpsertOutputFormat; +import com.dtstack.flink.sql.sink.rdb.RdbSink; +import com.dtstack.flink.sql.sink.rdb.format.RetractJDBCOutputFormat; +import com.dtstack.flink.sql.util.DtStringUtil; +import java.util.List; +import java.util.Map; /** * Date: 2017/2/27 @@ -33,33 +35,50 @@ * @author xuchao */ -public class MysqlSink extends AbstractRdbSink implements IStreamSinkGener { +public class MysqlSink extends RdbSink implements IStreamSinkGener { + + private static final String MYSQL_DRIVER = "com.mysql.jdbc.Driver"; public MysqlSink() { - super(new MySQLDialect()); } @Override - public JDBCUpsertOutputFormat getOutputFormat() { - JDBCOptions jdbcOptions = JDBCOptions.builder() - .setDbUrl(dbUrl) - .setDialect(jdbcDialect) - .setUsername(userName) - .setPassword(password) - .setTableName(tableName) - .build(); - - return JDBCUpsertOutputFormat.builder() - .setOptions(jdbcOptions) - .setFieldNames(fieldNames) - .setFlushMaxSize(batchNum) - .setFlushIntervalMills(batchWaitInterval) - .setFieldTypes(sqlTypes) - .setKeyFields(primaryKeys) - .setAllReplace(allReplace) - .setUpdateMode(updateMode) - .setErrorLimit(errorLimit) - .setName(name) - .build(); + public RetractJDBCOutputFormat getOutputFormat() { + return new RetractJDBCOutputFormat(); + } + + @Override + public void buildSql(String scheam, String tableName, List fields) { + buildInsertSql(tableName, fields); + } + + @Override + public String buildUpdateSql(String schema, String tableName, List fieldNames, Map> realIndexes, List fullField) { + return null; + } + + private void buildInsertSql(String tableName, List fields) { + String sqlTmp = "replace into " + tableName + " (${fields}) values (${placeholder})"; + String fieldsStr = ""; + String placeholder = ""; + + for (String fieldName : fields) { + fieldsStr += ",`" + fieldName + "`"; + placeholder += ",?"; + } + + fieldsStr = fieldsStr.replaceFirst(",", ""); + placeholder = placeholder.replaceFirst(",", ""); + + sqlTmp = sqlTmp.replace("${fields}", fieldsStr).replace("${placeholder}", placeholder); + this.sql = sqlTmp; + } + + + @Override + public String getDriverName() { + return MYSQL_DRIVER; } + + } diff --git a/mysql/mysql-sink/src/main/java/com/dtstack/flink/sql/sink/mysql/table/MysqlSinkParser.java b/mysql/mysql-sink/src/main/java/com/dtstack/flink/sql/sink/mysql/table/MysqlSinkParser.java index 8359fa0ff..2247eb8cc 100644 --- a/mysql/mysql-sink/src/main/java/com/dtstack/flink/sql/sink/mysql/table/MysqlSinkParser.java +++ b/mysql/mysql-sink/src/main/java/com/dtstack/flink/sql/sink/mysql/table/MysqlSinkParser.java @@ -19,9 +19,8 @@ package com.dtstack.flink.sql.sink.mysql.table; -import com.dtstack.flink.sql.core.rdb.JdbcCheckKeys; import com.dtstack.flink.sql.sink.rdb.table.RdbSinkParser; -import com.dtstack.flink.sql.table.AbstractTableInfo; +import com.dtstack.flink.sql.table.TableInfo; import java.util.Map; @@ -37,9 +36,8 @@ public class MysqlSinkParser extends RdbSinkParser { private static final String CURR_TYPE = "mysql"; @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { - props.put(JdbcCheckKeys.DRIVER_NAME, "com.mysql.jdbc.Driver"); - AbstractTableInfo mysqlTableInfo = super.getTableInfo(tableName, fieldsInfo, props); + public TableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { + TableInfo mysqlTableInfo = super.getTableInfo(tableName, fieldsInfo, props); mysqlTableInfo.setType(CURR_TYPE); return mysqlTableInfo; } diff --git a/mysql/mysql-sink/src/test/java/com/dtstack/flink/sql/sink/mysql/MySQLDialectTest.java b/mysql/mysql-sink/src/test/java/com/dtstack/flink/sql/sink/mysql/MySQLDialectTest.java deleted file mode 100644 index 696e507d7..000000000 --- a/mysql/mysql-sink/src/test/java/com/dtstack/flink/sql/sink/mysql/MySQLDialectTest.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.dtstack.flink.sql.sink.mysql; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -/** - * @program: flink.sql - * @author: wuren - * @create: 2020/06/17 - **/ -public class MySQLDialectTest { - - MySQLDialect mysqlDialect; - - @Before - public void setUp() throws Exception { - mysqlDialect = new MySQLDialect(); - } - - @Test - public void testEasyUtils() { - final String s = "jdbc:mysql://localhost:3306/foo_db"; - boolean r = mysqlDialect.canHandle(s); - Assert.assertTrue(r); - - String driver = mysqlDialect.defaultDriverName().get(); - Assert.assertTrue(driver.equals("com.mysql.jdbc.Driver")); - - final String foo = "foo"; - final String NORMAL_QUOTE = "`foo`"; - String strWithQuote = mysqlDialect.quoteIdentifier(foo); - - Assert.assertTrue(strWithQuote.equals(NORMAL_QUOTE)); - } - - @Test - public void testDialect() { - final String tableName = "table_foo"; - final String[] fieldNames = new String[] { - "id", - "name" - }; - final String NORMAL_REPELACE_STMT = - "REPLACE INTO `table_foo`(`id`, `name`) VALUES (?, ?)"; - final String NORMAL_UPSERT_STMT = - "INSERT INTO `table_foo`(`id`, `name`) VALUES (?, ?) " + - "ON DUPLICATE KEY UPDATE `id`=IFNULL(VALUES(`id`),`id`), " + - "`name`=IFNULL(VALUES(`name`),`name`)"; - - String replaceStmt = mysqlDialect.buildReplaceIntoStatement(tableName, fieldNames) - .get(); - String upsertStmt = mysqlDialect.buildDuplicateUpsertStatement(tableName, fieldNames) - .get(); - - Assert.assertTrue(NORMAL_REPELACE_STMT.equals(replaceStmt)); - Assert.assertTrue(NORMAL_UPSERT_STMT.equals(upsertStmt)); - - String upsertStmtWithReplace = mysqlDialect - .getUpsertStatement("", tableName, fieldNames, null, true) - .get(); - String upsertStmtWithoutReplace = mysqlDialect - .getUpsertStatement("", tableName, fieldNames, null, false) - .get(); - - Assert.assertTrue(replaceStmt.equals(upsertStmtWithReplace)); - Assert.assertTrue(upsertStmt.equals(upsertStmtWithoutReplace)); - } - -} \ No newline at end of file diff --git a/mysql/mysql-sink/src/test/java/com/dtstack/flink/sql/sink/mysql/MysqlSinkTest.java b/mysql/mysql-sink/src/test/java/com/dtstack/flink/sql/sink/mysql/MysqlSinkTest.java deleted file mode 100644 index c072efc91..000000000 --- a/mysql/mysql-sink/src/test/java/com/dtstack/flink/sql/sink/mysql/MysqlSinkTest.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.dtstack.flink.sql.sink.mysql; - -import com.dtstack.flink.sql.sink.rdb.dialect.JDBCDialect; -import com.dtstack.flink.sql.sink.rdb.format.JDBCUpsertOutputFormat; -import org.junit.Before; -import org.junit.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.mockito.Spy; -import org.powermock.api.support.membermodification.MemberModifier; - -import java.util.Optional; - -import static org.mockito.Mockito.*; - -/** - * @program: flink.sql - * @author: wuren - * @create: 2020/06/17 - **/ -public class MysqlSinkTest { - - @Mock - JDBCDialect jdbcDialect; - - @InjectMocks - MysqlSink mysqlSink = new MysqlSink();; - @Before - public void setUp () { - MockitoAnnotations.initMocks(this); - } - - @Test - public void testGetOutputFormat() throws IllegalAccessException { - when(jdbcDialect.defaultDriverName()).thenReturn(Optional.of("dd")); - - MemberModifier.field(MysqlSink.class, "dbUrl").set(mysqlSink, "foo"); - MemberModifier.field(MysqlSink.class, "jdbcDialect").set(mysqlSink, jdbcDialect); - MemberModifier.field(MysqlSink.class, "userName").set(mysqlSink, "foo"); - MemberModifier.field(MysqlSink.class, "password").set(mysqlSink, "foo"); - MemberModifier.field(MysqlSink.class, "tableName").set(mysqlSink, "foo"); - MemberModifier.field(MysqlSink.class, "fieldNames").set(mysqlSink, new String[]{"foo", "bar"}); - - JDBCUpsertOutputFormat format = mysqlSink.getOutputFormat(); - } -} diff --git a/mysql/mysql-sink/src/test/java/com/dtstack/flink/sql/sink/mysql/table/MysqlSinkParserTest.java b/mysql/mysql-sink/src/test/java/com/dtstack/flink/sql/sink/mysql/table/MysqlSinkParserTest.java deleted file mode 100644 index 52da563b1..000000000 --- a/mysql/mysql-sink/src/test/java/com/dtstack/flink/sql/sink/mysql/table/MysqlSinkParserTest.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.dtstack.flink.sql.sink.mysql.table; - -import org.junit.Before; -import org.junit.Test; - -import static org.junit.Assert.*; - -/** - * @program: flink.sql - * @author: wuren - * @create: 2020/06/17 - **/ -public class MysqlSinkParserTest { - - @Before - public void setUp() throws Exception { - } - - @Test - public void getTableInfo() { - } -} \ No newline at end of file diff --git a/mysql/mysql-sink/src/test/java/com/dtstack/flinkx/AppTest.java b/mysql/mysql-sink/src/test/java/com/dtstack/flinkx/AppTest.java new file mode 100644 index 000000000..33a0233ac --- /dev/null +++ b/mysql/mysql-sink/src/test/java/com/dtstack/flinkx/AppTest.java @@ -0,0 +1,58 @@ +/* + * 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 com.dtstack.flinkx; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +/** + * Unit test for simple App. + */ +public class AppTest + extends TestCase +{ + /** + * Create the test case + * + * @param testName name of the test case + */ + public AppTest( String testName ) + { + super( testName ); + } + + /** + * @return the suite of tests being tested + */ + public static Test suite() + { + return new TestSuite( AppTest.class ); + } + + /** + * Rigourous Test :-) + */ + public void testApp() + { + assertTrue( true ); + } +} diff --git a/mysql/pom.xml b/mysql/pom.xml index 8cc9c12ff..36221bcff 100644 --- a/mysql/pom.xml +++ b/mysql/pom.xml @@ -24,6 +24,12 @@ + + junit + junit + 3.8.1 + test + com.dtstack.flink diff --git a/oceanbase/oceanbase-side/oceanbase-all-side/pom.xml b/oceanbase/oceanbase-side/oceanbase-all-side/pom.xml deleted file mode 100644 index 7e6dc9e85..000000000 --- a/oceanbase/oceanbase-side/oceanbase-all-side/pom.xml +++ /dev/null @@ -1,94 +0,0 @@ - - - - sql.side.oceanbase - com.dtstack.flink - 1.0-SNAPSHOT - ../pom.xml - - 4.0.0 - - sql.side.all.oceanbase - oceanbase-all-side - jar - 1.0-SNAPSHOT - - - 1.0-SNAPSHOT - - - - - com.dtstack.flink - sql.side.oceanbase.core - ${sql.side.oceanbase.core.version} - - - - - - - org.apache.maven.plugins - maven-shade-plugin - 1.4 - - - package - - shade - - - false - - - - - - - - *:* - - META-INF/*.SF - META-INF/*.DSA - META-INF/*.RSA - - - - - - - - - - maven-antrun-plugin - 1.2 - - - copy-resources - - package - - run - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/oceanbase/oceanbase-side/oceanbase-all-side/src/main/java/com/dtstack/flink/sql/side/oceanbase/OceanbaseAllReqRow.java b/oceanbase/oceanbase-side/oceanbase-all-side/src/main/java/com/dtstack/flink/sql/side/oceanbase/OceanbaseAllReqRow.java deleted file mode 100644 index 379118165..000000000 --- a/oceanbase/oceanbase-side/oceanbase-all-side/src/main/java/com/dtstack/flink/sql/side/oceanbase/OceanbaseAllReqRow.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.oceanbase; - -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.rdb.all.AbstractRdbAllReqRow; -import com.dtstack.flink.sql.util.DtStringUtil; -import com.google.common.collect.Maps; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.sql.Connection; -import java.sql.DriverManager; -import java.util.List; -import java.util.Map; - -/** - * @author : tiezhu - * @date : 2020/3/26 - */ -public class OceanbaseAllReqRow extends AbstractRdbAllReqRow { - - private static final Logger LOG = LoggerFactory.getLogger(OceanbaseAllReqRow.class); - - private static final String OCEAN_BASE_DRIVER = "com.mysql.jdbc.Driver"; - - public OceanbaseAllReqRow(RowTypeInfo rowTypeInfo, - JoinInfo joinInfo, - List outFieldInfoList, - AbstractSideTableInfo sideTableInfo) { - super(new OceanbaseAllSideInfo(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo)); - } - - @Override - public Connection getConn(String dbUrl, String userName, String password) { - try { - Class.forName(OCEAN_BASE_DRIVER); - Map addParams = Maps.newHashMap(); - addParams.put("useCursorFetch", "true"); - String targetDbUrl = DtStringUtil.addJdbcParam(dbUrl, addParams, true); - return DriverManager.getConnection(targetDbUrl, userName, password); - } catch (Exception e) { - LOG.error("oceanbase get connect error", e); - throw new RuntimeException(e); - } - } - - @Override - public int getFetchSize() { - return Integer.MIN_VALUE; - } -} diff --git a/oceanbase/oceanbase-side/oceanbase-all-side/src/main/java/com/dtstack/flink/sql/side/oceanbase/OceanbaseAllSideInfo.java b/oceanbase/oceanbase-side/oceanbase-all-side/src/main/java/com/dtstack/flink/sql/side/oceanbase/OceanbaseAllSideInfo.java deleted file mode 100644 index 565e8c193..000000000 --- a/oceanbase/oceanbase-side/oceanbase-all-side/src/main/java/com/dtstack/flink/sql/side/oceanbase/OceanbaseAllSideInfo.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.oceanbase; - -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.rdb.all.RdbAllSideInfo; -import org.apache.flink.api.java.typeutils.RowTypeInfo; - -import java.util.List; - -/** - * @author : tiezhu - * @date : 2020/3/26 - */ -public class OceanbaseAllSideInfo extends RdbAllSideInfo { - public OceanbaseAllSideInfo(RowTypeInfo rowTypeInfo, - JoinInfo joinInfo, - List outFieldInfoList, - AbstractSideTableInfo sideTableInfo) { - super(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); - } -} diff --git a/oceanbase/oceanbase-side/oceanbase-all-side/src/test/java/com/dtstatck/flink/sql/side/oceanbase/OceanbaseAllReqRowTest.java b/oceanbase/oceanbase-side/oceanbase-all-side/src/test/java/com/dtstatck/flink/sql/side/oceanbase/OceanbaseAllReqRowTest.java deleted file mode 100644 index 7d7e9ea58..000000000 --- a/oceanbase/oceanbase-side/oceanbase-all-side/src/test/java/com/dtstatck/flink/sql/side/oceanbase/OceanbaseAllReqRowTest.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.dtstatck.flink.sql.side.oceanbase; - -import com.dtstack.flink.sql.side.oceanbase.OceanbaseAllReqRow; -import com.dtstack.flink.sql.side.rdb.all.RdbAllReqRowTestBase; - -public class OceanbaseAllReqRowTest extends RdbAllReqRowTestBase { - - @Override - protected void init() { - clazz = OceanbaseAllReqRow.class; - } - -} \ No newline at end of file diff --git a/oceanbase/oceanbase-side/oceanbase-async-side/pom.xml b/oceanbase/oceanbase-side/oceanbase-async-side/pom.xml deleted file mode 100644 index 2624147b5..000000000 --- a/oceanbase/oceanbase-side/oceanbase-async-side/pom.xml +++ /dev/null @@ -1,92 +0,0 @@ - - - - sql.side.oceanbase - com.dtstack.flink - 1.0-SNAPSHOT - ../pom.xml - - 4.0.0 - - sql.side.async.oceanbase - oceanbase-async-side - jar - 1.0-SNAPSHOT - - - 1.0-SNAPSHOT - - - - - com.dtstack.flink - sql.side.oceanbase.core - ${sql.side.oceanbase.core.version} - - - - - - - org.apache.maven.plugins - maven-shade-plugin - 1.4 - - - package - - shade - - - false - - - - - - - - *:* - - META-INF/*.SF - META-INF/*.DSA - META-INF/*.RSA - - - - - - - - - - maven-antrun-plugin - 1.2 - - - copy-resources - - package - - run - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/oceanbase/oceanbase-side/oceanbase-async-side/src/main/java/com/dtstack/flink/sql/side/oceanbase/OceanbaseAsyncReqRow.java b/oceanbase/oceanbase-side/oceanbase-async-side/src/main/java/com/dtstack/flink/sql/side/oceanbase/OceanbaseAsyncReqRow.java deleted file mode 100644 index ad91f6302..000000000 --- a/oceanbase/oceanbase-side/oceanbase-async-side/src/main/java/com/dtstack/flink/sql/side/oceanbase/OceanbaseAsyncReqRow.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.oceanbase; - -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.rdb.async.RdbAsyncReqRow; -import com.dtstack.flink.sql.side.rdb.table.RdbSideTableInfo; -import io.vertx.core.json.JsonObject; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.configuration.Configuration; - -import java.util.List; - -/** - * @author : tiezhu - * @date : 2020/3/26 - */ -public class OceanbaseAsyncReqRow extends RdbAsyncReqRow { - - private static final String OCEAN_BASE_DRIVER = "com.mysql.jdbc.Driver"; - - public OceanbaseAsyncReqRow(RowTypeInfo rowTypeInfo, - JoinInfo joinInfo, - List outFieldInfoList, - AbstractSideTableInfo sideTableInfo) { - super(new OceanbaseAsyncSideInfo(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo)); - } - - @Override - public void open(Configuration parameters) throws Exception { - super.open(parameters); - } - - @Override - public JsonObject buildJdbcConfig() { - JsonObject oceanbaseClientConfig = new JsonObject(); - RdbSideTableInfo rdbSideTableInfo = (RdbSideTableInfo) sideInfo.getSideTableInfo(); - oceanbaseClientConfig.put("url", rdbSideTableInfo.getUrl()) - .put("driver_class", OCEAN_BASE_DRIVER) - .put("max_pool_size", rdbSideTableInfo.getAsyncPoolSize()) - .put("user", rdbSideTableInfo.getUserName()) - .put("password", rdbSideTableInfo.getPassword()) - .put("provider_class", DT_PROVIDER_CLASS) - .put("preferred_test_query", PREFERRED_TEST_QUERY_SQL) - .put("idle_connection_test_period", DEFAULT_IDLE_CONNECTION_TEST_PEROID) - .put("test_conncetion_on_checkin", DEFAULT_TEST_CONNECTION_ON_CHECKIN); - - return oceanbaseClientConfig; - } -} diff --git a/oceanbase/oceanbase-side/oceanbase-async-side/src/main/java/com/dtstack/flink/sql/side/oceanbase/OceanbaseAsyncSideInfo.java b/oceanbase/oceanbase-side/oceanbase-async-side/src/main/java/com/dtstack/flink/sql/side/oceanbase/OceanbaseAsyncSideInfo.java deleted file mode 100644 index c3e79a573..000000000 --- a/oceanbase/oceanbase-side/oceanbase-async-side/src/main/java/com/dtstack/flink/sql/side/oceanbase/OceanbaseAsyncSideInfo.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.oceanbase; - -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.rdb.async.RdbAsyncSideInfo; -import org.apache.flink.api.java.typeutils.RowTypeInfo; - -import java.util.List; - -/** - * @author : tiezhu - * @date : 2020/3/26 - */ -public class OceanbaseAsyncSideInfo extends RdbAsyncSideInfo { - - public OceanbaseAsyncSideInfo(RowTypeInfo rowTypeInfo, - JoinInfo joinInfo, - List outfieldsInfoList, - AbstractSideTableInfo sideTableInfo){ - super(rowTypeInfo, joinInfo, outfieldsInfoList, sideTableInfo); - } -} diff --git a/oceanbase/oceanbase-side/oceanbase-async-side/src/test/java/com/dtstack/flink/sql/side/oceanbase/OceanbaseAsyncReqRowTest.java b/oceanbase/oceanbase-side/oceanbase-async-side/src/test/java/com/dtstack/flink/sql/side/oceanbase/OceanbaseAsyncReqRowTest.java deleted file mode 100644 index dea388810..000000000 --- a/oceanbase/oceanbase-side/oceanbase-async-side/src/test/java/com/dtstack/flink/sql/side/oceanbase/OceanbaseAsyncReqRowTest.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.dtstack.flink.sql.side.oceanbase; - -import com.dtstack.flink.sql.side.rdb.async.RdbAsyncReqRowTestBase; - -public class OceanbaseAsyncReqRowTest extends RdbAsyncReqRowTestBase { - - @Override - protected void init() { - clazz = OceanbaseAsyncReqRow.class; - } - -} \ No newline at end of file diff --git a/oceanbase/oceanbase-side/oceanbase-side-core/pom.xml b/oceanbase/oceanbase-side/oceanbase-side-core/pom.xml deleted file mode 100644 index 397b62063..000000000 --- a/oceanbase/oceanbase-side/oceanbase-side-core/pom.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - sql.side.oceanbase - com.dtstack.flink - 1.0-SNAPSHOT - ../pom.xml - - 4.0.0 - - sql.side.oceanbase.core - oceanbase-side-core - 1.0-SNAPSHOT - jar - - \ No newline at end of file diff --git a/oceanbase/oceanbase-side/oceanbase-side-core/src/main/java/com/dtstack/flink/sql/side/oceanbase/table/OceanbaseSideParser.java b/oceanbase/oceanbase-side/oceanbase-side-core/src/main/java/com/dtstack/flink/sql/side/oceanbase/table/OceanbaseSideParser.java deleted file mode 100644 index aad37ae2f..000000000 --- a/oceanbase/oceanbase-side/oceanbase-side-core/src/main/java/com/dtstack/flink/sql/side/oceanbase/table/OceanbaseSideParser.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.oceanbase.table; - -import com.dtstack.flink.sql.core.rdb.JdbcCheckKeys; -import com.dtstack.flink.sql.side.rdb.table.RdbSideParser; -import com.dtstack.flink.sql.table.AbstractTableInfo; - -import java.util.Map; - -/** - * @author : tiezhu - * @date : 2020/3/26 - */ -public class OceanbaseSideParser extends RdbSideParser { - - private static final String CURRENT_TYPE = "oceanbase"; - - @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { - props.put(JdbcCheckKeys.DRIVER_NAME, "com.mysql.jdbc.Driver"); - AbstractTableInfo oceanbaseTableInfo = super.getTableInfo(tableName, fieldsInfo, props); - oceanbaseTableInfo.setType(CURRENT_TYPE); - return oceanbaseTableInfo; - } -} diff --git a/oceanbase/oceanbase-side/oceanbase-side-core/src/test/java/com/dtstack/flink/sql/side/oceanbase/table/OceanbaseSideParserTest.java b/oceanbase/oceanbase-side/oceanbase-side-core/src/test/java/com/dtstack/flink/sql/side/oceanbase/table/OceanbaseSideParserTest.java deleted file mode 100644 index 3a7804193..000000000 --- a/oceanbase/oceanbase-side/oceanbase-side-core/src/test/java/com/dtstack/flink/sql/side/oceanbase/table/OceanbaseSideParserTest.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.dtstack.flink.sql.side.oceanbase.table; - -import com.dtstack.flink.sql.table.AbstractTableInfo; -import org.junit.Assert; -import org.junit.Test; - -import java.util.HashMap; -import java.util.Map; - -public class OceanbaseSideParserTest { - -// @Test - public void getTableInfo() { - OceanbaseSideParser sideParser = new OceanbaseSideParser(); - - final String tableName = "table_foo"; - final String fieldsInfo = "id INT, name VARCHAR, PRIMARY KEY (id)"; - - Map props = new HashMap(); - props.put("url", "jdbc:mysql://foo:3306/db_foo"); - props.put("tablename", "table_foo"); - props.put("username", "foo"); - props.put("password", "foo"); - - AbstractTableInfo tableInfo= sideParser.getTableInfo(tableName, fieldsInfo, props); - - final String NORMAL_TYPE = "oceanbase"; - final String table_type = tableInfo.getType(); - Assert.assertTrue(NORMAL_TYPE.equals(table_type)); - } - -} \ No newline at end of file diff --git a/oceanbase/oceanbase-side/pom.xml b/oceanbase/oceanbase-side/pom.xml deleted file mode 100644 index ab5fe108d..000000000 --- a/oceanbase/oceanbase-side/pom.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - sql.oceanbase - com.dtstack.flink - 1.0-SNAPSHOT - - 4.0.0 - - sql.side.oceanbase - 1.0-SNAPSHOT - - oceanbase-all-side - oceanbase-async-side - oceanbase-side-core - - oceanbase-side - pom - - - 1.0-SNAPSHOT - - - - - com.dtstack.flink - sql.side.rdb - ${rdb.side.version} - - - - - - com.dtstack.flink - sql.side.rdb - ${rdb.side.version} - test-jar - test - - - - \ No newline at end of file diff --git a/oceanbase/oceanbase-sink/pom.xml b/oceanbase/oceanbase-sink/pom.xml deleted file mode 100644 index 934d2a2ef..000000000 --- a/oceanbase/oceanbase-sink/pom.xml +++ /dev/null @@ -1,90 +0,0 @@ - - - - sql.oceanbase - com.dtstack.flink - 1.0-SNAPSHOT - - 4.0.0 - - sql.sink.oceanbase - jar - oceanbase-sink - - - 1.0-SNAPSHOT - - - - - com.dtstack.flink - sql.sink.rdb - ${sql.sink.rdb.version} - - - - - - - org.apache.maven.plugins - maven-shade-plugin - 1.4 - - - package - - shade - - - - - - - - - - *:* - - META-INF/*.SF - META-INF/*.DSA - META-INF/*.RSA - - - - - - - - - - maven-antrun-plugin - 1.2 - - - copy-resources - - package - - run - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/oceanbase/oceanbase-sink/src/main/java/com/dtstack/flink/sql/sink/oceanbase/OceanbaseDialect.java b/oceanbase/oceanbase-sink/src/main/java/com/dtstack/flink/sql/sink/oceanbase/OceanbaseDialect.java deleted file mode 100644 index e4bda555e..000000000 --- a/oceanbase/oceanbase-sink/src/main/java/com/dtstack/flink/sql/sink/oceanbase/OceanbaseDialect.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.oceanbase; - -import com.dtstack.flink.sql.sink.rdb.dialect.JDBCDialect; - -import java.util.Arrays; -import java.util.Optional; -import java.util.stream.Collectors; - -/** - * @author : tiezhu - * @date : 2020/3/24 - */ -public class OceanbaseDialect implements JDBCDialect { - @Override - public boolean canHandle(String url) { - return url.startsWith("jdbc:mysql:"); - } - - @Override - public Optional defaultDriverName() { - return Optional.of("com.mysql.jdbc.Driver"); - } - - @Override - public String quoteIdentifier(String identifier) { - return "`" + identifier + "`"; - } - - @Override - public Optional getUpsertStatement(String schema, - String tableName, - String[] fieldNames, - String[] uniqueKeyFields, - boolean allReplace) { - return allReplace ? - buildReplaceIntoStatement(tableName, fieldNames) : buildDuplicateUpsertStatement(tableName, fieldNames); - } - - public Optional buildDuplicateUpsertStatement(String tableName, String[] fieldNames) { - String updateClause = Arrays - .stream(fieldNames) - .map(f -> quoteIdentifier(f) + "=IFNULL(VALUES(" + quoteIdentifier(f) + ")," + quoteIdentifier(f) + ")") - .collect(Collectors.joining(", ")); - - return Optional.of(getInsertIntoStatement("", tableName, fieldNames, null) + - " ON DUPLICATE KEY UPDATE " + updateClause - ); - } - - public Optional buildReplaceIntoStatement(String tableName, String[] fieldNames) { - String columns = Arrays - .stream(fieldNames) - .map(this::quoteIdentifier) - .collect(Collectors.joining(", ")); - String placeholders = Arrays - .stream(fieldNames) - .map(f -> "?") - .collect(Collectors.joining(", ")); - return Optional.of("REPLACE INTO " + quoteIdentifier(tableName) + - "(" + columns + ")" + " VALUES (" + placeholders + ")"); - } -} diff --git a/oceanbase/oceanbase-sink/src/main/java/com/dtstack/flink/sql/sink/oceanbase/OceanbaseSink.java b/oceanbase/oceanbase-sink/src/main/java/com/dtstack/flink/sql/sink/oceanbase/OceanbaseSink.java deleted file mode 100644 index ad9bfab3b..000000000 --- a/oceanbase/oceanbase-sink/src/main/java/com/dtstack/flink/sql/sink/oceanbase/OceanbaseSink.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.oceanbase; - -import com.dtstack.flink.sql.sink.IStreamSinkGener; -import com.dtstack.flink.sql.sink.rdb.AbstractRdbSink; -import com.dtstack.flink.sql.sink.rdb.JDBCOptions; -import com.dtstack.flink.sql.sink.rdb.format.JDBCUpsertOutputFormat; - -/** - * @author : tiezhu - * @date : 2020/3/24 - */ -public class OceanbaseSink extends AbstractRdbSink implements IStreamSinkGener { - - public OceanbaseSink() { - super(new OceanbaseDialect()); - } - - @Override - public JDBCUpsertOutputFormat getOutputFormat() { - JDBCOptions oceanbaseOptions = JDBCOptions.builder() - .setDbUrl(dbUrl) - .setDialect(jdbcDialect) - .setUsername(userName) - .setPassword(password) - .setTableName(tableName) - .build(); - - return JDBCUpsertOutputFormat.builder() - .setOptions(oceanbaseOptions) - .setFieldNames(fieldNames) - .setFlushMaxSize(batchNum) - .setFlushIntervalMills(batchWaitInterval) - .setFieldTypes(sqlTypes) - .setKeyFields(primaryKeys) - .setAllReplace(allReplace) - .setUpdateMode(updateMode) - .setErrorLimit(errorLimit) - .build(); - } -} diff --git a/oceanbase/oceanbase-sink/src/main/java/com/dtstack/flink/sql/sink/oceanbase/table/OceanbaseSinkParser.java b/oceanbase/oceanbase-sink/src/main/java/com/dtstack/flink/sql/sink/oceanbase/table/OceanbaseSinkParser.java deleted file mode 100644 index 96b783a6f..000000000 --- a/oceanbase/oceanbase-sink/src/main/java/com/dtstack/flink/sql/sink/oceanbase/table/OceanbaseSinkParser.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.oceanbase.table; - -import com.dtstack.flink.sql.core.rdb.JdbcCheckKeys; -import com.dtstack.flink.sql.sink.rdb.table.RdbSinkParser; -import com.dtstack.flink.sql.table.AbstractTableInfo; - -import java.util.Map; - -/** - * @author : tiezhu - * @date : 2020/3/24 - */ -public class OceanbaseSinkParser extends RdbSinkParser { - - private static final String CURRENT_TYPE = "oceanbase"; - - @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { - props.put(JdbcCheckKeys.DRIVER_NAME, "com.mysql.jdbc.Driver"); - - AbstractTableInfo oceanbaseTableInfo = super.getTableInfo(tableName, fieldsInfo, props); - - oceanbaseTableInfo.setType(CURRENT_TYPE); - - return oceanbaseTableInfo; - } -} diff --git a/oceanbase/oceanbase-sink/src/test/java/com/dtstack/flink/sql/sink/ocean/OceanbaseDialectTest.java b/oceanbase/oceanbase-sink/src/test/java/com/dtstack/flink/sql/sink/ocean/OceanbaseDialectTest.java deleted file mode 100644 index 55f67a399..000000000 --- a/oceanbase/oceanbase-sink/src/test/java/com/dtstack/flink/sql/sink/ocean/OceanbaseDialectTest.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.dtstack.flink.sql.sink.ocean; - -import com.dtstack.flink.sql.sink.oceanbase.OceanbaseDialect; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -public class OceanbaseDialectTest { - - OceanbaseDialect dialect; - - @Before - public void setUp() { - dialect = new OceanbaseDialect(); - } - - @Test - public void testEasyUtils() { - final String s = "jdbc:mysql://localhost:3306/foo_db"; - boolean r = dialect.canHandle(s); - Assert.assertTrue(r); - - String driver = dialect.defaultDriverName().get(); - Assert.assertTrue(driver.equals("com.mysql.jdbc.Driver")); - - final String foo = "foo"; - final String NORMAL_QUOTE = "`foo`"; - String strWithQuote = dialect.quoteIdentifier(foo); - - Assert.assertTrue(strWithQuote.equals(NORMAL_QUOTE)); - } - - @Test - public void testDialect() { - final String tableName = "table_foo"; - final String[] fieldNames = new String[] { - "id", - "name" - }; - final String NORMAL_REPELACE_STMT = - "REPLACE INTO `table_foo`(`id`,`name`) VALUES (?,?)"; - final String NORMAL_UPSERT_STMT = - "INSERT INTO `table_foo`(`id`, `name`) VALUES (?, ?) ON DUPLICATE KEY UPDATE `id`IFNULL(VALUES(`id`),`id`),`name`IFNULL(VALUES(`name`),`name`)"; - - String upsertStmtWithReplace = dialect - .getUpsertStatement("", tableName, fieldNames, null, true) - .get(); - String upsertStmtWithoutReplace = dialect - .getUpsertStatement("", tableName, fieldNames, null, false) - .get(); - //TODO 待修复 -// Assert.assertTrue(NORMAL_REPELACE_STMT.equals(upsertStmtWithReplace)); -// Assert.assertTrue(NORMAL_UPSERT_STMT.equals(upsertStmtWithoutReplace)); - } - -} \ No newline at end of file diff --git a/oceanbase/oceanbase-sink/src/test/java/com/dtstack/flink/sql/sink/ocean/OceanbaseSinkTest.java b/oceanbase/oceanbase-sink/src/test/java/com/dtstack/flink/sql/sink/ocean/OceanbaseSinkTest.java deleted file mode 100644 index 92aa5ce1f..000000000 --- a/oceanbase/oceanbase-sink/src/test/java/com/dtstack/flink/sql/sink/ocean/OceanbaseSinkTest.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.dtstack.flink.sql.sink.ocean; - -import com.dtstack.flink.sql.sink.oceanbase.OceanbaseSink; -import com.dtstack.flink.sql.sink.rdb.dialect.JDBCDialect; -import com.dtstack.flink.sql.sink.rdb.format.JDBCUpsertOutputFormat; -import org.junit.Before; -import org.junit.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.powermock.api.support.membermodification.MemberModifier; - -import java.util.Optional; - -import static org.mockito.Mockito.when; - -public class OceanbaseSinkTest { - - @Mock - JDBCDialect jdbcDialect; - - @InjectMocks - OceanbaseSink sink = new OceanbaseSink();; - @Before - public void setUp () { - MockitoAnnotations.initMocks(this); - } - - @Test - public void testGetOutputFormat() throws IllegalAccessException { - when(jdbcDialect.defaultDriverName()).thenReturn(Optional.of("dd")); - - MemberModifier.field(OceanbaseSink.class, "dbUrl").set(sink, "foo"); - MemberModifier.field(OceanbaseSink.class, "jdbcDialect").set(sink, jdbcDialect); - MemberModifier.field(OceanbaseSink.class, "userName").set(sink, "foo"); - MemberModifier.field(OceanbaseSink.class, "password").set(sink, "foo"); - MemberModifier.field(OceanbaseSink.class, "tableName").set(sink, "foo"); - MemberModifier.field(OceanbaseSink.class, "fieldNames").set(sink, new String[]{"foo", "bar"}); - - JDBCUpsertOutputFormat format = sink.getOutputFormat(); - } - -} \ No newline at end of file diff --git a/oceanbase/oceanbase-sink/src/test/java/com/dtstack/flink/sql/sink/ocean/table/OceanbaseSinkParserTest.java b/oceanbase/oceanbase-sink/src/test/java/com/dtstack/flink/sql/sink/ocean/table/OceanbaseSinkParserTest.java deleted file mode 100644 index ae5a889b7..000000000 --- a/oceanbase/oceanbase-sink/src/test/java/com/dtstack/flink/sql/sink/ocean/table/OceanbaseSinkParserTest.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.dtstack.flink.sql.sink.ocean.table; - -import com.dtstack.flink.sql.sink.oceanbase.table.OceanbaseSinkParser; -import com.dtstack.flink.sql.table.AbstractTableInfo; -import org.junit.Assert; -import org.junit.Test; - -import java.util.HashMap; -import java.util.Map; - -public class OceanbaseSinkParserTest { - -// @Test - public void getTableInfo() { - OceanbaseSinkParser sideParser = new OceanbaseSinkParser(); - - final String tableName = "table_foo"; - final String fieldsInfo = "id INT, name VARCHAR"; - - Map props = new HashMap(); - props.put("url", "jdbc:mysql://foo:3306/db_foo"); - props.put("tablename", "table_foo"); - props.put("username", "foo"); - props.put("password", "foo"); - - AbstractTableInfo tableInfo= sideParser.getTableInfo(tableName, fieldsInfo, props); - - final String NORMAL_TYPE = "oceanbase"; - final String table_type = tableInfo.getType(); - Assert.assertTrue(NORMAL_TYPE.equals(table_type)); - } - -} \ No newline at end of file diff --git a/oceanbase/pom.xml b/oceanbase/pom.xml deleted file mode 100644 index 8b7c8bc36..000000000 --- a/oceanbase/pom.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - flink.sql - com.dtstack.flink - 1.0-SNAPSHOT - - 4.0.0 - - sql.oceanbase - pom - - oceanbase-sink - oceanbase-side - - - - 5.1.40 - 1.0-SNAPSHOT - - - - - com.dtstack.flink - sql.core - ${sql.core.version} - provided - - - - mysql - mysql-connector-java - ${mysql.connector.version} - - - - - \ No newline at end of file diff --git a/oracle/oracle-side/oracle-all-side/pom.xml b/oracle/oracle-side/oracle-all-side/pom.xml index 1a7c853e3..0685549c4 100644 --- a/oracle/oracle-side/oracle-all-side/pom.xml +++ b/oracle/oracle-side/oracle-all-side/pom.xml @@ -40,7 +40,6 @@ shade - false @@ -74,14 +73,14 @@ - + - + diff --git a/oracle/oracle-side/oracle-all-side/src/main/java/com/dtstack/flink/sql/side/oracle/OracleAllReqRow.java b/oracle/oracle-side/oracle-all-side/src/main/java/com/dtstack/flink/sql/side/oracle/OracleAllReqRow.java index 3be6687ec..18d9ba045 100644 --- a/oracle/oracle-side/oracle-all-side/src/main/java/com/dtstack/flink/sql/side/oracle/OracleAllReqRow.java +++ b/oracle/oracle-side/oracle-all-side/src/main/java/com/dtstack/flink/sql/side/oracle/OracleAllReqRow.java @@ -20,8 +20,8 @@ import com.dtstack.flink.sql.side.FieldInfo; import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.rdb.all.AbstractRdbAllReqRow; +import com.dtstack.flink.sql.side.SideTableInfo; +import com.dtstack.flink.sql.side.rdb.all.RdbAllReqRow; import com.dtstack.flink.sql.util.DtStringUtil; import org.apache.flink.api.java.typeutils.RowTypeInfo; import com.google.common.collect.Maps; @@ -36,22 +36,22 @@ /** * side operator with cache for all(period reload) */ -public class OracleAllReqRow extends AbstractRdbAllReqRow { +public class OracleAllReqRow extends RdbAllReqRow { private static final Logger LOG = LoggerFactory.getLogger(OracleAllReqRow.class); private static final String ORACLE_DRIVER = "oracle.jdbc.driver.OracleDriver"; - public OracleAllReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { + public OracleAllReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, SideTableInfo sideTableInfo) { super(new OracleAllSideInfo(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo)); } @Override - public Connection getConn(String dbUrl, String userName, String password) { + public Connection getConn(String dbURL, String userName, String password) { try { Class.forName(ORACLE_DRIVER); Map addParams = Maps.newHashMap(); - String targetDbUrl = DtStringUtil.addJdbcParam(dbUrl, addParams, true); + String targetDbUrl = DtStringUtil.addJdbcParam(dbURL, addParams, true); return DriverManager.getConnection(targetDbUrl, userName, password); } catch (Exception e) { LOG.error("", e); diff --git a/oracle/oracle-side/oracle-all-side/src/main/java/com/dtstack/flink/sql/side/oracle/OracleAllSideInfo.java b/oracle/oracle-side/oracle-all-side/src/main/java/com/dtstack/flink/sql/side/oracle/OracleAllSideInfo.java index 342533681..914a57aef 100644 --- a/oracle/oracle-side/oracle-all-side/src/main/java/com/dtstack/flink/sql/side/oracle/OracleAllSideInfo.java +++ b/oracle/oracle-side/oracle-all-side/src/main/java/com/dtstack/flink/sql/side/oracle/OracleAllSideInfo.java @@ -19,27 +19,42 @@ import com.dtstack.flink.sql.side.FieldInfo; import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; +import com.dtstack.flink.sql.side.SideTableInfo; import com.dtstack.flink.sql.side.rdb.all.RdbAllSideInfo; import com.dtstack.flink.sql.side.rdb.table.RdbSideTableInfo; import com.dtstack.flink.sql.util.DtStringUtil; +import org.apache.commons.lang3.StringUtils; import org.apache.flink.api.java.typeutils.RowTypeInfo; import java.util.List; public class OracleAllSideInfo extends RdbAllSideInfo { - public OracleAllSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { + public OracleAllSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, SideTableInfo sideTableInfo) { super(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); } @Override - public String getTableName(RdbSideTableInfo rdbSideTableInfo) { - return DtStringUtil.getTableFullPath(rdbSideTableInfo.getSchema(), rdbSideTableInfo.getTableName()); + public void buildEqualInfo(JoinInfo joinInfo, SideTableInfo sideTableInfo) { + RdbSideTableInfo rdbSideTableInfo = (RdbSideTableInfo) sideTableInfo; + + sqlCondition = "select ${selectField} from ${tableName} "; + + + sqlCondition = sqlCondition.replace("${tableName}", DtStringUtil.getTableFullPath(rdbSideTableInfo.getSchema(), rdbSideTableInfo.getTableName())).replace("${selectField}", dealLowerSelectFiled(sideSelectFields)); + System.out.println("---------side_exe_sql-----\n" + sqlCondition); } - @Override - public String quoteIdentifier(String identifier) { - return "\"" + identifier + "\""; + + private String dealLowerSelectFiled(String fieldsStr) { + StringBuilder sb = new StringBuilder(); + String[] fields = fieldsStr.split(","); + + for(String f : fields) { + sb.append("\"").append(f).append("\"").append(","); + } + + sb.deleteCharAt(sb.lastIndexOf(",")); + return sb.toString(); } } diff --git a/oracle/oracle-side/oracle-all-side/src/test/java/com/dtstack/flink/sql/side/oracle/OracleAllReqRowTest.java b/oracle/oracle-side/oracle-all-side/src/test/java/com/dtstack/flink/sql/side/oracle/OracleAllReqRowTest.java deleted file mode 100644 index 3164667a5..000000000 --- a/oracle/oracle-side/oracle-all-side/src/test/java/com/dtstack/flink/sql/side/oracle/OracleAllReqRowTest.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.dtstack.flink.sql.side.oracle; - -import com.dtstack.flink.sql.side.rdb.all.RdbAllReqRowTestBase; -import org.junit.Before; -import org.junit.Test; -import org.powermock.reflect.Whitebox; - -import static org.junit.Assert.*; - -public class OracleAllReqRowTest extends RdbAllReqRowTestBase { - - @Override - protected void init() { - clazz = OracleAllReqRow.class; - } - -} \ No newline at end of file diff --git a/oracle/oracle-side/oracle-async-side/pom.xml b/oracle/oracle-side/oracle-async-side/pom.xml index db0587d19..ba227fd1e 100644 --- a/oracle/oracle-side/oracle-async-side/pom.xml +++ b/oracle/oracle-side/oracle-async-side/pom.xml @@ -39,7 +39,6 @@ shade - false @@ -73,14 +72,14 @@ - + - + diff --git a/oracle/oracle-side/oracle-async-side/src/main/java/com/dtstack/flink/sql/side/oracle/OracleAsyncReqRow.java b/oracle/oracle-side/oracle-async-side/src/main/java/com/dtstack/flink/sql/side/oracle/OracleAsyncReqRow.java index c6eee416c..f973ffee2 100644 --- a/oracle/oracle-side/oracle-async-side/src/main/java/com/dtstack/flink/sql/side/oracle/OracleAsyncReqRow.java +++ b/oracle/oracle-side/oracle-async-side/src/main/java/com/dtstack/flink/sql/side/oracle/OracleAsyncReqRow.java @@ -19,43 +19,55 @@ package com.dtstack.flink.sql.side.oracle; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; import com.dtstack.flink.sql.side.FieldInfo; import com.dtstack.flink.sql.side.JoinInfo; +import com.dtstack.flink.sql.side.SideTableInfo; import com.dtstack.flink.sql.side.rdb.async.RdbAsyncReqRow; import com.dtstack.flink.sql.side.rdb.table.RdbSideTableInfo; +import io.vertx.core.Vertx; +import io.vertx.core.VertxOptions; import io.vertx.core.json.JsonObject; +import io.vertx.ext.jdbc.JDBCClient; import org.apache.flink.api.java.typeutils.RowTypeInfo; import org.apache.flink.configuration.Configuration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.List; public class OracleAsyncReqRow extends RdbAsyncReqRow { + + private static final Logger LOG = LoggerFactory.getLogger(OracleAsyncReqRow.class); + private static final String ORACLE_DRIVER = "oracle.jdbc.driver.OracleDriver"; - public OracleAsyncReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { + public OracleAsyncReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, SideTableInfo sideTableInfo) { super(new OracleAsyncSideInfo(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo)); } @Override public void open(Configuration parameters) throws Exception { super.open(parameters); - } - - @Override - public JsonObject buildJdbcConfig() { JsonObject oracleClientConfig = new JsonObject(); RdbSideTableInfo rdbSideTableInfo = (RdbSideTableInfo) sideInfo.getSideTableInfo(); oracleClientConfig.put("url", rdbSideTableInfo.getUrl()) .put("driver_class", ORACLE_DRIVER) - .put("max_pool_size", rdbSideTableInfo.getAsyncPoolSize()) + .put("max_pool_size", DEFAULT_MAX_DB_CONN_POOL_SIZE) .put("user", rdbSideTableInfo.getUserName()) .put("password", rdbSideTableInfo.getPassword()) .put("provider_class", DT_PROVIDER_CLASS) - .put("preferred_test_query", "select 1 from dual") + .put("preferred_test_query", PREFERRED_TEST_QUERY_SQL) .put("idle_connection_test_period", DEFAULT_IDLE_CONNECTION_TEST_PEROID) .put("test_connection_on_checkin", DEFAULT_TEST_CONNECTION_ON_CHECKIN); - return oracleClientConfig; + + System.setProperty("vertx.disableFileCPResolving", "true"); + + VertxOptions vo = new VertxOptions(); + vo.setEventLoopPoolSize(DEFAULT_VERTX_EVENT_LOOP_POOL_SIZE); + vo.setWorkerPoolSize(DEFAULT_VERTX_WORKER_POOL_SIZE); + vo.setFileResolverCachingEnabled(false); + Vertx vertx = Vertx.vertx(vo); + setRdbSQLClient(JDBCClient.createNonShared(vertx, oracleClientConfig)); } } diff --git a/oracle/oracle-side/oracle-async-side/src/main/java/com/dtstack/flink/sql/side/oracle/OracleAsyncSideInfo.java b/oracle/oracle-side/oracle-async-side/src/main/java/com/dtstack/flink/sql/side/oracle/OracleAsyncSideInfo.java index 658020b1c..c9d2f98d9 100644 --- a/oracle/oracle-side/oracle-async-side/src/main/java/com/dtstack/flink/sql/side/oracle/OracleAsyncSideInfo.java +++ b/oracle/oracle-side/oracle-async-side/src/main/java/com/dtstack/flink/sql/side/oracle/OracleAsyncSideInfo.java @@ -20,48 +20,72 @@ import com.dtstack.flink.sql.side.FieldInfo; import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; +import com.dtstack.flink.sql.side.SideTableInfo; import com.dtstack.flink.sql.side.rdb.async.RdbAsyncSideInfo; import com.dtstack.flink.sql.side.rdb.table.RdbSideTableInfo; -import com.dtstack.flink.sql.table.AbstractTableInfo; import com.dtstack.flink.sql.util.DtStringUtil; -import org.apache.commons.lang3.StringUtils; +import com.dtstack.flink.sql.util.ParseUtils; +import org.apache.calcite.sql.SqlNode; import org.apache.flink.api.java.typeutils.RowTypeInfo; +import com.google.common.collect.Lists; import java.util.List; public class OracleAsyncSideInfo extends RdbAsyncSideInfo { - public OracleAsyncSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { + public OracleAsyncSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, SideTableInfo sideTableInfo) { super(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); } @Override - public String getTableName(RdbSideTableInfo rdbSideTableInfo) { - return DtStringUtil.getTableFullPath(rdbSideTableInfo.getSchema(), rdbSideTableInfo.getTableName()); + public void buildEqualInfo(JoinInfo joinInfo, SideTableInfo sideTableInfo) { + RdbSideTableInfo rdbSideTableInfo = (RdbSideTableInfo) sideTableInfo; + + String sideTableName = joinInfo.getSideTableName(); + + SqlNode conditionNode = joinInfo.getCondition(); + + List sqlNodeList = Lists.newArrayList(); + List sqlJoinCompareOperate= Lists.newArrayList(); + + ParseUtils.parseAnd(conditionNode, sqlNodeList); + ParseUtils.parseJoinCompareOperate(conditionNode, sqlJoinCompareOperate); + + + for (SqlNode sqlNode : sqlNodeList) { + dealOneEqualCon(sqlNode, sideTableName); + } + + sqlCondition = "select ${selectField} from ${tableName} where "; + for (int i = 0; i < equalFieldList.size(); i++) { + String equalField = sideTableInfo.getPhysicalFields().getOrDefault(equalFieldList.get(i), equalFieldList.get(i)); + sqlCondition += dealLowerFiled(equalField) + " " + sqlJoinCompareOperate.get(i) + " " + " ?"; + if (i != equalFieldList.size() - 1) { + sqlCondition += " and "; + } + } + + sqlCondition = sqlCondition.replace("${tableName}", DtStringUtil.getTableFullPath(rdbSideTableInfo.getSchema(), rdbSideTableInfo.getTableName())).replace("${selectField}", dealLowerSelectFiled(sideSelectFields)); + System.out.println("---------side_exe_sql-----\n" + sqlCondition); } - @Override - public String quoteIdentifier(String identifier) { - return "\"" + identifier + "\""; + + + private String dealLowerFiled(String field) { + return "\"" + field + "\""; } - @Override - public String wrapperPlaceholder(String fieldName) { - int pos = sideTableInfo.getFieldList().indexOf(fieldName); - String type = sideTableInfo.getFieldTypeList().get(pos); - - String sqlDefaultPlaceholder = " ? "; - String rpadFormat = "rpad(?, %d, ' ')"; - - if (StringUtils.contains(type.toLowerCase(), "char")) { - AbstractTableInfo.FieldExtraInfo fieldExtraInfo = sideTableInfo.getFieldExtraInfoList().get(pos); - int charLength = fieldExtraInfo == null ? 0 : fieldExtraInfo.getLength(); - if (charLength > 0) { - return String.format(rpadFormat, charLength); - } + private String dealLowerSelectFiled(String fieldsStr) { + StringBuilder sb = new StringBuilder(); + String[] fields = fieldsStr.split(","); + + for(String f : fields) { + sb.append("\"").append(f).append("\"").append(","); } - return sqlDefaultPlaceholder; + + sb.deleteCharAt(sb.lastIndexOf(",")); + return sb.toString(); } + } diff --git a/oracle/oracle-side/oracle-async-side/src/test/java/com/dtstack/flink/sql/side/oracle/OracleAsyncReqRowTest.java b/oracle/oracle-side/oracle-async-side/src/test/java/com/dtstack/flink/sql/side/oracle/OracleAsyncReqRowTest.java deleted file mode 100644 index 7a40afaef..000000000 --- a/oracle/oracle-side/oracle-async-side/src/test/java/com/dtstack/flink/sql/side/oracle/OracleAsyncReqRowTest.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.dtstack.flink.sql.side.oracle; - -import com.dtstack.flink.sql.side.rdb.async.RdbAsyncReqRowTestBase; - -public class OracleAsyncReqRowTest extends RdbAsyncReqRowTestBase { - - @Override - protected void init() { - clazz = OracleAsyncReqRow.class; - } - -} \ No newline at end of file diff --git a/oracle/oracle-side/oracle-async-side/src/test/java/com/dtstack/flink/sql/side/oracle/OracleAsyncSideInfoTest.java b/oracle/oracle-side/oracle-async-side/src/test/java/com/dtstack/flink/sql/side/oracle/OracleAsyncSideInfoTest.java deleted file mode 100644 index 837b6ca8c..000000000 --- a/oracle/oracle-side/oracle-async-side/src/test/java/com/dtstack/flink/sql/side/oracle/OracleAsyncSideInfoTest.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.dtstack.flink.sql.side.oracle; - -import com.dtstack.flink.sql.side.rdb.table.RdbSideTableInfo; -import com.dtstack.flink.sql.table.AbstractTableInfo; -import org.junit.Assert; -import org.junit.Test; -import org.powermock.reflect.Whitebox; - -public class OracleAsyncSideInfoTest { - - @Test - public void testWrapperPlaceholder() { - RdbSideTableInfo tableInfo = new RdbSideTableInfo(); - String fieldName = "TEST_name"; - String type = "char"; - tableInfo.addField(fieldName); - tableInfo.addFieldType(type); - - AbstractTableInfo.FieldExtraInfo extraInfo = new AbstractTableInfo.FieldExtraInfo(); - extraInfo.setLength(4); - tableInfo.addFieldExtraInfo(extraInfo); - - OracleAsyncSideInfo sideInfo = Whitebox.newInstance(OracleAsyncSideInfo.class); - Whitebox.setInternalState(sideInfo, "sideTableInfo", tableInfo); - - String placeholder = sideInfo.wrapperPlaceholder(fieldName); - Assert.assertEquals("rpad(?, 4, ' ')", placeholder); - } - -} \ No newline at end of file diff --git a/oracle/oracle-side/oracle-side-core/src/main/java/com/dtstack/flink/sql/side/oracle/table/OracleSideParser.java b/oracle/oracle-side/oracle-side-core/src/main/java/com/dtstack/flink/sql/side/oracle/table/OracleSideParser.java index 59fdd795d..f9124bd10 100644 --- a/oracle/oracle-side/oracle-side-core/src/main/java/com/dtstack/flink/sql/side/oracle/table/OracleSideParser.java +++ b/oracle/oracle-side/oracle-side-core/src/main/java/com/dtstack/flink/sql/side/oracle/table/OracleSideParser.java @@ -17,9 +17,8 @@ */ package com.dtstack.flink.sql.side.oracle.table; -import com.dtstack.flink.sql.core.rdb.JdbcCheckKeys; import com.dtstack.flink.sql.side.rdb.table.RdbSideParser; -import com.dtstack.flink.sql.table.AbstractTableInfo; +import com.dtstack.flink.sql.table.TableInfo; import java.util.Map; @@ -28,9 +27,8 @@ public class OracleSideParser extends RdbSideParser { private static final String CURR_TYPE = "oracle"; @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { - props.put(JdbcCheckKeys.DRIVER_NAME, "oracle.jdbc.driver.OracleDriver"); - AbstractTableInfo oracleTableInfo = super.getTableInfo(tableName, fieldsInfo, props); + public TableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { + TableInfo oracleTableInfo = super.getTableInfo(tableName, fieldsInfo, props); oracleTableInfo.setType(CURR_TYPE); return oracleTableInfo; } diff --git a/oracle/oracle-side/oracle-side-core/src/test/java/com/dtstack/flink/sql/side/oracle/table/OracleSideParserTest.java b/oracle/oracle-side/oracle-side-core/src/test/java/com/dtstack/flink/sql/side/oracle/table/OracleSideParserTest.java deleted file mode 100644 index 3445b7084..000000000 --- a/oracle/oracle-side/oracle-side-core/src/test/java/com/dtstack/flink/sql/side/oracle/table/OracleSideParserTest.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.dtstack.flink.sql.side.oracle.table; - -import com.dtstack.flink.sql.table.AbstractTableInfo; -import org.junit.Assert; -import org.junit.Test; - -import java.util.HashMap; -import java.util.Map; - -import static org.junit.Assert.*; - -public class OracleSideParserTest { - -// @Test - public void getTableInfo() { - OracleSideParser sideParser = new OracleSideParser(); - - final String tableName = "table_foo"; - final String fieldsInfo = "id INT, name VARCHAR, PRIMARY KEY (id)"; - - Map props = new HashMap(); - props.put("url", "jdbc:mysql://foo:3306/db_foo"); - props.put("tablename", "table_foo"); - props.put("username", "foo"); - props.put("password", "foo"); - - AbstractTableInfo tableInfo= sideParser.getTableInfo(tableName, fieldsInfo, props); - - final String NORMAL_TYPE = "oracle"; - final String table_type = tableInfo.getType(); - Assert.assertTrue(NORMAL_TYPE.equals(table_type)); - } - -} \ No newline at end of file diff --git a/oracle/oracle-side/pom.xml b/oracle/oracle-side/pom.xml index 7da390027..e0ffe547b 100644 --- a/oracle/oracle-side/pom.xml +++ b/oracle/oracle-side/pom.xml @@ -29,15 +29,5 @@ sql.side.rdb ${rdb.side.version} - - - - - com.dtstack.flink - sql.side.rdb - ${rdb.side.version} - test-jar - test - \ No newline at end of file diff --git a/oracle/oracle-sink/pom.xml b/oracle/oracle-sink/pom.xml index 32b3beccf..7bd52ec72 100644 --- a/oracle/oracle-sink/pom.xml +++ b/oracle/oracle-sink/pom.xml @@ -39,7 +39,6 @@ shade - false @@ -73,14 +72,14 @@ - + - + diff --git a/oracle/oracle-sink/src/main/java/com/dtstack/flink/sql/sink/oracle/OracleDialect.java b/oracle/oracle-sink/src/main/java/com/dtstack/flink/sql/sink/oracle/OracleDialect.java deleted file mode 100644 index 590ecc7a1..000000000 --- a/oracle/oracle-sink/src/main/java/com/dtstack/flink/sql/sink/oracle/OracleDialect.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.oracle; - -import com.dtstack.flink.sql.sink.rdb.dialect.JDBCDialect; -import com.dtstack.flink.sql.table.AbstractTableInfo; -import com.dtstack.flink.sql.util.DtStringUtil; -import org.apache.commons.lang3.StringUtils; - -import java.util.Arrays; -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; - -/** - * Date: 2020/1/3 - * Company: www.dtstack.com - * @author maqi - */ -public class OracleDialect implements JDBCDialect { - - private final String SQL_DEFAULT_PLACEHOLDER = " ? "; - private final String DEAL_CHAR_KEY = "char"; - private String RPAD_FORMAT = " rpad(?, %d, ' ') "; - - private List fieldList; - private List fieldTypeList; - private List fieldExtraInfoList; - - @Override - public boolean canHandle(String url) { - return url.startsWith("jdbc:oracle:"); - } - - @Override - public Optional defaultDriverName() { - return Optional.of("oracle.jdbc.driver.OracleDriver"); - } - - @Override - public Optional getUpsertStatement(String schema, String tableName, String[] fieldNames, String[] uniqueKeyFields, boolean allReplace) { - tableName = DtStringUtil.getTableFullPath(schema, tableName); - StringBuilder mergeIntoSql = new StringBuilder(); - mergeIntoSql.append("MERGE INTO " + tableName + " T1 USING (") - .append(buildDualQueryStatement(fieldNames)) - .append(") T2 ON (") - .append(buildConnectionConditions(uniqueKeyFields) + ") "); - - String updateSql = buildUpdateConnection(fieldNames, uniqueKeyFields, allReplace); - - if (StringUtils.isNotEmpty(updateSql)) { - mergeIntoSql.append(" WHEN MATCHED THEN UPDATE SET "); - mergeIntoSql.append(updateSql); - } - - mergeIntoSql.append(" WHEN NOT MATCHED THEN ") - .append("INSERT (") - .append(Arrays.stream(fieldNames).map(this::quoteIdentifier).collect(Collectors.joining(","))) - .append(") VALUES (") - .append(Arrays.stream(fieldNames).map(col -> "T2." + quoteIdentifier(col)).collect(Collectors.joining(","))) - .append(")"); - - return Optional.of(mergeIntoSql.toString()); - } - - /** - * build T1."A"=T2."A" or T1."A"=nvl(T2."A",T1."A") - * @param fieldNames - * @param uniqueKeyFields - * @param allReplace - * @return - */ - private String buildUpdateConnection(String[] fieldNames, String[] uniqueKeyFields, boolean allReplace) { - List uniqueKeyList = Arrays.asList(uniqueKeyFields); - String updateConnectionSql = Arrays.stream(fieldNames). - filter(col -> !uniqueKeyList.contains(col)) - .map(col -> buildConnectionByAllReplace(allReplace, col)) - .collect(Collectors.joining(",")); - return updateConnectionSql; - } - - private String buildConnectionByAllReplace(boolean allReplace, String col) { - String conncetionSql = allReplace ? quoteIdentifier("T1") + "." + quoteIdentifier(col) + " = " + quoteIdentifier("T2") + "." + quoteIdentifier(col) : - quoteIdentifier("T1") + "." + quoteIdentifier(col) + " =nvl(" + quoteIdentifier("T2") + "." + quoteIdentifier(col) + "," - + quoteIdentifier("T1") + "." + quoteIdentifier(col) + ")"; - return conncetionSql; - } - - - private String buildConnectionConditions(String[] uniqueKeyFields) { - return Arrays.stream(uniqueKeyFields).map(col -> "T1." + quoteIdentifier(col) + "=T2." + quoteIdentifier(col)).collect(Collectors.joining(" AND ")); - } - - /** - * build select sql , such as (SELECT ? "A",? "B" FROM DUAL) - * - * @param column destination column - * @return - */ - public String buildDualQueryStatement(String[] column) { - StringBuilder sb = new StringBuilder("SELECT "); - String collect = Arrays.stream(column) - .map(col -> wrapperPlaceholder(col) + quoteIdentifier(col)) - .collect(Collectors.joining(", ")); - sb.append(collect).append(" FROM DUAL"); - return sb.toString(); - } - - - /** - * char type is wrapped with rpad - * @param fieldName - * @return - */ - public String wrapperPlaceholder(String fieldName) { - int pos = fieldList.indexOf(fieldName); - String type = fieldTypeList.get(pos); - - if (StringUtils.contains(type.toLowerCase(), DEAL_CHAR_KEY)) { - AbstractTableInfo.FieldExtraInfo fieldExtraInfo = fieldExtraInfoList.get(pos); - int charLength = fieldExtraInfo == null ? 0 : fieldExtraInfo.getLength(); - if (charLength > 0) { - return String.format(RPAD_FORMAT, charLength); - } - } - return SQL_DEFAULT_PLACEHOLDER; - } - - - public void setFieldList(List fieldList) { - this.fieldList = fieldList; - } - - public void setFieldTypeList(List fieldTypeList) { - this.fieldTypeList = fieldTypeList; - } - - public void setFieldExtraInfoList(List fieldExtraInfoList) { - this.fieldExtraInfoList = fieldExtraInfoList; - } -} diff --git a/oracle/oracle-sink/src/main/java/com/dtstack/flink/sql/sink/oracle/OracleSink.java b/oracle/oracle-sink/src/main/java/com/dtstack/flink/sql/sink/oracle/OracleSink.java index 64b9569b1..c30dc9c60 100644 --- a/oracle/oracle-sink/src/main/java/com/dtstack/flink/sql/sink/oracle/OracleSink.java +++ b/oracle/oracle-sink/src/main/java/com/dtstack/flink/sql/sink/oracle/OracleSink.java @@ -18,9 +18,17 @@ package com.dtstack.flink.sql.sink.oracle; import com.dtstack.flink.sql.sink.IStreamSinkGener; -import com.dtstack.flink.sql.sink.rdb.JDBCOptions; -import com.dtstack.flink.sql.sink.rdb.AbstractRdbSink; -import com.dtstack.flink.sql.sink.rdb.format.JDBCUpsertOutputFormat; +import com.dtstack.flink.sql.sink.rdb.RdbSink; +import com.dtstack.flink.sql.sink.rdb.format.ExtendOutputFormat; +import com.dtstack.flink.sql.sink.rdb.format.RetractJDBCOutputFormat; +import com.dtstack.flink.sql.util.DtStringUtil; +import org.apache.commons.lang3.StringUtils; +import com.google.common.collect.Lists; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; /** * Reason: @@ -29,37 +37,181 @@ * * @author maqi */ -public class OracleSink extends AbstractRdbSink implements IStreamSinkGener { +public class OracleSink extends RdbSink implements IStreamSinkGener { + private static final String ORACLE_DRIVER = "oracle.jdbc.driver.OracleDriver"; + + @Override + public String getDriverName() { + return ORACLE_DRIVER; + } - public OracleSink() { - super(new OracleDialect()); + @Override + public RetractJDBCOutputFormat getOutputFormat() { + return new ExtendOutputFormat(); } @Override - public JDBCUpsertOutputFormat getOutputFormat() { - ((OracleDialect) jdbcDialect).setFieldList(fieldList); - ((OracleDialect) jdbcDialect).setFieldTypeList(fieldTypeList); - ((OracleDialect) jdbcDialect).setFieldExtraInfoList(fieldExtraInfoList); - - JDBCOptions jdbcOptions = JDBCOptions.builder() - .setDbUrl(dbUrl) - .setDialect(jdbcDialect) - .setUsername(userName) - .setPassword(password) - .setTableName(tableName) - .setSchema(schema) - .build(); - - return JDBCUpsertOutputFormat.builder() - .setOptions(jdbcOptions) - .setFieldNames(fieldNames) - .setFlushMaxSize(batchNum) - .setFlushIntervalMills(batchWaitInterval) - .setFieldTypes(sqlTypes) - .setKeyFields(primaryKeys) - .setAllReplace(allReplace) - .setUpdateMode(updateMode) - .setErrorLimit(errorLimit) - .build(); + public void buildSql(String scheam, String tableName, List fields) { + buildInsertSql(scheam, tableName, fields); } + + private void buildInsertSql(String scheam, String tableName, List fields) { + + tableName = DtStringUtil.getTableFullPath(scheam,tableName); + + String sqlTmp = "insert into " + tableName + " (${fields}) values (${placeholder})"; + + List adaptFields = Lists.newArrayList(); + fields.forEach(field -> adaptFields.add(DtStringUtil.addQuoteForStr(field))); + + String fieldsStr = StringUtils.join(adaptFields, ","); + String placeholder = ""; + + for (String fieldName : fields) { + placeholder += ",?"; + } + placeholder = placeholder.replaceFirst(",", ""); + sqlTmp = sqlTmp.replace("${fields}", fieldsStr).replace("${placeholder}", placeholder); + this.sql = sqlTmp; + } + + /** + * use MERGE INTO build oracle replace into sql + * @param tableName + * @param fieldNames create table contained column columns + * @param realIndexes + * @param fullField real columns , query from db + * @return + */ + @Override + public String buildUpdateSql(String scheam, String tableName, List fieldNames, Map> realIndexes, List fullField) { + tableName = DtStringUtil.getTableFullPath(scheam, tableName); + + StringBuilder sb = new StringBuilder(); + + sb.append("MERGE INTO " + tableName + " T1 USING " + + "(" + makeValues(fieldNames) + ") T2 ON (" + + updateKeySql(realIndexes) + ") "); + + + String updateSql = getUpdateSql(fieldNames, fullField, "T1", "T2", keyColList(realIndexes)); + + if (StringUtils.isNotEmpty(updateSql)) { + sb.append(" WHEN MATCHED THEN UPDATE SET "); + sb.append(updateSql); + } + + sb.append(" WHEN NOT MATCHED THEN " + + "INSERT (" + quoteColumns(fieldNames) + ") VALUES (" + + quoteColumns(fieldNames, "T2") + ")"); + + return sb.toString(); + } + + + public String quoteColumns(List column) { + return quoteColumns(column, null); + } + + public String quoteColumns(List column, String table) { + String prefix = StringUtils.isBlank(table) ? "" : DtStringUtil.addQuoteForStr(table) + "."; + List list = new ArrayList<>(); + for (String col : column) { + list.add(prefix + DtStringUtil.addQuoteForStr(col)); + } + return StringUtils.join(list, ","); + } + + /** + * extract all distinct index column + * @param realIndexes + * @return + */ + protected List keyColList(Map> realIndexes) { + List keyCols = new ArrayList<>(); + for (Map.Entry> entry : realIndexes.entrySet()) { + List list = entry.getValue(); + for (String col : list) { + if (!containsIgnoreCase(keyCols,col)) { + keyCols.add(col); + } + } + } + return keyCols; + } + + /** + * build update sql , such as UPDATE SET "T1".A="T2".A + * @param updateColumn create table contained column columns + * @param fullColumn real columns , query from db + * @param leftTable alias + * @param rightTable alias + * @param indexCols index column + * @return + */ + public String getUpdateSql(List updateColumn, List fullColumn, String leftTable, String rightTable, List indexCols) { + String prefixLeft = StringUtils.isBlank(leftTable) ? "" : DtStringUtil.addQuoteForStr(leftTable) + "."; + String prefixRight = StringUtils.isBlank(rightTable) ? "" : DtStringUtil.addQuoteForStr(rightTable) + "."; + List list = new ArrayList<>(); + for (String col : fullColumn) { + // filter index column + if (indexCols == null || indexCols.size() == 0 || containsIgnoreCase(indexCols,col)) { + continue; + } + if (containsIgnoreCase(updateColumn,col)) { + list.add(prefixLeft + DtStringUtil.addQuoteForStr(col) + "=" + prefixRight + DtStringUtil.addQuoteForStr(col)); + } else { + list.add(prefixLeft + DtStringUtil.addQuoteForStr(col) + "=null"); + } + } + return StringUtils.join(list, ","); + } + + + /** + * build connect sql by index column, such as T1."A"=T2."A" + * @param updateKey + * @return + */ + public String updateKeySql(Map> updateKey) { + List exprList = new ArrayList<>(); + for (Map.Entry> entry : updateKey.entrySet()) { + List colList = new ArrayList<>(); + for (String col : entry.getValue()) { + colList.add("T1." + DtStringUtil.addQuoteForStr(col) + "=T2." + DtStringUtil.addQuoteForStr(col)); + } + exprList.add(StringUtils.join(colList, " AND ")); + } + return StringUtils.join(exprList, " OR "); + } + + /** + * build select sql , such as (SELECT ? "A",? "B" FROM DUAL) + * + * @param column destination column + * @return + */ + public String makeValues(List column) { + StringBuilder sb = new StringBuilder("SELECT "); + for (int i = 0; i < column.size(); ++i) { + if (i != 0) { + sb.append(","); + } + sb.append("? " + DtStringUtil.addQuoteForStr(column.get(i))); + } + sb.append(" FROM DUAL"); + return sb.toString(); + } + + public boolean containsIgnoreCase(List l, String s) { + Iterator it = l.iterator(); + while (it.hasNext()) { + if (it.next().equalsIgnoreCase(s)) + return true; + } + return false; + } + + + } diff --git a/oracle/oracle-sink/src/main/java/com/dtstack/flink/sql/sink/oracle/table/OracleSinkParser.java b/oracle/oracle-sink/src/main/java/com/dtstack/flink/sql/sink/oracle/table/OracleSinkParser.java index 2eeee3fb2..aff096bd3 100644 --- a/oracle/oracle-sink/src/main/java/com/dtstack/flink/sql/sink/oracle/table/OracleSinkParser.java +++ b/oracle/oracle-sink/src/main/java/com/dtstack/flink/sql/sink/oracle/table/OracleSinkParser.java @@ -17,9 +17,8 @@ */ package com.dtstack.flink.sql.sink.oracle.table; -import com.dtstack.flink.sql.core.rdb.JdbcCheckKeys; import com.dtstack.flink.sql.sink.rdb.table.RdbSinkParser; -import com.dtstack.flink.sql.table.AbstractTableInfo; +import com.dtstack.flink.sql.table.TableInfo; import java.util.Map; @@ -34,9 +33,8 @@ public class OracleSinkParser extends RdbSinkParser { private static final String CURR_TYPE = "oracle"; @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { - props.put(JdbcCheckKeys.DRIVER_NAME, "oracle.jdbc.driver.OracleDriver"); - AbstractTableInfo oracleTableInfo = super.getTableInfo(tableName, fieldsInfo, props); + public TableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { + TableInfo oracleTableInfo = super.getTableInfo(tableName, fieldsInfo, props); oracleTableInfo.setType(CURR_TYPE); return oracleTableInfo; } diff --git a/oracle/oracle-sink/src/test/java/com/dtstack/flink/sql/sink/oracle/OracleDialectTest.java b/oracle/oracle-sink/src/test/java/com/dtstack/flink/sql/sink/oracle/OracleDialectTest.java deleted file mode 100644 index c5548d524..000000000 --- a/oracle/oracle-sink/src/test/java/com/dtstack/flink/sql/sink/oracle/OracleDialectTest.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.dtstack.flink.sql.sink.oracle; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import java.util.ArrayList; - -public class OracleDialectTest { - - OracleDialect dialect; - - @Before - public void setUp() throws Exception { - dialect = new OracleDialect(); - ArrayList fields = new ArrayList<>(); - fields.add("id"); - fields.add("name"); - dialect.setFieldList(fields); - ArrayList fieldTypes = new ArrayList<>(); - fieldTypes.add("INT"); - fieldTypes.add("STRING"); - dialect.setFieldTypeList(fieldTypes); -// dialect.setFieldExtraInfoList(); - } - - @Test - public void testEasyUtils() { - final String s = "jdbc:oracle://localhost:3306/foo_db"; - boolean r = dialect.canHandle(s); - Assert.assertTrue(r); - - String driver = dialect.defaultDriverName().get(); - Assert.assertTrue(driver.equals("oracle.jdbc.driver.OracleDriver")); - } - - @Test - public void testDialect() { - final String tableName = "table_foo"; - final String[] fieldNames = new String[] { - "id", - "name" - }; - final String[] uniqueKeyFields = new String[] { - "id", - }; - final String NORMAL_STMT = - "MERGE INTO \"table_foo\" " + - "T1 USING (SELECT ? \"id\", ? \"name\" FROM DUAL) " + - "T2 ON (T1.\"id\"=T2.\"id\") " + - "WHEN MATCHED THEN UPDATE SET \"T1\".\"name\" =nvl(\"T2\".\"name\",\"T1\".\"name\") " + - "WHEN NOT MATCHED THEN INSERT (\"id\",\"name\") VALUES (T2.\"id\",T2.\"name\")"; - - String upsertStmt = dialect - .getUpsertStatement("", tableName, fieldNames, uniqueKeyFields, false) - .get(); - - Assert.assertTrue(NORMAL_STMT.equals(upsertStmt)); - } - -} \ No newline at end of file diff --git a/oracle/oracle-sink/src/test/java/com/dtstack/flink/sql/sink/oracle/OracleSinkTest.java b/oracle/oracle-sink/src/test/java/com/dtstack/flink/sql/sink/oracle/OracleSinkTest.java deleted file mode 100644 index e22ac1272..000000000 --- a/oracle/oracle-sink/src/test/java/com/dtstack/flink/sql/sink/oracle/OracleSinkTest.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.dtstack.flink.sql.sink.oracle; - -import com.dtstack.flink.sql.sink.rdb.format.JDBCUpsertOutputFormat; -import org.junit.Before; -import org.junit.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.powermock.api.support.membermodification.MemberModifier; -import java.util.Optional; -import static org.mockito.Mockito.when; - -public class OracleSinkTest { - - @Mock - OracleDialect jdbcDialect; - - @InjectMocks - OracleSink sink = new OracleSink();; - @Before - public void setUp () { - MockitoAnnotations.initMocks(this); - } - - @Test - public void testGetOutputFormat() throws IllegalAccessException { - when(jdbcDialect.defaultDriverName()).thenReturn(Optional.of("dd")); - - MemberModifier.field(OracleSink.class, "dbUrl").set(sink, "foo"); - MemberModifier.field(OracleSink.class, "jdbcDialect").set(sink, jdbcDialect); - MemberModifier.field(OracleSink.class, "userName").set(sink, "foo"); - MemberModifier.field(OracleSink.class, "password").set(sink, "foo"); - MemberModifier.field(OracleSink.class, "tableName").set(sink, "foo"); - MemberModifier.field(OracleSink.class, "fieldNames").set(sink, new String[]{"foo", "bar"}); - - JDBCUpsertOutputFormat format = sink.getOutputFormat(); - } - -} \ No newline at end of file diff --git a/oracle/oracle-sink/src/test/java/com/dtstack/flink/sql/sink/oracle/table/OracleSinkParserTest.java b/oracle/oracle-sink/src/test/java/com/dtstack/flink/sql/sink/oracle/table/OracleSinkParserTest.java deleted file mode 100644 index 889eb7bb0..000000000 --- a/oracle/oracle-sink/src/test/java/com/dtstack/flink/sql/sink/oracle/table/OracleSinkParserTest.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.dtstack.flink.sql.sink.oracle.table; - -import com.dtstack.flink.sql.table.AbstractTableInfo; -import org.junit.Assert; -import org.junit.Test; -import java.util.HashMap; -import java.util.Map; - -public class OracleSinkParserTest { - -// @Test - public void getTableInfo() { - OracleSinkParser sinkParser = new OracleSinkParser(); - - final String tableName = "table_foo"; - final String fieldsInfo = "id INT, name VARCHAR"; - - Map props = new HashMap(); - props.put("url", "jdbc:mysql://foo:3306/db_foo"); - props.put("tablename", "table_foo"); - props.put("username", "foo"); - props.put("password", "foo"); - - AbstractTableInfo tableInfo= sinkParser.getTableInfo(tableName, fieldsInfo, props); - - final String NORMAL_TYPE = "oracle"; - final String table_type = tableInfo.getType(); - Assert.assertTrue(NORMAL_TYPE.equals(table_type)); - } - -} \ No newline at end of file diff --git a/polardb/polardb-side/polardb-all-side/pom.xml b/polardb/polardb-side/polardb-all-side/pom.xml deleted file mode 100644 index 86fd96d77..000000000 --- a/polardb/polardb-side/polardb-all-side/pom.xml +++ /dev/null @@ -1,92 +0,0 @@ - - - - sql.side.polardb - com.dtstack.flink - 1.0-SNAPSHOT - - 4.0.0 - - sql.side.all.polardb - polardb-all-side - - jar - - - 1.0-SNAPSHOT - - - - - com.dtstack.flink - sql.side.polardb.core - ${sql.side.polardb.core.version} - - - - - - - org.apache.maven.plugins - maven-shade-plugin - 1.4 - - - package - - shade - - - - - - - - - - *:* - - META-INF/*.SF - META-INF/*.DSA - META-INF/*.RSA - - - - - - - - - - maven-antrun-plugin - 1.2 - - - copy-resources - - package - - run - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/polardb/polardb-side/polardb-all-side/src/main/java/com/dtstack/flink/sql/side/polardb/PolardbAllReqRow.java b/polardb/polardb-side/polardb-all-side/src/main/java/com/dtstack/flink/sql/side/polardb/PolardbAllReqRow.java deleted file mode 100644 index 5fbf0824b..000000000 --- a/polardb/polardb-side/polardb-all-side/src/main/java/com/dtstack/flink/sql/side/polardb/PolardbAllReqRow.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.polardb; - -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.rdb.all.AbstractRdbAllReqRow; -import com.dtstack.flink.sql.util.DtStringUtil; -import com.google.common.collect.Maps; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.sql.Connection; -import java.sql.DriverManager; -import java.util.List; -import java.util.Map; - -/** - * Date: 2019/12/20 - * Company: www.dtstack.com - * @author yinxi - */ -public class PolardbAllReqRow extends AbstractRdbAllReqRow { - - private static final long serialVersionUID = 2098635140857937717L; - - private static final Logger LOG = LoggerFactory.getLogger(PolardbAllReqRow.class); - - private static final String POLARDB_DRIVER = "com.mysql.cj.jdbc.Driver"; - - public PolardbAllReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { - super(new PolardbAllSideInfo(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo)); - } - - @Override - public Connection getConn(String dbUrl, String userName, String password) { - try { - Class.forName(POLARDB_DRIVER); - //add param useCursorFetch=true - Map addParams = Maps.newHashMap(); - addParams.put("useCursorFetch", "true"); - String targetDbUrl = DtStringUtil.addJdbcParam(dbUrl, addParams, true); - return DriverManager.getConnection(targetDbUrl, userName, password); - } catch (Exception e) { - LOG.error("", e); - throw new RuntimeException("", e); - } - } - - @Override - public int getFetchSize() { - return Integer.MIN_VALUE; - } -} diff --git a/polardb/polardb-side/polardb-all-side/src/main/java/com/dtstack/flink/sql/side/polardb/PolardbAllSideInfo.java b/polardb/polardb-side/polardb-all-side/src/main/java/com/dtstack/flink/sql/side/polardb/PolardbAllSideInfo.java deleted file mode 100644 index c46c9dfd6..000000000 --- a/polardb/polardb-side/polardb-all-side/src/main/java/com/dtstack/flink/sql/side/polardb/PolardbAllSideInfo.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.polardb; - -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.rdb.all.RdbAllSideInfo; -import org.apache.flink.api.java.typeutils.RowTypeInfo; - -import java.util.List; - -/** - * Date: 2019/12/20 - * Company: www.dtstack.com - * @author yinxi - */ -public class PolardbAllSideInfo extends RdbAllSideInfo { - public PolardbAllSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { - super(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); - } - - @Override - public String quoteIdentifier(String identifier) { - return "`" + identifier + "`"; - } -} - diff --git a/polardb/polardb-side/polardb-all-side/src/test/java/com/dtstack/flink/sql/side/polardb/PolardbAllReqRowTest.java b/polardb/polardb-side/polardb-all-side/src/test/java/com/dtstack/flink/sql/side/polardb/PolardbAllReqRowTest.java deleted file mode 100644 index bd754b34f..000000000 --- a/polardb/polardb-side/polardb-all-side/src/test/java/com/dtstack/flink/sql/side/polardb/PolardbAllReqRowTest.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.dtstack.flink.sql.side.polardb; - -import com.dtstack.flink.sql.side.rdb.all.RdbAllReqRowTestBase; - -public class PolardbAllReqRowTest extends RdbAllReqRowTestBase { - - @Override - protected void init() { - clazz = PolardbAllReqRow.class; - } - -} \ No newline at end of file diff --git a/polardb/polardb-side/polardb-async-side/pom.xml b/polardb/polardb-side/polardb-async-side/pom.xml deleted file mode 100644 index 068ad974d..000000000 --- a/polardb/polardb-side/polardb-async-side/pom.xml +++ /dev/null @@ -1,91 +0,0 @@ - - - - sql.side.polardb - com.dtstack.flink - 1.0-SNAPSHOT - - 4.0.0 - - sql.side.async.polardb - polardb-async-side - jar - - - 1.0-SNAPSHOT - - - - - com.dtstack.flink - sql.side.polardb.core - ${sql.side.polardb.core.version} - - - - - - - org.apache.maven.plugins - maven-shade-plugin - 1.4 - - - package - - shade - - - - - - - - - - *:* - - META-INF/*.SF - META-INF/*.DSA - META-INF/*.RSA - - - - - - - - - - maven-antrun-plugin - 1.2 - - - copy-resources - - package - - run - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/polardb/polardb-side/polardb-async-side/src/main/java/com/dtstack/flink/sql/side/polardb/PolardbAsyncReqRow.java b/polardb/polardb-side/polardb-async-side/src/main/java/com/dtstack/flink/sql/side/polardb/PolardbAsyncReqRow.java deleted file mode 100644 index 1ebaccd31..000000000 --- a/polardb/polardb-side/polardb-async-side/src/main/java/com/dtstack/flink/sql/side/polardb/PolardbAsyncReqRow.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.polardb; - -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.rdb.async.RdbAsyncReqRow; -import com.dtstack.flink.sql.side.rdb.table.RdbSideTableInfo; -import io.vertx.core.json.JsonObject; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.configuration.Configuration; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.List; - -/** - * Date: 2019/12/20 - * Company: www.dtstack.com - * @author yinxi - */ -public class PolardbAsyncReqRow extends RdbAsyncReqRow { - - private static final Logger LOG = LoggerFactory.getLogger(PolardbAsyncReqRow.class); - - private final static String POLARDB_DRIVER = "com.mysql.cj.jdbc.Driver"; - - public PolardbAsyncReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { - super(new PolardbAsyncSideInfo(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo)); - } - - @Override - public void open(Configuration parameters) throws Exception { - super.open(parameters); - } - - @Override - public JsonObject buildJdbcConfig() { - JsonObject polardbConfig = new JsonObject(); - RdbSideTableInfo rdbSideTableInfo = (RdbSideTableInfo) sideInfo.getSideTableInfo(); - polardbConfig.put("url", rdbSideTableInfo.getUrl()) - .put("driver_class", POLARDB_DRIVER) - .put("max_pool_size", rdbSideTableInfo.getAsyncPoolSize()) - .put("user", rdbSideTableInfo.getUserName()) - .put("password", rdbSideTableInfo.getPassword()) - .put("provider_class", DT_PROVIDER_CLASS) - .put("preferred_test_query", PREFERRED_TEST_QUERY_SQL) - .put("idle_connection_test_period", DEFAULT_IDLE_CONNECTION_TEST_PEROID) - .put("test_connection_on_checkin", DEFAULT_TEST_CONNECTION_ON_CHECKIN); - - return polardbConfig; - } -} diff --git a/polardb/polardb-side/polardb-async-side/src/main/java/com/dtstack/flink/sql/side/polardb/PolardbAsyncSideInfo.java b/polardb/polardb-side/polardb-async-side/src/main/java/com/dtstack/flink/sql/side/polardb/PolardbAsyncSideInfo.java deleted file mode 100644 index 15237956b..000000000 --- a/polardb/polardb-side/polardb-async-side/src/main/java/com/dtstack/flink/sql/side/polardb/PolardbAsyncSideInfo.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.polardb; - -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.rdb.async.RdbAsyncSideInfo; -import org.apache.flink.api.java.typeutils.RowTypeInfo; - -import java.util.List; - -/** - * Date: 2019/12/20 - * Company: www.dtstack.com - * @author yinxi - */ -public class PolardbAsyncSideInfo extends RdbAsyncSideInfo { - - public PolardbAsyncSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { - super(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); - } - - @Override - public String quoteIdentifier(String identifier) { - return "`" + identifier + "`"; - } -} diff --git a/polardb/polardb-side/polardb-async-side/src/test/java/com/dtstack/flink/sql/side/polardb/PolardbAsyncReqRowTest.java b/polardb/polardb-side/polardb-async-side/src/test/java/com/dtstack/flink/sql/side/polardb/PolardbAsyncReqRowTest.java deleted file mode 100644 index 39fa51b1a..000000000 --- a/polardb/polardb-side/polardb-async-side/src/test/java/com/dtstack/flink/sql/side/polardb/PolardbAsyncReqRowTest.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.dtstack.flink.sql.side.polardb; - -import com.dtstack.flink.sql.side.rdb.async.RdbAsyncReqRowTestBase; -import org.junit.Before; -import org.powermock.reflect.Whitebox; - -public class PolardbAsyncReqRowTest extends RdbAsyncReqRowTestBase { - - @Override - protected void init() { - clazz = PolardbAsyncReqRow.class; - } - -} \ No newline at end of file diff --git a/polardb/polardb-side/polardb-side-core/pom.xml b/polardb/polardb-side/polardb-side-core/pom.xml deleted file mode 100644 index 106cbe256..000000000 --- a/polardb/polardb-side/polardb-side-core/pom.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - sql.side.polardb - com.dtstack.flink - 1.0-SNAPSHOT - - 4.0.0 - - sql.side.polardb.core - 1.0-SNAPSHOT - polardb-side-core - - \ No newline at end of file diff --git a/polardb/polardb-side/polardb-side-core/src/main/java/com/dtstack/flink/sql/side/polardb/table/PolardbSideParser.java b/polardb/polardb-side/polardb-side-core/src/main/java/com/dtstack/flink/sql/side/polardb/table/PolardbSideParser.java deleted file mode 100644 index 4e2683b14..000000000 --- a/polardb/polardb-side/polardb-side-core/src/main/java/com/dtstack/flink/sql/side/polardb/table/PolardbSideParser.java +++ /dev/null @@ -1,43 +0,0 @@ - -/* - * 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 com.dtstack.flink.sql.side.polardb.table; - -import com.dtstack.flink.sql.core.rdb.JdbcCheckKeys; -import com.dtstack.flink.sql.side.rdb.table.RdbSideParser; -import com.dtstack.flink.sql.table.AbstractTableInfo; - -import java.util.Map; - -/** - * Date: 2019/12/20 - * Company: www.dtstack.com - * - * @author yinxi - */ -public class PolardbSideParser extends RdbSideParser { - private static final String CURR_TYPE = "polardb"; - - @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { - props.put(JdbcCheckKeys.DRIVER_NAME, "com.mysql.cj.jdbc.Driver"); - AbstractTableInfo mysqlTableInfo = super.getTableInfo(tableName, fieldsInfo, props); - mysqlTableInfo.setType(CURR_TYPE); - return mysqlTableInfo; - } -} diff --git a/polardb/polardb-side/polardb-side-core/src/test/java/com/dtstack/flink/sql/side/polardb/table/PolardbSideParserTest.java b/polardb/polardb-side/polardb-side-core/src/test/java/com/dtstack/flink/sql/side/polardb/table/PolardbSideParserTest.java deleted file mode 100644 index a4c02b40b..000000000 --- a/polardb/polardb-side/polardb-side-core/src/test/java/com/dtstack/flink/sql/side/polardb/table/PolardbSideParserTest.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.dtstack.flink.sql.side.polardb.table; - -import com.dtstack.flink.sql.table.AbstractTableInfo; -import org.junit.Assert; -import org.junit.Test; -import java.util.HashMap; -import java.util.Map; - -public class PolardbSideParserTest { - -// @Test - public void getTableInfo() { - PolardbSideParser sideParser = new PolardbSideParser(); - - final String tableName = "table_foo"; - final String fieldsInfo = "id INT, name VARCHAR, PRIMARY KEY (id)"; - - Map props = new HashMap(); - props.put("url", "jdbc:mysql://foo:3306/db_foo"); - props.put("tablename", "table_foo"); - props.put("username", "foo"); - props.put("password", "foo"); - - AbstractTableInfo tableInfo= sideParser.getTableInfo(tableName, fieldsInfo, props); - - final String NORMAL_TYPE = "polardb"; - final String table_type = tableInfo.getType(); - Assert.assertTrue(NORMAL_TYPE.equals(table_type)); - } - -} \ No newline at end of file diff --git a/polardb/polardb-side/pom.xml b/polardb/polardb-side/pom.xml deleted file mode 100644 index 70ab928fd..000000000 --- a/polardb/polardb-side/pom.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - sql.polardb - com.dtstack.flink - 1.0-SNAPSHOT - - 4.0.0 - - sql.side.polardb - 1.0-SNAPSHOT - - polardb-all-side - polardb-side-core - polardb-async-side - - polardb-side - pom - - - 1.0-SNAPSHOT - - - - - com.dtstack.flink - sql.side.rdb - ${rdb.side.version} - - - - - - com.dtstack.flink - sql.side.rdb - ${rdb.side.version} - test-jar - test - - - \ No newline at end of file diff --git a/polardb/polardb-sink/src/main/java/com/dtstack/flink/sql/sink/polardb/PolardbDialect.java b/polardb/polardb-sink/src/main/java/com/dtstack/flink/sql/sink/polardb/PolardbDialect.java deleted file mode 100644 index ec4b190b5..000000000 --- a/polardb/polardb-sink/src/main/java/com/dtstack/flink/sql/sink/polardb/PolardbDialect.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.polardb; - -import com.dtstack.flink.sql.sink.rdb.dialect.JDBCDialect; - -import java.util.Arrays; -import java.util.Optional; -import java.util.stream.Collectors; - -/** - * Date: 2020/1/15 - * Company: www.dtstack.com - * @author maqi - */ -public class PolardbDialect implements JDBCDialect { - - @Override - public boolean canHandle(String url) { - return url.startsWith("jdbc:mysql:"); - } - - @Override - public Optional defaultDriverName() { - return Optional.of("com.mysql.cj.jdbc.Driver"); - } - - @Override - public String quoteIdentifier(String identifier) { - return "`" + identifier + "`"; - } - - /** - * 根据ALLReplace参数,选择使用replace语句还是ON DUPLICATE KEY UPDATE 语句 - * @param tableName - * @param fieldNames - * @param uniqueKeyFields - * @param allReplace - * @return - */ - @Override - public Optional getUpsertStatement(String schema, String tableName, String[] fieldNames, String[] uniqueKeyFields, boolean allReplace) { - return allReplace ? buildReplaceIntoStatement(tableName, fieldNames) : buildDuplicateUpsertStatement(tableName, fieldNames); - } - - public Optional buildDuplicateUpsertStatement(String tableName, String[] fieldNames) { - String updateClause = Arrays.stream(fieldNames).map(f -> quoteIdentifier(f) + "=IFNULL(VALUES(" + quoteIdentifier(f) + ")," + quoteIdentifier(f) + ")") - .collect(Collectors.joining(", ")); - return Optional.of(getInsertIntoStatement("", tableName, fieldNames, null) + - " ON DUPLICATE KEY UPDATE " + updateClause - ); - } - - public Optional buildReplaceIntoStatement(String tableName, String[] fieldNames) { - String columns = Arrays.stream(fieldNames) - .map(this::quoteIdentifier) - .collect(Collectors.joining(", ")); - String placeholders = Arrays.stream(fieldNames) - .map(f -> "?") - .collect(Collectors.joining(", ")); - return Optional.of("REPLACE INTO " + quoteIdentifier(tableName) + - "(" + columns + ")" + " VALUES (" + placeholders + ")"); - } -} diff --git a/polardb/polardb-sink/src/main/java/com/dtstack/flink/sql/sink/polardb/PolardbSink.java b/polardb/polardb-sink/src/main/java/com/dtstack/flink/sql/sink/polardb/PolardbSink.java deleted file mode 100644 index ad7504213..000000000 --- a/polardb/polardb-sink/src/main/java/com/dtstack/flink/sql/sink/polardb/PolardbSink.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.polardb; - -import com.dtstack.flink.sql.sink.rdb.JDBCOptions; -import com.dtstack.flink.sql.sink.rdb.AbstractRdbSink; -import com.dtstack.flink.sql.sink.rdb.format.JDBCUpsertOutputFormat; - -/** - * Date: 2019/12/20 - * Company: www.dtstack.com - * @author yinxi - */ -public class PolardbSink extends AbstractRdbSink { - public PolardbSink() { - super(new PolardbDialect()); - } - - @Override - public JDBCUpsertOutputFormat getOutputFormat() { - JDBCOptions jdbcOptions = JDBCOptions.builder() - .setDbUrl(dbUrl) - .setDialect(jdbcDialect) - .setUsername(userName) - .setPassword(password) - .setTableName(tableName) - .build(); - - return JDBCUpsertOutputFormat.builder() - .setOptions(jdbcOptions) - .setFieldNames(fieldNames) - .setFlushMaxSize(batchNum) - .setFlushIntervalMills(batchWaitInterval) - .setFieldTypes(sqlTypes) - .setKeyFields(primaryKeys) - .setAllReplace(allReplace) - .setErrorLimit(errorLimit) - .setUpdateMode(updateMode).build(); - } -} diff --git a/polardb/polardb-sink/src/main/java/com/dtstack/flink/sql/sink/polardb/table/PolardbSinkParser.java b/polardb/polardb-sink/src/main/java/com/dtstack/flink/sql/sink/polardb/table/PolardbSinkParser.java deleted file mode 100644 index 80d62f3d0..000000000 --- a/polardb/polardb-sink/src/main/java/com/dtstack/flink/sql/sink/polardb/table/PolardbSinkParser.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.polardb.table; - -import com.dtstack.flink.sql.core.rdb.JdbcCheckKeys; -import com.dtstack.flink.sql.sink.rdb.table.RdbSinkParser; -import com.dtstack.flink.sql.table.AbstractTableInfo; - -import java.util.Map; - -/** - * Date: 2019/12/20 - * Company: www.dtstack.com - * - * @author yinxi - */ -public class PolardbSinkParser extends RdbSinkParser { - private static final String CURR_TYPE = "polardb"; - - @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { - props.put(JdbcCheckKeys.DRIVER_NAME, "com.mysql.cj.jdbc.Driver"); - AbstractTableInfo polardbTableInfo = super.getTableInfo(tableName, fieldsInfo, props); - polardbTableInfo.setType(CURR_TYPE); - return polardbTableInfo; - } -} diff --git a/polardb/polardb-sink/src/test/java/com/dtstack/flink/sql/sink/polardb/PolardbDialectTest.java b/polardb/polardb-sink/src/test/java/com/dtstack/flink/sql/sink/polardb/PolardbDialectTest.java deleted file mode 100644 index 38d8ddb00..000000000 --- a/polardb/polardb-sink/src/test/java/com/dtstack/flink/sql/sink/polardb/PolardbDialectTest.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.dtstack.flink.sql.sink.polardb; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - - -public class PolardbDialectTest { - - PolardbDialect dialect; - - @Before - public void setUp() { - dialect = new PolardbDialect(); - } - - @Test - public void testEasyUtils() { - final String s = "jdbc:mysql://localhost:3306/foo_db"; - boolean r = dialect.canHandle(s); - Assert.assertTrue(r); - - String driver = dialect.defaultDriverName().get(); - Assert.assertTrue(driver.equals("com.mysql.cj.jdbc.Driver")); - - final String foo = "foo"; - final String NORMAL_QUOTE = "`foo`"; - String strWithQuote = dialect.quoteIdentifier(foo); - - Assert.assertTrue(strWithQuote.equals(NORMAL_QUOTE)); - } - - @Test - public void testDialect() { - final String tableName = "table_foo"; - final String[] fieldNames = new String[] { - "id", - "name" - }; - final String NORMAL_REPELACE_STMT = - "REPLACE INTO `table_foo`(`id`, `name`) VALUES (?, ?)"; - final String NORMAL_UPSERT_STMT = - "INSERT INTO `table_foo`(`id`, `name`) VALUES (?, ?) " + - "ON DUPLICATE KEY UPDATE `id`=IFNULL(VALUES(`id`),`id`), " + - "`name`=IFNULL(VALUES(`name`),`name`)"; - - String replaceStmt = dialect.buildReplaceIntoStatement(tableName, fieldNames) - .get(); - String upsertStmt = dialect.buildDuplicateUpsertStatement(tableName, fieldNames) - .get(); - - Assert.assertTrue(NORMAL_REPELACE_STMT.equals(replaceStmt)); - Assert.assertTrue(NORMAL_UPSERT_STMT.equals(upsertStmt)); - - String upsertStmtWithReplace = dialect - .getUpsertStatement("", tableName, fieldNames, null, true) - .get(); - String upsertStmtWithoutReplace = dialect - .getUpsertStatement("", tableName, fieldNames, null, false) - .get(); - - Assert.assertTrue(replaceStmt.equals(upsertStmtWithReplace)); - Assert.assertTrue(upsertStmt.equals(upsertStmtWithoutReplace)); - } -} \ No newline at end of file diff --git a/polardb/polardb-sink/src/test/java/com/dtstack/flink/sql/sink/polardb/PolardbSinkTest.java b/polardb/polardb-sink/src/test/java/com/dtstack/flink/sql/sink/polardb/PolardbSinkTest.java deleted file mode 100644 index 154ba193c..000000000 --- a/polardb/polardb-sink/src/test/java/com/dtstack/flink/sql/sink/polardb/PolardbSinkTest.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.dtstack.flink.sql.sink.polardb; - -import com.dtstack.flink.sql.sink.rdb.dialect.JDBCDialect; -import com.dtstack.flink.sql.sink.rdb.format.JDBCUpsertOutputFormat; -import org.junit.Before; -import org.junit.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.powermock.api.support.membermodification.MemberModifier; -import java.util.Optional; -import static org.mockito.Mockito.when; - -public class PolardbSinkTest { - - // TODO CI timeout -// @Mock -// JDBCDialect jdbcDialect; -// -// @InjectMocks -// PolardbSink sink = new PolardbSink();; -// @Before -// public void setUp () { -// MockitoAnnotations.initMocks(this); -// } -// -// @Test -// public void testGetOutputFormat() throws IllegalAccessException { -// when(jdbcDialect.defaultDriverName()).thenReturn(Optional.of("dd")); -// -// MemberModifier.field(PolardbSink.class, "dbUrl").set(sink, "foo"); -// MemberModifier.field(PolardbSink.class, "jdbcDialect").set(sink, jdbcDialect); -// MemberModifier.field(PolardbSink.class, "userName").set(sink, "foo"); -// MemberModifier.field(PolardbSink.class, "password").set(sink, "foo"); -// MemberModifier.field(PolardbSink.class, "tableName").set(sink, "foo"); -// MemberModifier.field(PolardbSink.class, "fieldNames").set(sink, new String[]{"foo", "bar"}); -// -// JDBCUpsertOutputFormat format = sink.getOutputFormat(); -// } - -} \ No newline at end of file diff --git a/polardb/polardb-sink/src/test/java/com/dtstack/flink/sql/sink/polardb/table/PolardbSinkParserTest.java b/polardb/polardb-sink/src/test/java/com/dtstack/flink/sql/sink/polardb/table/PolardbSinkParserTest.java deleted file mode 100644 index 62c626156..000000000 --- a/polardb/polardb-sink/src/test/java/com/dtstack/flink/sql/sink/polardb/table/PolardbSinkParserTest.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.dtstack.flink.sql.sink.polardb.table; - -import com.dtstack.flink.sql.table.AbstractTableInfo; -import org.junit.Assert; -import org.junit.Test; -import java.util.HashMap; -import java.util.Map; - -public class PolardbSinkParserTest { - -// @Test - public void getTableInfo() { - PolardbSinkParser sinkParser = new PolardbSinkParser(); - - final String tableName = "table_foo"; - final String fieldsInfo = "id INT, name VARCHAR, PRIMARY KEY (id)"; - - Map props = new HashMap(); - props.put("url", "jdbc:mysql://foo:3306/db_foo"); - props.put("tablename", "table_foo"); - props.put("username", "foo"); - props.put("password", "foo"); - - AbstractTableInfo tableInfo= sinkParser.getTableInfo(tableName, fieldsInfo, props); - - final String NORMAL_TYPE = "polardb"; - final String table_type = tableInfo.getType(); - Assert.assertTrue(NORMAL_TYPE.equals(table_type)); - } - -} \ No newline at end of file diff --git a/polardb/pom.xml b/polardb/pom.xml deleted file mode 100644 index 7131b2e79..000000000 --- a/polardb/pom.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - flink.sql - com.dtstack.flink - 1.0-SNAPSHOT - ../pom.xml - - - 4.0.0 - sql.polardb - pom - - - polardb-sink - polardb-side - - - - 8.0.16 - 1.0-SNAPSHOT - - - - - - com.dtstack.flink - sql.core - ${sql.core.version} - provided - - - - mysql - mysql-connector-java - ${mysql.connector.version} - - - - \ No newline at end of file diff --git a/pom.xml b/pom.xml index e19e2b678..b4c3478b3 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,6 @@ http://maven.apache.org core - kafka-base kafka09 kafka10 kafka11 @@ -18,9 +17,6 @@ mysql hbase elasticsearch5 - elasticsearch5-xh - elasticsearch6 - elasticsearch7 mongo redis5 launcher @@ -30,81 +26,17 @@ cassandra kudu postgresql + serversocket console clickhouse - impala - db2 - polardb - oceanbase - tidb - kingbase - aws - file - http - solr - - - dirtyData - - - - UTF-8 - 1.10.1 - 2.7.3 - 4.12 - 2.21.0 - 2.0.4 - 0.7.8 - - - - - junit - junit - ${junit.version} - test - - - org.mockito - mockito-core - ${mockito.version} - test - - - org.powermock - powermock-module-junit4 - ${powermock.version} - test - - - org.powermock - powermock-api-mockito2 - ${powermock.version} - test - - - org.mockito - mockito-core - - - - - org.jacoco - org.jacoco.agent - runtime - test - ${jacoco.version} - - - com.alibaba - fastjson - 1.2.76 - - + + UTF-8 + 1.8.1 + @@ -117,20 +49,6 @@ - - org.jacoco - jacoco-maven-plugin - 0.7.8 - - - - prepare-agent - report - - - - - pl.project13.maven git-commit-id-plugin @@ -153,21 +71,6 @@ - - org.apache.maven.plugins - maven-clean-plugin - 3.1.0 - - - - ${basedir}/plugins - - - ${basedir}/sqlplugins - - - - diff --git a/postgresql/pom.xml b/postgresql/pom.xml index b218137b6..53398b87b 100644 --- a/postgresql/pom.xml +++ b/postgresql/pom.xml @@ -18,10 +18,16 @@ 1.0-SNAPSHOT - 42.4.1 + 42.2.2 + + junit + junit + 3.8.1 + test + com.dtstack.flink diff --git a/postgresql/postgresql-side/pom.xml b/postgresql/postgresql-side/pom.xml index 7c589ee80..0e3723ea6 100644 --- a/postgresql/postgresql-side/pom.xml +++ b/postgresql/postgresql-side/pom.xml @@ -32,17 +32,6 @@ sql.side.rdb ${rdb.side.version} - - - - - com.dtstack.flink - sql.side.rdb - ${rdb.side.version} - test-jar - test - - diff --git a/postgresql/postgresql-side/postgresql-all-side/pom.xml b/postgresql/postgresql-side/postgresql-all-side/pom.xml index 681fdec88..d076d9300 100644 --- a/postgresql/postgresql-side/postgresql-all-side/pom.xml +++ b/postgresql/postgresql-side/postgresql-all-side/pom.xml @@ -40,7 +40,6 @@ shade - false @@ -74,14 +73,14 @@ - + - + diff --git a/postgresql/postgresql-side/postgresql-all-side/src/main/java/com/dtstack/flink/sql/side/postgresql/PostgresqlAllReqRow.java b/postgresql/postgresql-side/postgresql-all-side/src/main/java/com/dtstack/flink/sql/side/postgresql/PostgresqlAllReqRow.java index 0ec8f96ce..6d68cfdca 100644 --- a/postgresql/postgresql-side/postgresql-all-side/src/main/java/com/dtstack/flink/sql/side/postgresql/PostgresqlAllReqRow.java +++ b/postgresql/postgresql-side/postgresql-all-side/src/main/java/com/dtstack/flink/sql/side/postgresql/PostgresqlAllReqRow.java @@ -20,8 +20,8 @@ import com.dtstack.flink.sql.side.FieldInfo; import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.rdb.all.AbstractRdbAllReqRow; +import com.dtstack.flink.sql.side.SideTableInfo; +import com.dtstack.flink.sql.side.rdb.all.RdbAllReqRow; import com.dtstack.flink.sql.util.DtStringUtil; import org.apache.flink.api.java.typeutils.RowTypeInfo; import org.apache.flink.shaded.guava18.com.google.common.collect.Maps; @@ -41,7 +41,7 @@ * @author tcm */ -public class PostgresqlAllReqRow extends AbstractRdbAllReqRow { +public class PostgresqlAllReqRow extends RdbAllReqRow { private static final long serialVersionUID = 2098635140857937717L; @@ -49,18 +49,18 @@ public class PostgresqlAllReqRow extends AbstractRdbAllReqRow { private static final String POSTGRESQL_DRIVER = "org.postgresql.Driver"; - public PostgresqlAllReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { + public PostgresqlAllReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, SideTableInfo sideTableInfo) { super(new PostgresqlAllSideInfo(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo)); } @Override - public Connection getConn(String dbUrl, String userName, String password) { + public Connection getConn(String dbURL, String userName, String password) { try { Class.forName(POSTGRESQL_DRIVER); //add param useCursorFetch=true Map addParams = Maps.newHashMap(); addParams.put("useCursorFetch", "true"); - String targetDbUrl = DtStringUtil.addJdbcParam(dbUrl, addParams, true); + String targetDbUrl = DtStringUtil.addJdbcParam(dbURL, addParams, true); return DriverManager.getConnection(targetDbUrl, userName, password); } catch (Exception e) { LOG.error("", e); diff --git a/postgresql/postgresql-side/postgresql-all-side/src/main/java/com/dtstack/flink/sql/side/postgresql/PostgresqlAllSideInfo.java b/postgresql/postgresql-side/postgresql-all-side/src/main/java/com/dtstack/flink/sql/side/postgresql/PostgresqlAllSideInfo.java index fa07d078b..d383ee46d 100644 --- a/postgresql/postgresql-side/postgresql-all-side/src/main/java/com/dtstack/flink/sql/side/postgresql/PostgresqlAllSideInfo.java +++ b/postgresql/postgresql-side/postgresql-all-side/src/main/java/com/dtstack/flink/sql/side/postgresql/PostgresqlAllSideInfo.java @@ -20,10 +20,8 @@ import com.dtstack.flink.sql.side.FieldInfo; import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; +import com.dtstack.flink.sql.side.SideTableInfo; import com.dtstack.flink.sql.side.rdb.all.RdbAllSideInfo; -import com.dtstack.flink.sql.side.rdb.table.RdbSideTableInfo; -import com.dtstack.flink.sql.util.DtStringUtil; import org.apache.flink.api.java.typeutils.RowTypeInfo; import java.util.List; @@ -37,12 +35,7 @@ */ public class PostgresqlAllSideInfo extends RdbAllSideInfo { - public PostgresqlAllSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { + public PostgresqlAllSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, SideTableInfo sideTableInfo) { super(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); } - - @Override - public String getTableName(RdbSideTableInfo rdbSideTableInfo) { - return DtStringUtil.getTableFullPath(rdbSideTableInfo.getSchema(), rdbSideTableInfo.getTableName()); - } } diff --git a/postgresql/postgresql-side/postgresql-all-side/src/test/java/com/dtstack/flink/sql/side/postgresql/PostgresqlAllReqRowTest.java b/postgresql/postgresql-side/postgresql-all-side/src/test/java/com/dtstack/flink/sql/side/postgresql/PostgresqlAllReqRowTest.java deleted file mode 100644 index cd351fc24..000000000 --- a/postgresql/postgresql-side/postgresql-all-side/src/test/java/com/dtstack/flink/sql/side/postgresql/PostgresqlAllReqRowTest.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.dtstack.flink.sql.side.postgresql; - -import com.dtstack.flink.sql.side.rdb.all.RdbAllReqRowTestBase; - -public class PostgresqlAllReqRowTest extends RdbAllReqRowTestBase { - - @Override - protected void init() { - clazz = PostgresqlAllReqRow.class; - } - -} \ No newline at end of file diff --git a/postgresql/postgresql-side/postgresql-async-side/pom.xml b/postgresql/postgresql-side/postgresql-async-side/pom.xml index 26def03cd..13296e7f3 100644 --- a/postgresql/postgresql-side/postgresql-async-side/pom.xml +++ b/postgresql/postgresql-side/postgresql-async-side/pom.xml @@ -41,7 +41,6 @@ shade - false @@ -75,14 +74,14 @@ - + - + diff --git a/postgresql/postgresql-side/postgresql-async-side/src/main/java/com/dtstack/flink/sql/side/postgresql/PostgresqlAsyncReqRow.java b/postgresql/postgresql-side/postgresql-async-side/src/main/java/com/dtstack/flink/sql/side/postgresql/PostgresqlAsyncReqRow.java index 6f928cf24..02b333819 100644 --- a/postgresql/postgresql-side/postgresql-async-side/src/main/java/com/dtstack/flink/sql/side/postgresql/PostgresqlAsyncReqRow.java +++ b/postgresql/postgresql-side/postgresql-async-side/src/main/java/com/dtstack/flink/sql/side/postgresql/PostgresqlAsyncReqRow.java @@ -19,12 +19,15 @@ package com.dtstack.flink.sql.side.postgresql; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; import com.dtstack.flink.sql.side.FieldInfo; import com.dtstack.flink.sql.side.JoinInfo; +import com.dtstack.flink.sql.side.SideTableInfo; import com.dtstack.flink.sql.side.rdb.async.RdbAsyncReqRow; import com.dtstack.flink.sql.side.rdb.table.RdbSideTableInfo; +import io.vertx.core.Vertx; +import io.vertx.core.VertxOptions; import io.vertx.core.json.JsonObject; +import io.vertx.ext.jdbc.JDBCClient; import org.apache.flink.api.java.typeutils.RowTypeInfo; import org.apache.flink.configuration.Configuration; import org.slf4j.Logger; @@ -45,7 +48,7 @@ public class PostgresqlAsyncReqRow extends RdbAsyncReqRow { private final static String POSTGRESQL_DRIVER = "org.postgresql.Driver"; - public PostgresqlAsyncReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { + public PostgresqlAsyncReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, SideTableInfo sideTableInfo) { super(new PostgresqlAsyncSideInfo(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo)); } @@ -53,21 +56,19 @@ public PostgresqlAsyncReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { + public PostgresqlAsyncSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, SideTableInfo sideTableInfo) { super(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); } - - @Override - public String getTableName(RdbSideTableInfo rdbSideTableInfo) { - return DtStringUtil.getTableFullPath(rdbSideTableInfo.getSchema(), rdbSideTableInfo.getTableName()); - } } diff --git a/postgresql/postgresql-side/postgresql-async-side/src/test/java/com/dtstack/flink/sql/side/postgresql/PostgresqlAsyncReqRowTest.java b/postgresql/postgresql-side/postgresql-async-side/src/test/java/com/dtstack/flink/sql/side/postgresql/PostgresqlAsyncReqRowTest.java deleted file mode 100644 index 301cad56a..000000000 --- a/postgresql/postgresql-side/postgresql-async-side/src/test/java/com/dtstack/flink/sql/side/postgresql/PostgresqlAsyncReqRowTest.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.dtstack.flink.sql.side.postgresql; - -import com.dtstack.flink.sql.side.rdb.async.RdbAsyncReqRowTestBase; - -public class PostgresqlAsyncReqRowTest extends RdbAsyncReqRowTestBase { - - @Override - protected void init() { - clazz = PostgresqlAsyncReqRow.class; - } - -} \ No newline at end of file diff --git a/postgresql/postgresql-side/postgresql-side-core/src/main/java/com/dtstack/flink/sql/side/postgresql/table/PostgresqlSideParser.java b/postgresql/postgresql-side/postgresql-side-core/src/main/java/com/dtstack/flink/sql/side/postgresql/table/PostgresqlSideParser.java index fe1afb578..faee2c704 100644 --- a/postgresql/postgresql-side/postgresql-side-core/src/main/java/com/dtstack/flink/sql/side/postgresql/table/PostgresqlSideParser.java +++ b/postgresql/postgresql-side/postgresql-side-core/src/main/java/com/dtstack/flink/sql/side/postgresql/table/PostgresqlSideParser.java @@ -19,9 +19,8 @@ package com.dtstack.flink.sql.side.postgresql.table; -import com.dtstack.flink.sql.core.rdb.JdbcCheckKeys; import com.dtstack.flink.sql.side.rdb.table.RdbSideParser; -import com.dtstack.flink.sql.table.AbstractTableInfo; +import com.dtstack.flink.sql.table.TableInfo; import java.util.Map; @@ -38,9 +37,8 @@ public class PostgresqlSideParser extends RdbSideParser { private static final String CURR_TYPE = "postgresql"; @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { - props.put(JdbcCheckKeys.DRIVER_NAME, "org.postgresql.Driver"); - AbstractTableInfo pgTableInfo = super.getTableInfo(tableName, fieldsInfo, props); + public TableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { + TableInfo pgTableInfo = super.getTableInfo(tableName, fieldsInfo, props); pgTableInfo.setType(CURR_TYPE); return pgTableInfo; } diff --git a/postgresql/postgresql-side/postgresql-side-core/src/test/java/com/dtstack/flink/sql/side/postgresql/table/PostgresqlSideParserTest.java b/postgresql/postgresql-side/postgresql-side-core/src/test/java/com/dtstack/flink/sql/side/postgresql/table/PostgresqlSideParserTest.java deleted file mode 100644 index 64c745a5a..000000000 --- a/postgresql/postgresql-side/postgresql-side-core/src/test/java/com/dtstack/flink/sql/side/postgresql/table/PostgresqlSideParserTest.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.dtstack.flink.sql.side.postgresql.table; - - -import com.dtstack.flink.sql.table.AbstractTableInfo; -import org.junit.Assert; -import org.junit.Test; - -import java.util.HashMap; -import java.util.Map; - -public class PostgresqlSideParserTest { - -// @Test - public void getTableInfo() { - PostgresqlSideParser sideParser = new PostgresqlSideParser(); - - final String tableName = "table_foo"; - final String fieldsInfo = "id INT, name VARCHAR, PRIMARY KEY (id)"; - - Map props = new HashMap(); - props.put("url", "jdbc:postgresql://foo:3306/db_foo"); - props.put("tablename", "table_foo"); - props.put("username", "foo"); - props.put("password", "foo"); - - AbstractTableInfo tableInfo= sideParser.getTableInfo(tableName, fieldsInfo, props); - - final String NORMAL_TYPE = "postgresql"; - final String table_type = tableInfo.getType(); - Assert.assertTrue(NORMAL_TYPE.equals(table_type)); - } - -} \ No newline at end of file diff --git a/postgresql/postgresql-sink/pom.xml b/postgresql/postgresql-sink/pom.xml index 6c29644db..d65368358 100644 --- a/postgresql/postgresql-sink/pom.xml +++ b/postgresql/postgresql-sink/pom.xml @@ -39,7 +39,6 @@ shade - false @@ -73,14 +72,14 @@ - + - + diff --git a/postgresql/postgresql-sink/src/main/java/com/dtstack/flink/sql/sink/postgresql/PostgresqlDialect.java b/postgresql/postgresql-sink/src/main/java/com/dtstack/flink/sql/sink/postgresql/PostgresqlDialect.java deleted file mode 100644 index a11f18674..000000000 --- a/postgresql/postgresql-sink/src/main/java/com/dtstack/flink/sql/sink/postgresql/PostgresqlDialect.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.postgresql; - - -import com.dtstack.flink.sql.sink.rdb.dialect.JDBCDialect; -import org.apache.commons.lang3.StringUtils; - -import java.util.Arrays; -import java.util.Optional; -import java.util.stream.Collectors; - -/** - * Date: 2020/1/3 - * Company: www.dtstack.com - * @author maqi - */ -public class PostgresqlDialect implements JDBCDialect { - @Override - public boolean canHandle(String url) { - return url.startsWith("jdbc:postgresql:"); - } - - @Override - public Optional defaultDriverName() { - return Optional.of("org.postgresql.Driver"); - } - - @Override - public Optional getUpsertStatement(String schema, String tableName, String[] fieldNames, String[] uniqueKeyFields, boolean allReplace) { - String uniqueColumns = Arrays.stream(uniqueKeyFields) - .map(this::quoteIdentifier) - .collect(Collectors.joining(", ")); - - String updateClause = Arrays.stream(fieldNames) - .filter(item -> !Arrays.asList(uniqueKeyFields).contains(item)) - .map(f -> quoteIdentifier(f) + "=EXCLUDED." + quoteIdentifier(f)) - .collect(Collectors.joining(", ")); - - if (StringUtils.isBlank(updateClause)) { - return Optional.of( - getInsertIntoStatement(schema, tableName, fieldNames, null) - + " ON CONFLICT (" - + uniqueColumns - + ") DO NOTHING"); - } - - return Optional.of(getInsertIntoStatement(schema, tableName, fieldNames, null) + - " ON CONFLICT (" + uniqueColumns + ")" + - " DO UPDATE SET " + updateClause - ); - - } - -} diff --git a/postgresql/postgresql-sink/src/main/java/com/dtstack/flink/sql/sink/postgresql/PostgresqlSink.java b/postgresql/postgresql-sink/src/main/java/com/dtstack/flink/sql/sink/postgresql/PostgresqlSink.java index 4dcf84dea..663816ca0 100644 --- a/postgresql/postgresql-sink/src/main/java/com/dtstack/flink/sql/sink/postgresql/PostgresqlSink.java +++ b/postgresql/postgresql-sink/src/main/java/com/dtstack/flink/sql/sink/postgresql/PostgresqlSink.java @@ -20,54 +20,92 @@ package com.dtstack.flink.sql.sink.postgresql; -import com.dtstack.flink.sql.enums.EUpdateMode; import com.dtstack.flink.sql.sink.IStreamSinkGener; -import com.dtstack.flink.sql.sink.postgresql.writer.CopyWriter; -import com.dtstack.flink.sql.sink.rdb.JDBCOptions; -import com.dtstack.flink.sql.sink.rdb.AbstractRdbSink; -import com.dtstack.flink.sql.sink.rdb.format.JDBCUpsertOutputFormat; -import com.dtstack.flink.sql.sink.rdb.writer.AbstractUpsertWriter; -import com.dtstack.flink.sql.sink.rdb.writer.JDBCWriter; +import com.dtstack.flink.sql.sink.postgresql.table.PostgresqlTableInfo; +import com.dtstack.flink.sql.sink.rdb.RdbSink; +import com.dtstack.flink.sql.sink.rdb.format.RetractJDBCOutputFormat; +import com.dtstack.flink.sql.table.TargetTableInfo; import org.apache.commons.lang3.StringUtils; +import java.util.List; +import java.util.Map; + /** - * @author maqi + * Date: 2019-08-22 + * Company: mmg + * + * @author tcm */ -public class PostgresqlSink extends AbstractRdbSink implements IStreamSinkGener { + +public class PostgresqlSink extends RdbSink implements IStreamSinkGener { + + private static final String POSTGRESQL_DRIVER = "org.postgresql.Driver"; + + private boolean isUpsert; + + private String keyField; + public PostgresqlSink() { - super(new PostgresqlDialect()); } @Override - public JDBCUpsertOutputFormat getOutputFormat() { - JDBCOptions jdbcOptions = JDBCOptions.builder() - .setDbUrl(dbUrl) - .setDialect(jdbcDialect) - .setUsername(userName) - .setPassword(password) - .setTableName(tableName) - .setSchema(schema) - .build(); - - return JDBCUpsertOutputFormat.builder() - .setOptions(jdbcOptions) - .setFieldNames(fieldNames) - .setFlushMaxSize(batchNum) - .setFlushIntervalMills(batchWaitInterval) - .setFieldTypes(sqlTypes) - .setKeyFields(primaryKeys) - .setAllReplace(allReplace) - .setUpdateMode(updateMode) - .setJDBCWriter(createJdbcWriter()) - .setErrorLimit(errorLimit) - .build(); + public RdbSink genStreamSink(TargetTableInfo targetTableInfo) { + PostgresqlTableInfo pgTableInfo = (PostgresqlTableInfo) targetTableInfo; + this.isUpsert = pgTableInfo.isUpsert(); + this.keyField = pgTableInfo.getKeyField(); + super.genStreamSink(targetTableInfo); + return this; + } + + @Override + public RetractJDBCOutputFormat getOutputFormat() { + return new RetractJDBCOutputFormat(); + } + + @Override + public void buildSql(String scheam, String tableName, List fields) { + buildInsertSql(tableName, fields); + } + + @Override + public String buildUpdateSql(String schema, String tableName, List fieldNames, Map> realIndexes, List fullField) { + return null; } - private JDBCWriter createJdbcWriter(){ - if (StringUtils.equalsIgnoreCase(updateMode, EUpdateMode.APPEND.name()) || primaryKeys == null || primaryKeys.size() == 0) { - return new CopyWriter(tableName, fieldNames, null, errorLimit); + + private void buildInsertSql(String tableName, List fields) { + StringBuffer sqlBuffer = new StringBuffer(); + + sqlBuffer.append("insert into ".concat(tableName) + .concat(" (") + .concat(StringUtils.join(fields, ",")) + .concat(") ") + ); + sqlBuffer.append("values ("); + StringBuffer upsertFields = new StringBuffer(); + for (String fieldName : fields) { + sqlBuffer.append("?,"); + if (this.isUpsert) { + if (fieldName.equals(this.keyField)) { + continue; + } + upsertFields.append(String.format("%s=excluded.%s,", fieldName, fieldName)); + } } - return AbstractUpsertWriter.create( - jdbcDialect, schema, tableName, fieldNames, sqlTypes, primaryKeys.toArray(new String[primaryKeys.size()]), null, - true, allReplace, null, errorLimit); + sqlBuffer.deleteCharAt(sqlBuffer.length() - 1); + sqlBuffer.append(")"); + + if (this.isUpsert) { + upsertFields.deleteCharAt(upsertFields.length() - 1); + sqlBuffer.append(" ON conflict(".concat(keyField).concat(")")); + sqlBuffer.append(" DO UPDATE SET "); + sqlBuffer.append(upsertFields); + } + this.sql = sqlBuffer.toString(); + } + + @Override + public String getDriverName() { + return POSTGRESQL_DRIVER; } + } diff --git a/postgresql/postgresql-sink/src/main/java/com/dtstack/flink/sql/sink/postgresql/table/PostgresqlSinkParser.java b/postgresql/postgresql-sink/src/main/java/com/dtstack/flink/sql/sink/postgresql/table/PostgresqlSinkParser.java index 9e9db93ee..f773b5a5c 100644 --- a/postgresql/postgresql-sink/src/main/java/com/dtstack/flink/sql/sink/postgresql/table/PostgresqlSinkParser.java +++ b/postgresql/postgresql-sink/src/main/java/com/dtstack/flink/sql/sink/postgresql/table/PostgresqlSinkParser.java @@ -19,9 +19,10 @@ package com.dtstack.flink.sql.sink.postgresql.table; -import com.dtstack.flink.sql.core.rdb.JdbcCheckKeys; import com.dtstack.flink.sql.sink.rdb.table.RdbSinkParser; -import com.dtstack.flink.sql.table.AbstractTableInfo; +import com.dtstack.flink.sql.table.TableInfo; +import com.dtstack.flink.sql.util.MathUtil; +import org.apache.commons.lang3.StringUtils; import java.util.Map; @@ -36,10 +37,27 @@ public class PostgresqlSinkParser extends RdbSinkParser { private static final String CURR_TYPE = "postgresql"; @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { - props.put(JdbcCheckKeys.DRIVER_NAME, "org.postgresql.Driver"); - AbstractTableInfo pgTableInfo = super.getTableInfo(tableName, fieldsInfo, props); - pgTableInfo.setType(CURR_TYPE); + public TableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { + PostgresqlTableInfo pgTableInfo = new PostgresqlTableInfo(); + pgTableInfo.setName(tableName); + parseFieldsInfo(fieldsInfo, pgTableInfo); + + pgTableInfo.setParallelism(MathUtil.getIntegerVal(props.get(PostgresqlTableInfo.PARALLELISM_KEY.toLowerCase()))); + pgTableInfo.setUrl(MathUtil.getString(props.get(PostgresqlTableInfo.URL_KEY.toLowerCase()))); + pgTableInfo.setTableName(MathUtil.getString(props.get(PostgresqlTableInfo.TABLE_NAME_KEY.toLowerCase()))); + pgTableInfo.setUserName(MathUtil.getString(props.get(PostgresqlTableInfo.USER_NAME_KEY.toLowerCase()))); + pgTableInfo.setPassword(MathUtil.getString(props.get(PostgresqlTableInfo.PASSWORD_KEY.toLowerCase()))); + pgTableInfo.setBatchSize(MathUtil.getIntegerVal(props.get(PostgresqlTableInfo.BATCH_SIZE_KEY.toLowerCase()))); + pgTableInfo.setBatchWaitInterval(MathUtil.getLongVal(props.get(PostgresqlTableInfo.BATCH_WAIT_INTERVAL_KEY.toLowerCase()))); + pgTableInfo.setBufferSize(MathUtil.getString(props.get(PostgresqlTableInfo.BUFFER_SIZE_KEY.toLowerCase()))); + pgTableInfo.setFlushIntervalMs(MathUtil.getString(props.get(PostgresqlTableInfo.FLUSH_INTERVALMS_KEY.toLowerCase()))); + + pgTableInfo.setKeyField(MathUtil.getString(props.get(PostgresqlTableInfo.TABLE_KEY_FIELD.toLowerCase()))); + + String isUpsertStr = (String) props.get(PostgresqlTableInfo.TABLE_IS_UPSERT.toLowerCase()); + pgTableInfo.setUpsert(!StringUtils.isEmpty(isUpsertStr) && isUpsertStr.equals("true") ? true : false); + + pgTableInfo.check(); return pgTableInfo; } } diff --git a/postgresql/postgresql-sink/src/main/java/com/dtstack/flink/sql/sink/postgresql/table/PostgresqlTableInfo.java b/postgresql/postgresql-sink/src/main/java/com/dtstack/flink/sql/sink/postgresql/table/PostgresqlTableInfo.java new file mode 100644 index 000000000..78df0de14 --- /dev/null +++ b/postgresql/postgresql-sink/src/main/java/com/dtstack/flink/sql/sink/postgresql/table/PostgresqlTableInfo.java @@ -0,0 +1,76 @@ +/* + * 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 com.dtstack.flink.sql.sink.postgresql.table; + +import com.dtstack.flink.sql.sink.rdb.table.RdbTableInfo; +import org.apache.flink.calcite.shaded.com.google.common.base.Preconditions; + +/** + * Date: 2019-08-22 + * Company: mmg + * + * @author tcm + */ + +public class PostgresqlTableInfo extends RdbTableInfo { + + public static final String TABLE_IS_UPSERT = "isUpsert"; + + public static final String TABLE_KEY_FIELD = "keyField"; + + private static final String CURR_TYPE = "postgresql"; + + private boolean isUpsert; + + private String keyField; + + + public PostgresqlTableInfo() { + setType(CURR_TYPE); + } + + public boolean isUpsert() { + return isUpsert; + } + + public void setUpsert(boolean upsert) { + isUpsert = upsert; + } + + public String getKeyField() { + return keyField; + } + + public void setKeyField(String keyField) { + this.keyField = keyField; + } + + @Override + public boolean check() { + Preconditions.checkNotNull(getUrl(), "postgresql field of URL is required"); + Preconditions.checkNotNull(getTableName(), "postgresql field of tableName is required"); + Preconditions.checkNotNull(getUserName(), "postgresql field of userName is required"); + Preconditions.checkNotNull(getPassword(), "postgresql field of password is required"); + if (isUpsert()) { + Preconditions.checkNotNull(getKeyField(), "postgresql field of keyField is required"); + } + return true; + } +} diff --git a/postgresql/postgresql-sink/src/main/java/com/dtstack/flink/sql/sink/postgresql/writer/CopyWriter.java b/postgresql/postgresql-sink/src/main/java/com/dtstack/flink/sql/sink/postgresql/writer/CopyWriter.java deleted file mode 100644 index 8c032ec39..000000000 --- a/postgresql/postgresql-sink/src/main/java/com/dtstack/flink/sql/sink/postgresql/writer/CopyWriter.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.postgresql.writer; - -import com.dtstack.flink.sql.outputformat.AbstractDtRichOutputFormat; -import com.dtstack.flink.sql.sink.rdb.writer.JDBCWriter; -import com.google.common.collect.Lists; -import org.apache.commons.collections.CollectionUtils; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.types.Row; -import org.postgresql.copy.CopyManager; -import org.postgresql.core.BaseConnection; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.ByteArrayInputStream; -import java.nio.charset.StandardCharsets; -import java.sql.Connection; -import java.sql.SQLException; -import java.util.List; - -/** - * Company: www.dtstack.com - * support pg copy mode - * - * @author dapeng - * @date 2020-09-21 - */ -public class CopyWriter implements JDBCWriter { - - private static final long serialVersionUID = 1L; - - private static final Logger LOG = LoggerFactory.getLogger(CopyWriter.class); - - private static final String COPY_SQL_TEMPL = "copy %s(%s) from stdin DELIMITER '%s' NULL as '%s'"; - - private static final String DEFAULT_FIELD_DELIM = "\001"; - - private static final String DEFAULT_NULL_DELIM = "\002"; - - private static final String LINE_DELIMITER = "\n"; - - private CopyManager copyManager; - - private transient List rows; - - private String copySql; - - private String tableName; - - private String[] fieldNames; - - /** - * dirty data count limit. Once count over limit then throw exception. - */ - private long errorLimit; - - // only use metric - private transient AbstractDtRichOutputFormat metricOutputFormat; - - public CopyWriter(String tableName, String[] fieldNames, AbstractDtRichOutputFormat metricOutputFormat, long errorLimit) { - this.tableName = tableName; - this.fieldNames = fieldNames; - this.metricOutputFormat = metricOutputFormat; - this.copySql = String.format(COPY_SQL_TEMPL, tableName, String.join(",", fieldNames), DEFAULT_FIELD_DELIM, DEFAULT_NULL_DELIM); - this.errorLimit = errorLimit; - } - - @Override - public void initMetricOutput(AbstractDtRichOutputFormat metricOutputFormat) { - this.metricOutputFormat = metricOutputFormat; - } - - @Override - public void open(Connection connection) throws SQLException { - copyManager = new CopyManager((BaseConnection) connection); - this.rows = Lists.newArrayList(); - } - - @Override - public void prepareStatement(Connection connection) throws SQLException { - - } - - @Override - public void addRecord(Tuple2 record) { - if (!record.f0) { - return; - } - rows.add(Row.copy(record.f1)); - } - - @Override - public void executeBatch(Connection connection) throws SQLException { - if(CollectionUtils.isEmpty(rows)){ - return; - } - //write with copy - StringBuilder sb = new StringBuilder(); - for (Row row : rows) { - int lastIndex = row.getArity() - 1; - for (int index = 0; index < row.getArity(); index++) { - Object rowData = row.getField(index); - sb.append(rowData == null ? DEFAULT_NULL_DELIM : rowData); - if (index != lastIndex) { - sb.append(DEFAULT_FIELD_DELIM); - } - } - sb.append(LINE_DELIMITER); - } - try { - ByteArrayInputStream bi = new ByteArrayInputStream(sb.toString().getBytes(StandardCharsets.UTF_8)); - copyManager.copyIn(copySql, bi); - connection.commit(); - rows.clear(); - } catch (Exception e) { - connection.rollback(); - connection.commit(); - executeUpdate(connection); - } - - } - - @Override - public void cleanBatchWhenError() throws SQLException { - - } - - @Override - public void executeUpdate(Connection connection) throws SQLException { - int index = 0; - StringBuilder sb = new StringBuilder(); - for (Row row : rows) { - try { - for (; index < row.getArity(); index++) { - Object rowData = row.getField(index); - sb.append(rowData) - .append(DEFAULT_FIELD_DELIM); - } - - String rowVal = sb.toString(); - ByteArrayInputStream bi = new ByteArrayInputStream(rowVal.getBytes(StandardCharsets.UTF_8)); - copyManager.copyIn(copySql, bi); - connection.commit(); - } catch (Exception e) { - dealExecuteError( - connection, - e, - metricOutputFormat, - row, - errorLimit, - LOG - ); - } - } - rows.clear(); - - } - - @Override - public void close() throws SQLException { - - } - -} diff --git a/postgresql/postgresql-sink/src/test/java/com/dtstack/flink/sql/sink/postgresql/PostgresqlDialectTest.java b/postgresql/postgresql-sink/src/test/java/com/dtstack/flink/sql/sink/postgresql/PostgresqlDialectTest.java deleted file mode 100644 index e3ecefb92..000000000 --- a/postgresql/postgresql-sink/src/test/java/com/dtstack/flink/sql/sink/postgresql/PostgresqlDialectTest.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.dtstack.flink.sql.sink.postgresql; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import static org.junit.Assert.*; - -public class PostgresqlDialectTest { - - PostgresqlDialect dialect; - - @Before - public void setUp() throws Exception { - dialect = new PostgresqlDialect(); - } - - @Test - public void testEasyUtils() { - final String s = "jdbc:postgresql://localhost:3306/foo_db"; - boolean r = dialect.canHandle(s); - Assert.assertTrue(r); - - String driver = dialect.defaultDriverName().get(); - Assert.assertTrue(driver.equals("org.postgresql.Driver")); - } - - @Test - public void testDialect() { - final String tableName = "table_foo"; - final String[] fieldNames = new String[] { - "id", - "name" - }; - final String[] uniqueKeyFields = new String[] { - "id", - }; - final String NORMAL_STMT = - "INSERT INTO \"table_foo\"(\"id\", \"name\") VALUES (?, ?) " + - "ON CONFLICT (\"id\") " + - "DO UPDATE SET \"id\"=EXCLUDED.\"id\", \"name\"=EXCLUDED.\"name\""; - - String upsertStmt = dialect - .getUpsertStatement("", tableName, fieldNames, uniqueKeyFields, false) - .get(); - - Assert.assertTrue(NORMAL_STMT.equals(upsertStmt)); - } - -} \ No newline at end of file diff --git a/postgresql/postgresql-sink/src/test/java/com/dtstack/flink/sql/sink/postgresql/PostgresqlSinkTest.java b/postgresql/postgresql-sink/src/test/java/com/dtstack/flink/sql/sink/postgresql/PostgresqlSinkTest.java deleted file mode 100644 index 9c5e077e6..000000000 --- a/postgresql/postgresql-sink/src/test/java/com/dtstack/flink/sql/sink/postgresql/PostgresqlSinkTest.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.dtstack.flink.sql.sink.postgresql; - -import com.dtstack.flink.sql.sink.rdb.dialect.JDBCDialect; -import com.dtstack.flink.sql.sink.rdb.format.JDBCUpsertOutputFormat; -import org.junit.Before; -import org.junit.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.powermock.api.support.membermodification.MemberModifier; - -import java.util.Optional; - -import static org.mockito.Mockito.when; - -public class PostgresqlSinkTest { - - @Mock - JDBCDialect jdbcDialect; - - @InjectMocks - PostgresqlSink sink = new PostgresqlSink();; - @Before - public void setUp () { - MockitoAnnotations.initMocks(this); - } - - @Test - public void testGetOutputFormat() throws IllegalAccessException { - when(jdbcDialect.defaultDriverName()).thenReturn(Optional.of("dd")); - - MemberModifier.field(PostgresqlSink.class, "dbUrl").set(sink, "foo"); - MemberModifier.field(PostgresqlSink.class, "jdbcDialect").set(sink, jdbcDialect); - MemberModifier.field(PostgresqlSink.class, "userName").set(sink, "foo"); - MemberModifier.field(PostgresqlSink.class, "password").set(sink, "foo"); - MemberModifier.field(PostgresqlSink.class, "tableName").set(sink, "foo"); - MemberModifier.field(PostgresqlSink.class, "fieldNames").set(sink, new String[]{"foo", "bar"}); - - JDBCUpsertOutputFormat format = sink.getOutputFormat(); - } - -} \ No newline at end of file diff --git a/postgresql/postgresql-sink/src/test/java/com/dtstack/flink/sql/sink/postgresql/table/PostgresqlSinkParserTest.java b/postgresql/postgresql-sink/src/test/java/com/dtstack/flink/sql/sink/postgresql/table/PostgresqlSinkParserTest.java deleted file mode 100644 index f6c02b74d..000000000 --- a/postgresql/postgresql-sink/src/test/java/com/dtstack/flink/sql/sink/postgresql/table/PostgresqlSinkParserTest.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.dtstack.flink.sql.sink.postgresql.table; - -import com.dtstack.flink.sql.table.AbstractTableInfo; -import org.junit.Assert; -import org.junit.Test; -import java.util.HashMap; -import java.util.Map; - -public class PostgresqlSinkParserTest { - -// @Test - public void getTableInfo() { - PostgresqlSinkParser sinkParser = new PostgresqlSinkParser(); - - final String tableName = "table_foo"; - final String fieldsInfo = "id INT, name VARCHAR"; - - Map props = new HashMap(); - props.put("url", "jdbc:mysql://foo:3306/db_foo"); - props.put("tablename", "table_foo"); - props.put("username", "foo"); - props.put("password", "foo"); - - AbstractTableInfo tableInfo= sinkParser.getTableInfo(tableName, fieldsInfo, props); - - final String NORMAL_TYPE = "postgresql"; - final String table_type = tableInfo.getType(); - Assert.assertTrue(NORMAL_TYPE.equals(table_type)); - } - -} \ No newline at end of file diff --git a/rdb/pom.xml b/rdb/pom.xml index 1969547af..5cd5d4187 100644 --- a/rdb/pom.xml +++ b/rdb/pom.xml @@ -15,48 +15,29 @@ rdb-side rdb-sink - rdb-core pom + 3.8.1 1.0-SNAPSHOT - - com.dtstack.flink - sql.core - ${sql.core.version} - provided + junit + junit + ${junit.version} + test - - com.dtstack.flink sql.core ${sql.core.version} - test-jar - test + provided - - - - org.apache.maven.plugins - maven-jar-plugin - - - - test-jar - - - - - - \ No newline at end of file diff --git a/rdb/rdb-core/pom.xml b/rdb/rdb-core/pom.xml deleted file mode 100644 index 32ad8b6c0..000000000 --- a/rdb/rdb-core/pom.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - sql.rdb - com.dtstack.flink - 1.0-SNAPSHOT - - 4.0.0 - - rdb-core - sql.core.rdb - - - 8 - 8 - - - \ No newline at end of file diff --git a/rdb/rdb-core/src/main/java/com/dtstack/flink/sql/core/rdb/JdbcCheckKeys.java b/rdb/rdb-core/src/main/java/com/dtstack/flink/sql/core/rdb/JdbcCheckKeys.java deleted file mode 100644 index 6eef874fa..000000000 --- a/rdb/rdb-core/src/main/java/com/dtstack/flink/sql/core/rdb/JdbcCheckKeys.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.core.rdb; - -/** - * @author tiezhu - * Date 2020-12-25 - * Company dtstack - */ -public class JdbcCheckKeys { - public static final String DRIVER_NAME = "driverName"; - public static final String URL_KEY = "url"; - public static final String USER_NAME_KEY = "userName"; - public static final String PASSWORD_KEY = "password"; - public static final String TABLE_TYPE_KEY = "tableType"; - public static final String NEED_CHECK = "needCheck"; - public static final String SCHEMA_KEY = "schema"; - public static final String TABLE_NAME_KEY = "tableName"; - // create 语句中的name - public static final String OPERATION_NAME_KEY = "operationName"; - // 用来检查update、replace等操作的column - public static final String COLUMN_KEY = "column"; - public static final String TABLE_INFO_KEY = "tableInfo"; -} diff --git a/rdb/rdb-core/src/main/java/com/dtstack/flink/sql/core/rdb/JdbcResourceCheck.java b/rdb/rdb-core/src/main/java/com/dtstack/flink/sql/core/rdb/JdbcResourceCheck.java deleted file mode 100644 index 541d59437..000000000 --- a/rdb/rdb-core/src/main/java/com/dtstack/flink/sql/core/rdb/JdbcResourceCheck.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.core.rdb; - -import com.dtstack.flink.sql.core.rdb.util.JdbcConnectionUtil; -import com.dtstack.flink.sql.resource.ResourceCheck; -import org.apache.commons.lang.StringUtils; -import org.apache.flink.runtime.execution.SuppressRestartsException; - -import java.sql.Connection; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -/** - * @author: chuixue - * @create: 2020-12-08 17:24 - * @description:jdbc资源检测 - **/ -public class JdbcResourceCheck extends ResourceCheck { - private static final String DELETE_STR = "delete"; - private static final String SELECT_STR = "select"; - private static final String INSERT_STR = "insert"; - private static final String UPDATE_STR = "update"; - private static final String REPLACE_STR = "replace"; - - private static final String CHECK_SELECT_SQL = "select 1 from $table where 1=2"; - private static final String CHECK_DELETE_SQL = "delete from $table where 1=3"; - private static final String CHECK_INSERT_SQL = "insert into $table (select * from $table where 1=2)"; - - private static final Map PRIVILEGE_SQL_MAP = new HashMap<>(); - private static final JdbcResourceCheck Instance = new JdbcResourceCheck(); - - static { - PRIVILEGE_SQL_MAP.put(SELECT_STR, CHECK_SELECT_SQL); - PRIVILEGE_SQL_MAP.put(DELETE_STR, CHECK_DELETE_SQL); - PRIVILEGE_SQL_MAP.put(INSERT_STR, CHECK_INSERT_SQL); - } - - private JdbcResourceCheck() { - } - - public static JdbcResourceCheck getInstance() { - return Instance; - } - - @Override - public void checkResourceStatus(Map checkProperties) { - if (!NEED_CHECK || !Boolean.parseBoolean(checkProperties.get(JdbcCheckKeys.NEED_CHECK))) { - LOG.warn("Ignore checking [{}] type data source , tableName is [{}]." - , checkProperties.get(JdbcCheckKeys.TABLE_TYPE_KEY) - , checkProperties.get(JdbcCheckKeys.TABLE_NAME_KEY)); - return; - } - - LOG.info("start checking [{}] type data source , tableName is [{}]." - , checkProperties.get(JdbcCheckKeys.TABLE_TYPE_KEY) - , checkProperties.get(JdbcCheckKeys.TABLE_NAME_KEY)); - List privilegeList = new ArrayList<>(); - if (checkProperties.get(TABLE_TYPE_KEY).equalsIgnoreCase(SIDE_STR)) { - privilegeList.add(SELECT_STR); - } - if (checkProperties.get(TABLE_TYPE_KEY).equalsIgnoreCase(SINK_STR)) { - privilegeList.add(INSERT_STR); - // privilegeList.add(DELETE_STR); - } - checkPrivilege( - checkProperties.get(JdbcCheckKeys.DRIVER_NAME) - , checkProperties.get(JdbcCheckKeys.URL_KEY) - , checkProperties.get(JdbcCheckKeys.USER_NAME_KEY) - , checkProperties.get(JdbcCheckKeys.PASSWORD_KEY) - , checkProperties.get(JdbcCheckKeys.TABLE_NAME_KEY) - , checkProperties.get(JdbcCheckKeys.SCHEMA_KEY) - , privilegeList - ); - LOG.info("data source is available and user [{}] has the corresponding permissions {} for [{}] type , tableName is [{}]" - , checkProperties.get(JdbcCheckKeys.USER_NAME_KEY) - , privilegeList.toString() - , checkProperties.get(JdbcCheckKeys.TABLE_TYPE_KEY) - , checkProperties.get(JdbcCheckKeys.TABLE_NAME_KEY)); - } - - public void checkPrivilege( - String driverName - , String url - , String userName - , String password - , String tableName - , String schema - , List privilegeList) { - Connection connection = - JdbcConnectionUtil.getConnectionWithRetry(driverName, url, userName, password); - Statement statement = null; - String tableInfo = Objects.isNull(schema) ? tableName : schema + "." + tableName; - String privilege = null; - try { - statement = connection.createStatement(); - for (String s : privilegeList) { - privilege = s; - statement.execute( - StringUtils.replace( - PRIVILEGE_SQL_MAP.get(privilege.toLowerCase()), - "$table", - tableName - ) - ); - } - } catch (SQLException sqlException) { - if (sqlException.getMessage().contains("command denied")) { - throw new SuppressRestartsException(new Throwable( - String.format("user [%s] don't have [%s] privilege of table [%s]", userName, privilege, tableInfo))); - } - - throw new SuppressRestartsException(new IllegalArgumentException(sqlException.getMessage())); - } finally { - JdbcConnectionUtil.closeConnectionResource(null, statement, connection, false); - } - } -} diff --git a/rdb/rdb-core/src/main/java/com/dtstack/flink/sql/core/rdb/util/JdbcConnectionUtil.java b/rdb/rdb-core/src/main/java/com/dtstack/flink/sql/core/rdb/util/JdbcConnectionUtil.java deleted file mode 100644 index 57fc26cf2..000000000 --- a/rdb/rdb-core/src/main/java/com/dtstack/flink/sql/core/rdb/util/JdbcConnectionUtil.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.core.rdb.util; - -import com.dtstack.flink.sql.classloader.ClassLoaderManager; -import com.dtstack.flink.sql.exception.ExceptionTrace; -import com.dtstack.flink.sql.util.ThreadUtil; -import com.google.common.base.Preconditions; -import org.apache.flink.runtime.execution.SuppressRestartsException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.Objects; - -/** - * @author tiezhu - * Date 2020-12-25 - * Company dtstack - */ -public class JdbcConnectionUtil { - private static final int DEFAULT_RETRY_NUM = 3; - private static final long DEFAULT_RETRY_TIME_WAIT = 3L; - private static final int DEFAULT_VALID_TIME = 10; - private static final Logger LOG = LoggerFactory.getLogger(JdbcConnectionUtil.class); - - /** - * 关闭连接资源 - * - * @param rs ResultSet - * @param stmt Statement - * @param conn Connection - * @param commit 手动提交事务 - */ - public static void closeConnectionResource( - ResultSet rs - , Statement stmt - , Connection conn - , boolean commit) { - if (Objects.nonNull(rs)) { - try { - rs.close(); - } catch (SQLException e) { - LOG.warn("Close resultSet error: {}", e.getMessage()); - } - } - - if (Objects.nonNull(stmt)) { - try { - stmt.close(); - } catch (SQLException e) { - LOG.warn("Close statement error:{}", e.getMessage()); - } - } - - if (Objects.nonNull(conn)) { - try { - if (commit) { - commit(conn); - } else { - rollBack(conn); - } - - conn.close(); - } catch (SQLException e) { - LOG.warn("Close connection error:{}", e.getMessage()); - } - } - } - - /** - * 手动提交事物 - * - * @param conn Connection - */ - public static void commit(Connection conn) { - try { - if (!conn.isClosed() && conn.isValid(DEFAULT_VALID_TIME) && !conn.getAutoCommit()) { - conn.commit(); - } - } catch (SQLException e) { - LOG.warn("commit error:{}", e.getMessage()); - } - } - - /** - * 手动回滚事物 - * - * @param conn Connection - */ - public static void rollBack(Connection conn) { - try { - if (!conn.isClosed() && conn.isValid(DEFAULT_VALID_TIME) && !conn.getAutoCommit()) { - conn.rollback(); - } - } catch (SQLException e) { - LOG.warn("rollBack error:{}", e.getMessage()); - } - } - - /** - * get connection from datasource and retry when failed. - * - * @param driverName driver name for rdb datasource - * @param url connect url - * @param userName connect user name - * @param password password for user name - * @return a valid connection - */ - public static Connection getConnectionWithRetry(String driverName, - String url, - String userName, - String password) { - String message = "Get connection failed. " + - "\nurl: [%s]" + - "\nuserName: [%s]" + - "\ncause: [%s]"; - String errorCause; - String errorMessage = ""; - - ClassLoaderManager.forName(driverName, JdbcConnectionUtil.class.getClassLoader()); - Preconditions.checkNotNull(url, "url can't be null!"); - - for (int i = 0; i < DEFAULT_RETRY_NUM; i++) { - try { - Connection connection = - Objects.isNull(userName) ? - DriverManager.getConnection(url) : - DriverManager.getConnection(url, userName, password); - connection.setAutoCommit(false); - return connection; - } catch (Exception e) { - errorCause = ExceptionTrace.traceOriginalCause(e); - errorMessage = String.format( - message, - url, - userName, - errorCause - ); - LOG.warn(errorMessage); - LOG.warn("Connect will retry after [{}] s. Retry time [{}] ...", DEFAULT_RETRY_TIME_WAIT, i + 1); - ThreadUtil.sleepSeconds(DEFAULT_RETRY_TIME_WAIT); - } - } - throw new SuppressRestartsException(new SQLException(errorMessage)); - } -} diff --git a/rdb/rdb-side/pom.xml b/rdb/rdb-side/pom.xml index 5a7f7c99b..c7350877f 100644 --- a/rdb/rdb-side/pom.xml +++ b/rdb/rdb-side/pom.xml @@ -16,7 +16,7 @@ jar - 3.9.4 + 3.5.2 @@ -35,12 +35,6 @@ ${vertx.version} - - com.dtstack.flink - sql.core.rdb - 1.0-SNAPSHOT - - diff --git a/rdb/rdb-side/src/main/java/com/dtstack/flink/sql/side/rdb/all/AbstractRdbAllReqRow.java b/rdb/rdb-side/src/main/java/com/dtstack/flink/sql/side/rdb/all/AbstractRdbAllReqRow.java deleted file mode 100644 index 49d84b566..000000000 --- a/rdb/rdb-side/src/main/java/com/dtstack/flink/sql/side/rdb/all/AbstractRdbAllReqRow.java +++ /dev/null @@ -1,228 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.rdb.all; - -import com.dtstack.flink.sql.core.rdb.JdbcResourceCheck; -import com.dtstack.flink.sql.core.rdb.util.JdbcConnectionUtil; -import com.dtstack.flink.sql.side.BaseAllReqRow; -import com.dtstack.flink.sql.side.BaseSideInfo; -import com.dtstack.flink.sql.side.rdb.table.RdbSideTableInfo; -import com.dtstack.flink.sql.side.rdb.util.SwitchUtil; -import com.dtstack.flink.sql.util.RowDataComplete; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import org.apache.calcite.sql.JoinType; -import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.configuration.Configuration; -import org.apache.flink.table.dataformat.BaseRow; -import org.apache.flink.table.dataformat.GenericRow; -import org.apache.flink.table.typeutils.TimeIndicatorTypeInfo; -import org.apache.flink.util.Collector; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.sql.Timestamp; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicReference; -import java.util.stream.Collectors; - -/** - * side operator with cache for all(period reload) - * Date: 2018/11/26 - * Company: www.dtstack.com - * - * @author maqi - */ - -public abstract class AbstractRdbAllReqRow extends BaseAllReqRow { - - private static final long serialVersionUID = 2098635140857937718L; - - private static final Logger LOG = LoggerFactory.getLogger(AbstractRdbAllReqRow.class); - - private static final int CONN_RETRY_NUM = 3; - - private static final int DEFAULT_FETCH_SIZE = 1000; - private static volatile boolean resourceCheck = true; - private final AtomicReference>>> cacheRef = new AtomicReference<>(); - - public AbstractRdbAllReqRow(BaseSideInfo sideInfo) { - super(sideInfo); - } - - @Override - public void open(Configuration parameters) throws Exception { - RdbSideTableInfo tableInfo = (RdbSideTableInfo) sideInfo.getSideTableInfo(); - synchronized (AbstractRdbAllReqRow.class) { - if (resourceCheck) { - resourceCheck = false; - JdbcResourceCheck.getInstance().checkResourceStatus(tableInfo.getCheckProperties()); - } - } - super.open(parameters); - LOG.info("rdb dim table config info: {} ", tableInfo.toString()); - } - - @Override - protected void initCache() throws SQLException { - Map>> newCache = Maps.newConcurrentMap(); - cacheRef.set(newCache); - loadData(newCache); - } - - @Override - protected void reloadCache() { - //reload cacheRef and replace to old cacheRef - Map>> newCache = Maps.newConcurrentMap(); - try { - loadData(newCache); - } catch (SQLException e) { - throw new RuntimeException(e); - } - cacheRef.set(newCache); - LOG.info("----- rdb all cacheRef reload end:{}", Calendar.getInstance()); - } - - @Override - public void flatMap(BaseRow value, Collector out) throws Exception { - GenericRow genericRow = (GenericRow) value; - List equalValIndex = sideInfo.getEqualValIndex(); - ArrayList inputParams = equalValIndex.stream() - .map(genericRow::getField) - .collect(Collectors.toCollection(ArrayList::new)); - - if (inputParams.size() != equalValIndex.size() && sideInfo.getJoinType() == JoinType.LEFT) { - BaseRow row = fillData(value, null); - RowDataComplete.collectBaseRow(out, row); - return; - } - - String cacheKey = inputParams.stream() - .map(String::valueOf) - .collect(Collectors.joining("_")); - - List> cacheList = cacheRef.get().get(cacheKey); - if (CollectionUtils.isEmpty(cacheList) && sideInfo.getJoinType() == JoinType.LEFT) { - BaseRow row = fillData(value, null); - RowDataComplete.collectBaseRow(out, row); - } else if (!CollectionUtils.isEmpty(cacheList)) { - cacheList.forEach(one -> RowDataComplete.collectBaseRow(out, fillData(value, one))); - } - } - - /** - * covert flink time attribute.Type information for indicating event or processing time. - * However, it behaves like a regular SQL timestamp but is serialized as Long. - * - * @param entry - * @param obj - * @return - */ - @Override - protected Object dealTimeAttributeType(Class entry, Object obj) { - boolean isTimeIndicatorTypeInfo = TimeIndicatorTypeInfo.class.isAssignableFrom(entry); - if (obj instanceof LocalDateTime && isTimeIndicatorTypeInfo) { - //去除上一层OutputRowtimeProcessFunction 调用时区导致的影响 - obj = ((Timestamp) obj).getTime() + (long) LOCAL_TZ.getOffset(((Timestamp) obj).getTime()); - } - return obj; - } - - private void loadData(Map>> tmpCache) throws SQLException { - queryAndFillData(tmpCache, getConnectionWithRetry((RdbSideTableInfo) sideInfo.getSideTableInfo())); - } - - private Connection getConnectionWithRetry(RdbSideTableInfo tableInfo) throws SQLException { - String connInfo = "url:" + tableInfo.getUrl() + "; userName:" + tableInfo.getUserName(); - String errorMsg = null; - for (int i = 0; i < CONN_RETRY_NUM; i++) { - try { - return getConn(tableInfo.getUrl(), tableInfo.getUserName(), tableInfo.getPassword()); - } catch (Exception e) { - try { - LOG.warn("get conn fail, wait for 5 sec and try again, connInfo:" + connInfo); - errorMsg = e.getCause().toString(); - Thread.sleep(5 * 1000); - } catch (InterruptedException e1) { - LOG.error("", e1); - } - } - } - throw new SQLException("get conn fail. connInfo: " + connInfo + "\ncause by: " + errorMsg); - } - - private void queryAndFillData(Map>> tmpCache, Connection connection) throws SQLException { - //load data from table - String sql = sideInfo.getSqlCondition(); - Statement statement = connection.createStatement(); - statement.setFetchSize(getFetchSize()); - ResultSet resultSet = statement.executeQuery(sql); - - String[] sideFieldNames = StringUtils.split(sideInfo.getSideSelectFields(), ","); - String[] sideFieldTypes = sideInfo.getSideTableInfo().getFieldTypes(); - String[] fields = sideInfo.getSideTableInfo().getFields(); - Map sideFieldNamesAndTypes = Maps.newHashMap(); - for (int i = 0; i < fields.length; i++) { - sideFieldNamesAndTypes.put(fields[i], sideFieldTypes[i]); - } - - while (resultSet.next()) { - Map oneRow = Maps.newHashMap(); - for (String fieldName : sideFieldNames) { - Object object = resultSet.getObject(fieldName.trim()); - object = SwitchUtil.getTarget(object, sideFieldNamesAndTypes.get(fieldName)); - oneRow.put(fieldName.trim(), object); - } - - String cacheKey = sideInfo.getEqualFieldList().stream() - .map(oneRow::get) - .map(String::valueOf) - .collect(Collectors.joining("_")); - - tmpCache.computeIfAbsent(cacheKey, key -> Lists.newArrayList()) - .add(oneRow); - } - JdbcConnectionUtil.closeConnectionResource(resultSet, statement, connection, false); - } - - public int getFetchSize() { - return DEFAULT_FETCH_SIZE; - } - - /** - * get jdbc connection - * - * @param dbURL - * @param userName - * @param password - * @return - */ - public abstract Connection getConn(String dbURL, String userName, String password); - -} diff --git a/rdb/rdb-side/src/main/java/com/dtstack/flink/sql/side/rdb/all/RdbAllReqRow.java b/rdb/rdb-side/src/main/java/com/dtstack/flink/sql/side/rdb/all/RdbAllReqRow.java new file mode 100644 index 000000000..5fc7ba158 --- /dev/null +++ b/rdb/rdb-side/src/main/java/com/dtstack/flink/sql/side/rdb/all/RdbAllReqRow.java @@ -0,0 +1,228 @@ +/* + * 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 com.dtstack.flink.sql.side.rdb.all; + +import com.dtstack.flink.sql.side.AllReqRow; +import com.dtstack.flink.sql.side.SideInfo; +import com.dtstack.flink.sql.side.rdb.table.RdbSideTableInfo; +import com.dtstack.flink.sql.side.rdb.util.SwitchUtil; +import org.apache.calcite.sql.JoinType; +import org.apache.commons.collections.CollectionUtils; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import org.apache.flink.table.typeutils.TimeIndicatorTypeInfo; +import org.apache.flink.types.Row; +import org.apache.flink.util.Collector; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.sql.Timestamp; +import java.util.Calendar; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; + +/** + * side operator with cache for all(period reload) + * Date: 2018/11/26 + * Company: www.dtstack.com + * + * @author maqi + */ + +public abstract class RdbAllReqRow extends AllReqRow { + + private static final long serialVersionUID = 2098635140857937718L; + + private static final Logger LOG = LoggerFactory.getLogger(RdbAllReqRow.class); + + private static final int CONN_RETRY_NUM = 3; + + private AtomicReference>>> cacheRef = new AtomicReference<>(); + + public RdbAllReqRow(SideInfo sideInfo) { + super(sideInfo); + } + + @Override + public Row fillData(Row input, Object sideInput) { + Map cacheInfo = (Map) sideInput; + Row row = new Row(sideInfo.getOutFieldInfoList().size()); + for (Map.Entry entry : sideInfo.getInFieldIndex().entrySet()) { + Object obj = input.getField(entry.getValue()); + boolean isTimeIndicatorTypeInfo = TimeIndicatorTypeInfo.class.isAssignableFrom(sideInfo.getRowTypeInfo().getTypeAt(entry.getValue()).getClass()); + + //Type information for indicating event or processing time. However, it behaves like a regular SQL timestamp but is serialized as Long. + if (obj instanceof Timestamp && isTimeIndicatorTypeInfo) { + obj = ((Timestamp) obj).getTime(); + } + + row.setField(entry.getKey(), obj); + } + + for (Map.Entry entry : sideInfo.getSideFieldNameIndex().entrySet()) { + if (cacheInfo == null) { + row.setField(entry.getKey(), null); + } else { + row.setField(entry.getKey(), cacheInfo.get(entry.getValue())); + } + } + + return row; + } + + @Override + protected void initCache() throws SQLException { + Map>> newCache = Maps.newConcurrentMap(); + cacheRef.set(newCache); + loadData(newCache); + } + + @Override + protected void reloadCache() { + //reload cacheRef and replace to old cacheRef + Map>> newCache = Maps.newConcurrentMap(); + try { + loadData(newCache); + } catch (SQLException e) { + LOG.error("", e); + } + + cacheRef.set(newCache); + LOG.info("----- rdb all cacheRef reload end:{}", Calendar.getInstance()); + } + + + @Override + public void flatMap(Row value, Collector out) throws Exception { + List inputParams = Lists.newArrayList(); + for (Integer conValIndex : sideInfo.getEqualValIndex()) { + Object equalObj = value.getField(conValIndex); + if (equalObj == null) { + if (sideInfo.getJoinType() == JoinType.LEFT) { + Row row = fillData(value, null); + out.collect(row); + } + return; + } + inputParams.add(equalObj); + } + + String key = buildKey(inputParams); + List> cacheList = cacheRef.get().get(key); + if (CollectionUtils.isEmpty(cacheList)) { + if (sideInfo.getJoinType() == JoinType.LEFT) { + Row row = fillData(value, null); + out.collect(row); + } else { + return; + } + + return; + } + + for (Map one : cacheList) { + out.collect(fillData(value, one)); + } + + } + + private String buildKey(List equalValList) { + StringBuilder sb = new StringBuilder(""); + for (Object equalVal : equalValList) { + sb.append(equalVal).append("_"); + } + + return sb.toString(); + } + + private String buildKey(Map val, List equalFieldList) { + StringBuilder sb = new StringBuilder(""); + for (String equalField : equalFieldList) { + sb.append(val.get(equalField)).append("_"); + } + + return sb.toString(); + } + + public abstract Connection getConn(String dbURL, String userName, String password); + + + private void loadData(Map>> tmpCache) throws SQLException { + RdbSideTableInfo tableInfo = (RdbSideTableInfo) sideInfo.getSideTableInfo(); + Connection connection = null; + + try { + for (int i = 0; i < CONN_RETRY_NUM; i++) { + try { + connection = getConn(tableInfo.getUrl(), tableInfo.getUserName(), tableInfo.getPassword()); + break; + } catch (Exception e) { + if (i == CONN_RETRY_NUM - 1) { + throw new RuntimeException("", e); + } + try { + String connInfo = "url:" + tableInfo.getUrl() + ";userName:" + tableInfo.getUserName() + ",pwd:" + tableInfo.getPassword(); + LOG.warn("get conn fail, wait for 5 sec and try again, connInfo:" + connInfo); + Thread.sleep(5 * 1000); + } catch (InterruptedException e1) { + e1.printStackTrace(); + } + } + + } + + //load data from table + String sql = sideInfo.getSqlCondition(); + Statement statement = connection.createStatement(); + statement.setFetchSize(getFetchSize()); + ResultSet resultSet = statement.executeQuery(sql); + String[] sideFieldNames = sideInfo.getSideSelectFields().split(","); + String[] fields = sideInfo.getSideTableInfo().getFieldTypes(); + while (resultSet.next()) { + Map oneRow = Maps.newHashMap(); + for (String fieldName : sideFieldNames) { + Object object = resultSet.getObject(fieldName.trim()); + int fieldIndex = sideInfo.getSideTableInfo().getFieldList().indexOf(fieldName.trim()); + object = SwitchUtil.getTarget(object, fields[fieldIndex]); + oneRow.put(fieldName.trim(), object); + } + + String cacheKey = buildKey(oneRow, sideInfo.getEqualFieldList()); + List> list = tmpCache.computeIfAbsent(cacheKey, key -> Lists.newArrayList()); + list.add(oneRow); + } + } catch (Exception e) { + LOG.error("", e); + } finally { + if (connection != null) { + connection.close(); + } + } + } + + public int getFetchSize() { + return 1000; + } + +} diff --git a/rdb/rdb-side/src/main/java/com/dtstack/flink/sql/side/rdb/all/RdbAllSideInfo.java b/rdb/rdb-side/src/main/java/com/dtstack/flink/sql/side/rdb/all/RdbAllSideInfo.java index 5a7d9ae84..c10b394e5 100644 --- a/rdb/rdb-side/src/main/java/com/dtstack/flink/sql/side/rdb/all/RdbAllSideInfo.java +++ b/rdb/rdb-side/src/main/java/com/dtstack/flink/sql/side/rdb/all/RdbAllSideInfo.java @@ -18,25 +18,18 @@ package com.dtstack.flink.sql.side.rdb.all; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.BaseSideInfo; import com.dtstack.flink.sql.side.FieldInfo; import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.PredicateInfo; +import com.dtstack.flink.sql.side.SideInfo; +import com.dtstack.flink.sql.side.SideTableInfo; import com.dtstack.flink.sql.side.rdb.table.RdbSideTableInfo; import com.dtstack.flink.sql.util.ParseUtils; -import com.google.common.collect.Lists; import org.apache.calcite.sql.SqlNode; import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.lang3.StringUtils; import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.google.common.collect.Lists; import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.stream.Collectors; /** * Reason: @@ -46,50 +39,21 @@ * @author maqi */ -public class RdbAllSideInfo extends BaseSideInfo { +public class RdbAllSideInfo extends SideInfo { private static final long serialVersionUID = -5858335638589472159L; - private static final Logger LOG = LoggerFactory.getLogger(RdbAllSideInfo.class.getSimpleName()); - public RdbAllSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { + public RdbAllSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, SideTableInfo sideTableInfo) { super(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); } @Override - public void buildEqualInfo(JoinInfo joinInfo, AbstractSideTableInfo sideTableInfo) { + public void buildEqualInfo(JoinInfo joinInfo, SideTableInfo sideTableInfo) { RdbSideTableInfo rdbSideTableInfo = (RdbSideTableInfo) sideTableInfo; - List selectFields = Lists.newArrayList(); - Map physicalFields = rdbSideTableInfo.getPhysicalFields(); - physicalFields.keySet().forEach( - item -> { - if (Objects.isNull(physicalFields.get(item))) { - selectFields.add(quoteIdentifier(item)); - } else { - selectFields.add(quoteIdentifier(physicalFields.get(item)) + " AS " + quoteIdentifier(item)); - } - } - ); - sqlCondition = getSelectFromStatement(getTableName(rdbSideTableInfo), selectFields, sideTableInfo.getPredicateInfoes()); - LOG.info("--------dimension sql query-------\n{}" + sqlCondition); - } - - public String getAdditionalWhereClause() { - return ""; - } - - private String getSelectFromStatement(String tableName, List selectFields, List predicateInfoes) { - String fromClause = String.join(", ", selectFields); - String predicateClause = predicateInfoes.stream().map(this::buildFilterCondition).collect(Collectors.joining(" AND ")); - String whereClause = buildWhereClause(predicateClause); - return "SELECT " + fromClause + " FROM " + tableName + whereClause; - } - private String buildWhereClause(String predicateClause) { - String additionalWhereClause = getAdditionalWhereClause(); - String whereClause = (!StringUtils.isEmpty(predicateClause) || !StringUtils.isEmpty(additionalWhereClause) ? " WHERE " + predicateClause : ""); - whereClause += (StringUtils.isEmpty(predicateClause)) ? additionalWhereClause.replaceFirst("AND", "") : additionalWhereClause; - return whereClause; + sqlCondition = "select ${selectField} from ${tableName} "; + sqlCondition = sqlCondition.replace("${tableName}", rdbSideTableInfo.getTableName()).replace("${selectField}", sideSelectFields); } @Override @@ -143,29 +107,4 @@ public void parseSelectFields(JoinInfo joinInfo) { sideSelectFields = String.join(",", fields); } - - public String buildFilterCondition(PredicateInfo info) { - switch (info.getOperatorKind()) { - case "IN": - case "NOT_IN": - return quoteIdentifier(info.getFieldName()) + " " + info.getOperatorName() + " ( " + info.getCondition() + " )"; - case "NOT_EQUALS": - return quoteIdentifier(info.getFieldName()) + " != " + info.getCondition(); - case "BETWEEN": - return quoteIdentifier(info.getFieldName()) + " BETWEEN " + info.getCondition(); - case "IS_NOT_NULL": - case "IS_NULL": - return quoteIdentifier(info.getFieldName()) + " " + info.getOperatorName(); - default: - return quoteIdentifier(info.getFieldName()) + " " + info.getOperatorName() + " " + info.getCondition(); - } - } - - public String getTableName(RdbSideTableInfo rdbSideTableInfo) { - return rdbSideTableInfo.getTableName(); - } - - public String quoteIdentifier(String identifier) { - return " " + identifier + " "; - } } diff --git a/rdb/rdb-side/src/main/java/com/dtstack/flink/sql/side/rdb/async/RdbAsyncReqRow.java b/rdb/rdb-side/src/main/java/com/dtstack/flink/sql/side/rdb/async/RdbAsyncReqRow.java index 2aeed79d1..d997f7d58 100644 --- a/rdb/rdb-side/src/main/java/com/dtstack/flink/sql/side/rdb/async/RdbAsyncReqRow.java +++ b/rdb/rdb-side/src/main/java/com/dtstack/flink/sql/side/rdb/async/RdbAsyncReqRow.java @@ -19,51 +19,23 @@ package com.dtstack.flink.sql.side.rdb.async; -import com.dtstack.flink.sql.core.rdb.JdbcResourceCheck; import com.dtstack.flink.sql.enums.ECacheContentType; -import com.dtstack.flink.sql.exception.ExceptionTrace; -import com.dtstack.flink.sql.factory.DTThreadFactory; -import com.dtstack.flink.sql.side.BaseAsyncReqRow; -import com.dtstack.flink.sql.side.BaseSideInfo; -import com.dtstack.flink.sql.side.CacheMissVal; +import com.dtstack.flink.sql.side.*; import com.dtstack.flink.sql.side.cache.CacheObj; -import com.dtstack.flink.sql.side.rdb.table.RdbSideTableInfo; import com.dtstack.flink.sql.side.rdb.util.SwitchUtil; -import com.dtstack.flink.sql.util.DateUtil; -import com.dtstack.flink.sql.util.RowDataComplete; -import com.dtstack.flink.sql.util.ThreadUtil; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import io.vertx.core.AsyncResult; -import io.vertx.core.Handler; -import io.vertx.core.Vertx; -import io.vertx.core.VertxOptions; import io.vertx.core.json.JsonArray; -import io.vertx.core.json.JsonObject; -import io.vertx.ext.jdbc.JDBCClient; import io.vertx.ext.sql.SQLClient; import io.vertx.ext.sql.SQLConnection; -import org.apache.commons.lang3.StringUtils; -import org.apache.flink.configuration.Configuration; -import org.apache.flink.runtime.execution.SuppressRestartsException; +import com.google.common.collect.Lists; import org.apache.flink.streaming.api.functions.async.ResultFuture; -import org.apache.flink.table.dataformat.BaseRow; -import org.apache.flink.table.dataformat.GenericRow; +import org.apache.flink.table.typeutils.TimeIndicatorTypeInfo; +import org.apache.flink.types.Row; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.math.BigDecimal; import java.sql.Timestamp; -import java.time.Instant; import java.util.List; import java.util.Map; -import java.util.Objects; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicLong; /** * Date: 2018/11/26 @@ -72,7 +44,7 @@ * @author maqi */ -public class RdbAsyncReqRow extends BaseAsyncReqRow { +public class RdbAsyncReqRow extends AsyncReqRow { private static final long serialVersionUID = 2098635244857937720L; @@ -82,9 +54,7 @@ public class RdbAsyncReqRow extends BaseAsyncReqRow { public final static int DEFAULT_VERTX_WORKER_POOL_SIZE = Runtime.getRuntime().availableProcessors() * 2; - public final static int DEFAULT_DB_CONN_POOL_SIZE = DEFAULT_VERTX_EVENT_LOOP_POOL_SIZE + DEFAULT_VERTX_WORKER_POOL_SIZE; - - public final static int MAX_DB_CONN_POOL_SIZE_LIMIT = 5; + public final static int DEFAULT_MAX_DB_CONN_POOL_SIZE = DEFAULT_VERTX_EVENT_LOOP_POOL_SIZE + DEFAULT_VERTX_WORKER_POOL_SIZE; public final static int DEFAULT_IDLE_CONNECTION_TEST_PEROID = 60; @@ -92,248 +62,113 @@ public class RdbAsyncReqRow extends BaseAsyncReqRow { public final static String DT_PROVIDER_CLASS = "com.dtstack.flink.sql.side.rdb.provider.DTC3P0DataSourceProvider"; - public final static String PREFERRED_TEST_QUERY_SQL = "SELECT 1 FROM DUAL"; - - private transient SQLClient rdbSqlClient; - - private transient Vertx vertx; - - private int asyncPoolSize = 1; - - private final int errorLogPrintNum = 3; - - private final AtomicBoolean connectionStatus = new AtomicBoolean(true); + public final static String PREFERRED_TEST_QUERY_SQL = "select 1 from dual"; - private static volatile boolean resourceCheck = false; + private transient SQLClient rdbSQLClient; - private transient ThreadPoolExecutor executor; - - // 共享条件:1.一个维表多个并行度在一个tm上可以共享,2.多个同种类型维表单个并行度、多个并行度在一个tm上可以共享 - protected static Map rdbSqlClientPool = Maps.newConcurrentMap(); - // 同种类型维表以url为单位,在同一个tm中只有一个连接池 - private String url ; - - private final static int MAX_TASK_QUEUE_SIZE = 100000; - - public RdbAsyncReqRow(BaseSideInfo sideInfo) { + public RdbAsyncReqRow(SideInfo sideInfo) { super(sideInfo); - init(sideInfo); - } - - @Override - public void open(Configuration parameters) throws Exception { - RdbSideTableInfo rdbSideTableInfo = (RdbSideTableInfo) sideInfo.getSideTableInfo(); - synchronized (RdbAsyncReqRow.class) { - if (resourceCheck) { - resourceCheck = false; - JdbcResourceCheck.getInstance().checkResourceStatus(rdbSideTableInfo.getCheckProperties()); - } - } - super.open(parameters); - - VertxOptions vertxOptions = new VertxOptions(); - if (clientShare) { - rdbSideTableInfo.setAsyncPoolSize(poolSize); - } - - JsonObject jdbcConfig = buildJdbcConfig(); - System.setProperty("vertx.disableFileCPResolving", "true"); - vertxOptions - .setEventLoopPoolSize(DEFAULT_VERTX_EVENT_LOOP_POOL_SIZE) - .setWorkerPoolSize(asyncPoolSize) - .setFileResolverCachingEnabled(false); - - executor = new ThreadPoolExecutor( - MAX_DB_CONN_POOL_SIZE_LIMIT, - MAX_DB_CONN_POOL_SIZE_LIMIT, - 0, - TimeUnit.MILLISECONDS, - new LinkedBlockingQueue<>(MAX_TASK_QUEUE_SIZE), - new DTThreadFactory("rdbAsyncExec"), - new ThreadPoolExecutor.CallerRunsPolicy()); - - vertx = Vertx.vertx(vertxOptions); - if (clientShare) { - rdbSqlClientPool.putIfAbsent(url, JDBCClient.createNonShared(vertx, jdbcConfig)); - LOG.info("{} lru type open connection share, url:{}, rdbSqlClientPool size:{}, rdbSqlClientPool:{}", rdbSideTableInfo.getType(), url, rdbSqlClientPool.size(), rdbSqlClientPool); - } else { - this.rdbSqlClient = JDBCClient.createNonShared(vertx, jdbcConfig); - } - - } - - protected void init(BaseSideInfo sideInfo) { - RdbSideTableInfo rdbSideTableInfo = (RdbSideTableInfo) sideInfo.getSideTableInfo(); - int defaultAsyncPoolSize = Math.min(MAX_DB_CONN_POOL_SIZE_LIMIT, DEFAULT_DB_CONN_POOL_SIZE); - asyncPoolSize = rdbSideTableInfo.getAsyncPoolSize() > 0 ? - rdbSideTableInfo.getAsyncPoolSize() : defaultAsyncPoolSize; - rdbSideTableInfo.setAsyncPoolSize(asyncPoolSize); - url = rdbSideTableInfo.getUrl(); - } - - public JsonObject buildJdbcConfig() { - throw new SuppressRestartsException( - new Throwable("Function buildJdbcConfig() must be overridden")); - } - - @Override - protected void preInvoke(BaseRow input, ResultFuture resultFuture) { } @Override - public void handleAsyncInvoke(Map inputParams, BaseRow input, ResultFuture resultFuture) throws Exception { - SQLClient sqlClient = clientShare ? rdbSqlClientPool.get(url) : this.rdbSqlClient; - AtomicLong networkLogCounter = new AtomicLong(0L); - //network is unhealthy - while (!connectionStatus.get()) { - if (networkLogCounter.getAndIncrement() % 1000 == 0) { - LOG.info("network unhealthy to block task"); + public void asyncInvoke(Row input, ResultFuture resultFuture) throws Exception { + + JsonArray inputParams = new JsonArray(); + for (Integer conValIndex : sideInfo.getEqualValIndex()) { + Object equalObj = input.getField(conValIndex); + if (equalObj == null) { + dealMissKey(input, resultFuture); + return; } - Thread.sleep(100); + inputParams.add(equalObj); } - Map params = formatInputParam(inputParams); - executor.execute(() -> connectWithRetry(params, input, resultFuture, sqlClient)); - } - protected void asyncQueryData(Map inputParams, - BaseRow input, - ResultFuture resultFuture, - SQLClient rdbSqlClient, - AtomicLong failCounter, - AtomicBoolean finishFlag, - CountDownLatch latch) { - doAsyncQueryData( - inputParams, - input, - resultFuture, - rdbSqlClient, - failCounter, - finishFlag, - latch); - } + String key = buildCacheKey(inputParams); + if (openCache()) { + CacheObj val = getFromCache(key); + if (val != null) { - final protected void doAsyncQueryData( - Map inputParams, - BaseRow input, - ResultFuture resultFuture, - SQLClient rdbSqlClient, - AtomicLong failCounter, - AtomicBoolean finishFlag, - CountDownLatch latch) { - rdbSqlClient.getConnection(conn -> { - try { - String errorMsg; - Integer retryMaxNum = sideInfo.getSideTableInfo().getConnectRetryMaxNum(3); - int logPrintTime = retryMaxNum / errorLogPrintNum == 0 ? - retryMaxNum : retryMaxNum / errorLogPrintNum; - if (conn.failed()) { - connectionStatus.set(false); - errorMsg = ExceptionTrace.traceOriginalCause(conn.cause()); - if (failCounter.getAndIncrement() % logPrintTime == 0) { - LOG.error("getConnection error. cause by " + errorMsg); - } - LOG.error(String.format("retry ... current time [%s]", failCounter.get())); - if (failCounter.get() >= retryMaxNum) { - resultFuture.completeExceptionally( - new SuppressRestartsException(conn.cause()) - ); - finishFlag.set(true); - } + if (ECacheContentType.MissVal == val.getType()) { + dealMissKey(input, resultFuture); return; + } else if (ECacheContentType.MultiLine == val.getType()) { + List rowList = Lists.newArrayList(); + for (Object jsonArray : (List) val.getContent()) { + Row row = fillData(input, jsonArray); + rowList.add(row); + } + resultFuture.complete(rowList); + } else { + resultFuture.completeExceptionally(new RuntimeException("not support cache obj type " + val.getType())); } - connectionStatus.set(true); - registerTimerAndAddToHandler(input, resultFuture); - - handleQuery(conn.result(), inputParams, input, resultFuture); - finishFlag.set(true); - } catch (Exception e) { - dealFillDataError(input, resultFuture, e); - } finally { - latch.countDown(); - } - }); - } - - private void connectWithRetry(Map inputParams, BaseRow input, ResultFuture resultFuture, SQLClient rdbSqlClient) { - AtomicLong failCounter = new AtomicLong(0); - AtomicBoolean finishFlag = new AtomicBoolean(false); - while (!finishFlag.get()) { - try { - CountDownLatch latch = new CountDownLatch(1); - asyncQueryData( - inputParams, - input, - resultFuture, - rdbSqlClient, - failCounter, - finishFlag, - latch); - try { - latch.await(); - } catch (InterruptedException e) { - LOG.error("", e); - } - - } catch (Exception e) { - //数据源队列溢出情况 - connectionStatus.set(false); - } - if (!finishFlag.get()) { - ThreadUtil.sleepSeconds(ThreadUtil.DEFAULT_SLEEP_TIME); + return; } } - } - - private Object convertDataType(Object val) { - if (val == null) { - // OK - } else if (val instanceof Number && !(val instanceof BigDecimal)) { - // OK - } else if (val instanceof Boolean) { - // OK - } else if (val instanceof String) { - // OK - } else if (val instanceof Character) { - // OK - } else if (val instanceof CharSequence) { - } else if (val instanceof JsonObject) { - - } else if (val instanceof JsonArray) { + rdbSQLClient.getConnection(conn -> { + if (conn.failed()) { + //Treatment failures + resultFuture.completeExceptionally(conn.cause()); + return; + } - } else if (val instanceof Map) { + final SQLConnection connection = conn.result(); + String sqlCondition = sideInfo.getSqlCondition(); + connection.queryWithParams(sqlCondition, inputParams, rs -> { + if (rs.failed()) { + LOG.error("Cannot retrieve the data from the database", rs.cause()); + resultFuture.completeExceptionally(rs.cause()); + return; + } - } else if (val instanceof List) { + List cacheContent = Lists.newArrayList(); - } else if (val instanceof byte[]) { + int resultSize = rs.result().getResults().size(); + if (resultSize > 0) { + List rowList = Lists.newArrayList(); - } else if (val instanceof Instant) { + for (JsonArray line : rs.result().getResults()) { + Row row = fillData(input, line); + if (openCache()) { + cacheContent.add(line); + } + rowList.add(row); + } - } else if (val instanceof Timestamp) { - val = DateUtil.timestampToString((Timestamp) val); - } else if (val instanceof java.util.Date) { - val = DateUtil.dateToString((java.sql.Date) val); - } else { - val = val.toString(); - } - return val; + if (openCache()) { + putCache(key, CacheObj.buildCacheObj(ECacheContentType.MultiLine, cacheContent)); + } - } + resultFuture.complete(rowList); + } else { + dealMissKey(input, resultFuture); + if (openCache()) { + putCache(key, CacheMissVal.getMissKeyObj()); + } + } - @Override - public String buildCacheKey(Map inputParam) { - return StringUtils.join(inputParam.values(), "_"); + // and close the connection + connection.close(done -> { + if (done.failed()) { + throw new RuntimeException(done.cause()); + } + }); + }); + }); } @Override - public BaseRow fillData(BaseRow input, Object line) { - GenericRow genericRow = (GenericRow) input; + public Row fillData(Row input, Object line) { JsonArray jsonArray = (JsonArray) line; - GenericRow row = new GenericRow(sideInfo.getOutFieldInfoList().size()); - row.setHeader(input.getHeader()); + Row row = new Row(sideInfo.getOutFieldInfoList().size()); + String[] fields = sideInfo.getSideTableInfo().getFieldTypes(); for (Map.Entry entry : sideInfo.getInFieldIndex().entrySet()) { - Object obj = genericRow.getField(entry.getValue()); - obj = convertTimeIndictorTypeInfo(entry.getValue(), obj); + Object obj = input.getField(entry.getValue()); + boolean isTimeIndicatorTypeInfo = TimeIndicatorTypeInfo.class.isAssignableFrom(sideInfo.getRowTypeInfo().getTypeAt(entry.getValue()).getClass()); + if (obj instanceof Timestamp && isTimeIndicatorTypeInfo) { + obj = ((Timestamp) obj).getTime(); + } + row.setField(entry.getKey(), obj); } @@ -341,8 +176,7 @@ public BaseRow fillData(BaseRow input, Object line) { if (jsonArray == null) { row.setField(entry.getKey(), null); } else { - String fieldType = sideInfo.getSelectSideFieldType(entry.getValue()); - Object object = SwitchUtil.getTarget(jsonArray.getValue(entry.getValue()), fieldType); + Object object = SwitchUtil.getTarget(jsonArray.getValue(entry.getValue()), fields[entry.getValue()]); row.setField(entry.getKey(), object); } } @@ -353,101 +187,23 @@ public BaseRow fillData(BaseRow input, Object line) { @Override public void close() throws Exception { super.close(); - if (clientShare && rdbSqlClientPool.get(url) != null) { - rdbSqlClientPool.get(url).close(getAsyncResultHandler()); - } - if (rdbSqlClient != null) { - rdbSqlClient.close(getAsyncResultHandler()); - } - - if (executor != null) { - executor.shutdown(); - } - - // 关闭异步连接vertx事件循环线程,因为vertx使用的是非守护线程 - if (Objects.nonNull(vertx)) { - vertx.close(done -> { - if (done.failed()) { - LOG.error("vert.x close error. cause by " + - ExceptionTrace.traceOriginalCause(done.cause()) - ); - } - }); + if (rdbSQLClient != null) { + rdbSQLClient.close(); } - } - - private Handler> getAsyncResultHandler() { - return done -> { - if (done.failed()) { - LOG.error("sql client close failed! " + - ExceptionTrace.traceOriginalCause(done.cause()) - ); - } - if (done.succeeded()) { - LOG.info("sql client closed."); - } - }; } - private void handleQuery(SQLConnection connection, Map inputParams, BaseRow input, ResultFuture resultFuture) { - String key = buildCacheKey(inputParams); - JsonArray params = new JsonArray(Lists.newArrayList(inputParams.values())); - connection.queryWithParams(sideInfo.getSqlCondition(), params, rs -> { - try { - if (rs.failed()) { - LOG.error( - String.format("\nget data with sql [%s] failed! \ncause: [%s]", - sideInfo.getSqlCondition(), - rs.cause().getMessage() - ) - ); - dealFillDataError(input, resultFuture, rs.cause()); - return; - } - - List cacheContent = Lists.newArrayList(); - - int resultSize = rs.result().getResults().size(); - if (resultSize > 0) { - List rowList = Lists.newArrayList(); - - for (JsonArray line : rs.result().getResults()) { - BaseRow row = fillData(input, line); - if (openCache()) { - cacheContent.add(line); - } - rowList.add(row); - } + public String buildCacheKey(JsonArray jsonArray) { + StringBuilder sb = new StringBuilder(); + for (Object ele : jsonArray.getList()) { + sb.append(ele.toString()) + .append("_"); + } - if (openCache()) { - putCache(key, CacheObj.buildCacheObj(ECacheContentType.MultiLine, cacheContent)); - } - RowDataComplete.completeBaseRow(resultFuture, rowList); - } else { - dealMissKey(input, resultFuture); - if (openCache()) { - putCache(key, CacheMissVal.getMissKeyObj()); - } - } - } finally { - // and close the connection - connection.close(done -> { - if (done.failed()) { - LOG.error("sql connection close failed! " + - ExceptionTrace.traceOriginalCause(done.cause()) - ); - } - }); - } - }); + return sb.toString(); } - private Map formatInputParam(Map inputParam) { - Map result = Maps.newLinkedHashMap(); - inputParam.forEach((k, v) -> { - result.put(k, convertDataType(v)); - }); - return result; + public void setRdbSQLClient(SQLClient rdbSQLClient) { + this.rdbSQLClient = rdbSQLClient; } } diff --git a/rdb/rdb-side/src/main/java/com/dtstack/flink/sql/side/rdb/async/RdbAsyncSideInfo.java b/rdb/rdb-side/src/main/java/com/dtstack/flink/sql/side/rdb/async/RdbAsyncSideInfo.java index 7f20802aa..0481e3443 100644 --- a/rdb/rdb-side/src/main/java/com/dtstack/flink/sql/side/rdb/async/RdbAsyncSideInfo.java +++ b/rdb/rdb-side/src/main/java/com/dtstack/flink/sql/side/rdb/async/RdbAsyncSideInfo.java @@ -18,28 +18,23 @@ package com.dtstack.flink.sql.side.rdb.async; -import org.apache.flink.api.java.typeutils.RowTypeInfo; - import com.dtstack.flink.sql.side.FieldInfo; import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.PredicateInfo; -import com.dtstack.flink.sql.side.BaseSideInfo; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; +import com.dtstack.flink.sql.side.SideInfo; +import com.dtstack.flink.sql.side.SideTableInfo; import com.dtstack.flink.sql.side.rdb.table.RdbSideTableInfo; import com.dtstack.flink.sql.util.ParseUtils; -import com.google.common.collect.Lists; import org.apache.calcite.sql.SqlBasicCall; import org.apache.calcite.sql.SqlIdentifier; import org.apache.calcite.sql.SqlKind; import org.apache.calcite.sql.SqlNode; -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.apache.calcite.sql.*; +import org.apache.flink.api.java.typeutils.RowTypeInfo; +import com.google.common.collect.Lists; import java.util.Arrays; import java.util.List; import java.util.Map; -import java.util.stream.Collectors; /** @@ -50,24 +45,24 @@ * @author maqi */ -public class RdbAsyncSideInfo extends BaseSideInfo { +public class RdbAsyncSideInfo extends SideInfo { private static final long serialVersionUID = 1942629132469918611L; - private static final Logger LOG = LoggerFactory.getLogger(RdbAsyncSideInfo.class); - - public RdbAsyncSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { + public RdbAsyncSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, SideTableInfo sideTableInfo) { super(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); } @Override - public void buildEqualInfo(JoinInfo joinInfo, AbstractSideTableInfo sideTableInfo) { + public void buildEqualInfo(JoinInfo joinInfo, SideTableInfo sideTableInfo) { RdbSideTableInfo rdbSideTableInfo = (RdbSideTableInfo) sideTableInfo; String sideTableName = joinInfo.getSideTableName(); + SqlNode conditionNode = joinInfo.getCondition(); List sqlNodeList = Lists.newArrayList(); + List sqlJoinCompareOperate= Lists.newArrayList(); ParseUtils.parseAnd(conditionNode, sqlNodeList); @@ -77,62 +72,92 @@ public void buildEqualInfo(JoinInfo joinInfo, AbstractSideTableInfo sideTableInf dealOneEqualCon(sqlNode, sideTableName); } - sqlCondition = getSelectFromStatement(getTableName(rdbSideTableInfo), Arrays.asList(StringUtils.split(sideSelectFields, ",")), - equalFieldList, sqlJoinCompareOperate, sideTableInfo.getPredicateInfoes()); - LOG.info("----------dimension sql query-----------\n{}", sqlCondition); - } - - public String getAdditionalWhereClause() { - return ""; - } - - public String getSelectFromStatement(String tableName, List selectFields, List conditionFields, List sqlJoinCompareOperate, - List predicateInfoes) { - String fromClause = selectFields.stream() - .map(this::quoteIdentifier) - .collect(Collectors.joining(", ")); + List whereConditionList = Lists.newArrayList();; + Map physicalFields = rdbSideTableInfo.getPhysicalFields(); + SqlNode whereNode = ((SqlSelect) joinInfo.getSelectNode()).getWhere(); + if (whereNode != null) { + // 解析维表中的过滤条件 + ParseUtils.parseSideWhere(whereNode, physicalFields, whereConditionList); + } - String whereClause = conditionFields.stream() - .map(f -> quoteIdentifier(sideTableInfo.getPhysicalFields().getOrDefault(f, f)) + sqlJoinCompareOperate.get(conditionFields.indexOf(f)) + wrapperPlaceholder(f)) - .collect(Collectors.joining(" AND ")); + sqlCondition = "select ${selectField} from ${tableName} where "; + for (int i = 0; i < equalFieldList.size(); i++) { + String equalField = sideTableInfo.getPhysicalFields().getOrDefault(equalFieldList.get(i), equalFieldList.get(i)); - String predicateClause = predicateInfoes.stream() - .map(this::buildFilterCondition) - .collect(Collectors.joining(" AND ")); + sqlCondition += equalField + " " + sqlJoinCompareOperate.get(i) + " ? "; + if (i != equalFieldList.size() - 1) { + sqlCondition += " and "; + } + } + if (0 != whereConditionList.size()) { + // 如果where条件中第一个符合条件的是维表中的条件 + String firstCondition = whereConditionList.get(0); + if (!"and".equalsIgnoreCase(firstCondition) && !"or".equalsIgnoreCase(firstCondition)) { + whereConditionList.add(0, "and ("); + } else { + whereConditionList.add(1, "("); + } + whereConditionList.add(whereConditionList.size(), ")"); + sqlCondition += String.join(" ", whereConditionList); + } - String dimQuerySql = "SELECT " + fromClause + " FROM " + tableName + (conditionFields.size() > 0 ? " WHERE " + whereClause : "") - + (predicateInfoes.size() > 0 ? " AND " + predicateClause : "") + getAdditionalWhereClause(); + sqlCondition = sqlCondition.replace("${tableName}", rdbSideTableInfo.getTableName()).replace("${selectField}", sideSelectFields); - return dimQuerySql; + System.out.println("--------side sql query:-------------------"); + System.out.println(sqlCondition); } - public String wrapperPlaceholder(String fieldName) { - return " ? "; - } - public String buildFilterCondition(PredicateInfo info) { - switch (info.getOperatorKind()) { - case "IN": - case "NOT_IN": - return quoteIdentifier(info.getFieldName()) + " " + info.getOperatorName() + " ( " + info.getCondition() + " )"; - case "NOT_EQUALS": - return quoteIdentifier(info.getFieldName()) + " != " + info.getCondition(); - case "BETWEEN": - return quoteIdentifier(info.getFieldName()) + " BETWEEN " + info.getCondition(); - case "IS_NOT_NULL": - case "IS_NULL": - return quoteIdentifier(info.getFieldName()) + " " + info.getOperatorName(); - default: - return quoteIdentifier(info.getFieldName()) + " " + info.getOperatorName() + " " + info.getCondition(); + @Override + public void dealOneEqualCon(SqlNode sqlNode, String sideTableName) { + if (!SqlKind.COMPARISON.contains(sqlNode.getKind())) { + throw new RuntimeException("not compare operator."); } - } - public String getTableName(RdbSideTableInfo rdbSideTableInfo) { - return rdbSideTableInfo.getTableName(); - } + SqlIdentifier left = (SqlIdentifier) ((SqlBasicCall) sqlNode).getOperands()[0]; + SqlIdentifier right = (SqlIdentifier) ((SqlBasicCall) sqlNode).getOperands()[1]; + + String leftTableName = left.getComponent(0).getSimple(); + String leftField = left.getComponent(1).getSimple(); + + String rightTableName = right.getComponent(0).getSimple(); + String rightField = right.getComponent(1).getSimple(); + + if (leftTableName.equalsIgnoreCase(sideTableName)) { + equalFieldList.add(leftField); + int equalFieldIndex = -1; + for (int i = 0; i < rowTypeInfo.getFieldNames().length; i++) { + String fieldName = rowTypeInfo.getFieldNames()[i]; + if (fieldName.equalsIgnoreCase(rightField)) { + equalFieldIndex = i; + } + } + if (equalFieldIndex == -1) { + throw new RuntimeException("can't deal equal field: " + sqlNode); + } + + equalValIndex.add(equalFieldIndex); + + } else if (rightTableName.equalsIgnoreCase(sideTableName)) { + + equalFieldList.add(rightField); + int equalFieldIndex = -1; + for (int i = 0; i < rowTypeInfo.getFieldNames().length; i++) { + String fieldName = rowTypeInfo.getFieldNames()[i]; + if (fieldName.equalsIgnoreCase(leftField)) { + equalFieldIndex = i; + } + } + if (equalFieldIndex == -1) { + throw new RuntimeException("can't deal equal field: " + sqlNode.toString()); + } + + equalValIndex.add(equalFieldIndex); + + } else { + throw new RuntimeException("resolve equalFieldList error:" + sqlNode.toString()); + } - public String quoteIdentifier(String identifier) { - return " " + identifier + " "; } } \ No newline at end of file diff --git a/rdb/rdb-side/src/main/java/com/dtstack/flink/sql/side/rdb/provider/DTC3P0DataSourceProvider.java b/rdb/rdb-side/src/main/java/com/dtstack/flink/sql/side/rdb/provider/DTC3P0DataSourceProvider.java index 542258257..fcca4f0ef 100644 --- a/rdb/rdb-side/src/main/java/com/dtstack/flink/sql/side/rdb/provider/DTC3P0DataSourceProvider.java +++ b/rdb/rdb-side/src/main/java/com/dtstack/flink/sql/side/rdb/provider/DTC3P0DataSourceProvider.java @@ -25,19 +25,13 @@ import javax.sql.DataSource; import java.beans.PropertyVetoException; import java.sql.SQLException; -/** - * Date: 2019/9/17 - * Company: www.dtstack.com - * @author maqi - */ + public class DTC3P0DataSourceProvider extends C3P0DataSourceProvider { @Override public DataSource getDataSource(JsonObject config) throws SQLException { String url = config.getString("url"); - if (url == null) { - throw new NullPointerException("url cannot be null"); - } + if (url == null) throw new NullPointerException("url cannot be null"); String driverClass = config.getString("driver_class"); String user = config.getString("user"); String password = config.getString("password"); diff --git a/rdb/rdb-side/src/main/java/com/dtstack/flink/sql/side/rdb/table/RdbSideParser.java b/rdb/rdb-side/src/main/java/com/dtstack/flink/sql/side/rdb/table/RdbSideParser.java index 20d9fc1b6..b9811b0ee 100644 --- a/rdb/rdb-side/src/main/java/com/dtstack/flink/sql/side/rdb/table/RdbSideParser.java +++ b/rdb/rdb-side/src/main/java/com/dtstack/flink/sql/side/rdb/table/RdbSideParser.java @@ -19,14 +19,12 @@ package com.dtstack.flink.sql.side.rdb.table; -import com.dtstack.flink.sql.table.AbstractSideTableParser; -import com.dtstack.flink.sql.table.AbstractTableInfo; +import com.dtstack.flink.sql.table.AbsSideTableParser; +import com.dtstack.flink.sql.table.TableInfo; import com.dtstack.flink.sql.util.MathUtil; import java.util.Map; -import static com.dtstack.flink.sql.side.rdb.table.RdbSideTableInfo.DRIVER_NAME; - /** * Reason: * Date: 2018/11/26 @@ -35,10 +33,10 @@ * @author maqi */ -public class RdbSideParser extends AbstractSideTableParser { +public class RdbSideParser extends AbsSideTableParser { @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { + public TableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { RdbSideTableInfo rdbTableInfo = new RdbSideTableInfo(); rdbTableInfo.setName(tableName); parseFieldsInfo(fieldsInfo, rdbTableInfo); @@ -50,14 +48,6 @@ public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map + * * 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. @@ -17,14 +17,8 @@ */ package com.dtstack.flink.sql.side.rdb.table; -import com.dtstack.flink.sql.core.rdb.JdbcCheckKeys; -import com.dtstack.flink.sql.core.rdb.JdbcResourceCheck; -import com.dtstack.flink.sql.resource.ResourceCheck; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; +import com.dtstack.flink.sql.side.SideTableInfo; import com.google.common.base.Preconditions; -import com.google.common.collect.Maps; - -import java.util.Map; /** * Reason: @@ -33,21 +27,19 @@ * * @author maqi */ -public class RdbSideTableInfo extends AbstractSideTableInfo { +public class RdbSideTableInfo extends SideTableInfo { + + private static final long serialVersionUID = -1L; - public static final String DRIVER_NAME = "driverName"; public static final String URL_KEY = "url"; + public static final String TABLE_NAME_KEY = "tableName"; + public static final String USER_NAME_KEY = "userName"; + public static final String PASSWORD_KEY = "password"; + public static final String SCHEMA_KEY = "schema"; - private static final long serialVersionUID = -1L; - private String driverName; - private String url; - private String tableName; - private String userName; - private String password; - private String schema; @Override public boolean check() { @@ -55,15 +47,19 @@ public boolean check() { Preconditions.checkNotNull(tableName, "rdb of tableName is required"); Preconditions.checkNotNull(userName, "rdb of userName is required"); Preconditions.checkNotNull(password, "rdb of password is required"); - Preconditions.checkArgument(getFieldList().size() == getFieldExtraInfoList().size(), - "fields and fieldExtraInfoList attributes must be the same length"); - // 是否在client端快速检测表资源是否可用,这样在client能访问资源的情况下快速失败,不用提交到集群检测 - if (getFastCheck()) { - JdbcResourceCheck.getInstance().checkResourceStatus(this.getCheckProperties()); - } return true; } + private String url; + + private String tableName; + + private String userName; + + private String password; + + private String schema; + public String getSchema() { return schema; } @@ -103,39 +99,4 @@ public String getPassword() { public void setPassword(String password) { this.password = password; } - - public String getDriverName() { - return driverName; - } - - public void setDriverName(String driverName) { - this.driverName = driverName; - } - - @Override - public String toString() { - String cacheInfo = super.toString(); - String connectionInfo = "Rdb Side Connection Info{" + - "url='" + url + '\'' + - ", tableName='" + tableName + '\'' + - ", schema='" + schema + '\'' + - ", driverName='" + driverName + '\'' + - '}'; - return cacheInfo + " , " + connectionInfo; - } - - @Override - public Map buildCheckProperties() { - Map properties = Maps.newHashMap(); - properties.put(JdbcCheckKeys.DRIVER_NAME, getDriverName()); - properties.put(JdbcCheckKeys.URL_KEY, getUrl()); - properties.put(JdbcCheckKeys.USER_NAME_KEY, getUserName()); - properties.put(JdbcCheckKeys.PASSWORD_KEY, getPassword()); - properties.put(JdbcCheckKeys.SCHEMA_KEY, getSchema()); - properties.put(JdbcCheckKeys.TABLE_NAME_KEY, getTableName()); - properties.put(JdbcCheckKeys.OPERATION_NAME_KEY, getName()); - properties.put(JdbcCheckKeys.TABLE_TYPE_KEY, "side"); - properties.put(JdbcCheckKeys.NEED_CHECK, String.valueOf(ResourceCheck.NEED_CHECK)); - return properties; - } } diff --git a/rdb/rdb-side/src/main/java/com/dtstack/flink/sql/side/rdb/util/MathUtil.java b/rdb/rdb-side/src/main/java/com/dtstack/flink/sql/side/rdb/util/MathUtil.java new file mode 100644 index 000000000..d03b33045 --- /dev/null +++ b/rdb/rdb-side/src/main/java/com/dtstack/flink/sql/side/rdb/util/MathUtil.java @@ -0,0 +1,255 @@ +/* + * 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 com.dtstack.flink.sql.side.rdb.util; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.sql.Date; +import java.sql.Timestamp; +import java.text.ParseException; +import java.text.SimpleDateFormat; + +/** + * Date: 2017/4/21 + * Company: www.dtstack.com + * + * @author xuchao + */ + +public class MathUtil { + + public static Long getLongVal(Object obj) { + if (obj == null) { + return null; + } + + if (obj instanceof String) { + return Long.valueOf((String) obj); + } else if (obj instanceof Long) { + return (Long) obj; + } else if (obj instanceof Integer) { + return Long.valueOf(obj.toString()); + } else if (obj instanceof BigDecimal) { + return ((BigDecimal) obj).longValue(); + } else if (obj instanceof BigInteger) { + return ((BigInteger) obj).longValue(); + } + throw new RuntimeException("not support type of " + obj.getClass() + " convert to Long."); + } + + public static Long getLongVal(Object obj, long defaultVal) { + if (obj == null) { + return defaultVal; + } + + return getLongVal(obj); + } + + public static Integer getIntegerVal(Object obj) { + if (obj == null) { + return null; + } + + if (obj instanceof String) { + return Integer.valueOf((String) obj); + } else if (obj instanceof Integer) { + return (Integer) obj; + } else if (obj instanceof Long) { + return ((Long) obj).intValue(); + } else if (obj instanceof Double) { + return ((Double) obj).intValue(); + } else if (obj instanceof BigDecimal) { + return ((BigDecimal) obj).intValue(); + } else if (obj instanceof BigInteger) { + return ((BigInteger) obj).intValue(); + } + + throw new RuntimeException("not support type of " + obj.getClass() + " convert to Integer."); + } + + public static Integer getIntegerVal(Object obj, int defaultVal) { + if (obj == null) { + return defaultVal; + } + + return getIntegerVal(obj); + } + + public static Float getFloatVal(Object obj) { + if (obj == null) { + return null; + } + + if (obj instanceof String) { + return Float.valueOf((String) obj); + } else if (obj instanceof Float) { + return (Float) obj; + } else if (obj instanceof BigDecimal) { + return ((BigDecimal) obj).floatValue(); + } + + throw new RuntimeException("not support type of " + obj.getClass() + " convert to Float."); + } + + public static Float getFloatVal(Object obj, float defaultVal) { + if (obj == null) { + return defaultVal; + } + + return getFloatVal(obj); + } + + public static Double getDoubleVal(Object obj) { + if (obj == null) { + return null; + } + + if (obj instanceof String) { + return Double.valueOf((String) obj); + } else if (obj instanceof Float) { + return (Double) obj; + } else if (obj instanceof BigDecimal) { + return ((BigDecimal) obj).doubleValue(); + } + + throw new RuntimeException("not support type of " + obj.getClass() + " convert to Double."); + } + + public static Double getDoubleVal(Object obj, double defaultVal) { + if (obj == null) { + return defaultVal; + } + + return getDoubleVal(obj); + } + + + public static Boolean getBoolean(Object obj) { + if (obj == null) { + return null; + } + + if (obj instanceof String) { + return Boolean.valueOf((String) obj); + } else if (obj instanceof Boolean) { + return (Boolean) obj; + } + + throw new RuntimeException("not support type of " + obj.getClass() + " convert to Boolean."); + } + + public static Boolean getBoolean(Object obj, boolean defaultVal) { + if (obj == null) { + return defaultVal; + } + + return getBoolean(obj); + } + + public static String getString(Object obj) { + if (obj == null) { + return null; + } + + if (obj instanceof String) { + return (String) obj; + } + + return obj.toString(); + } + + public static Byte getByte(Object obj) { + if (obj == null) { + return null; + } + + if (obj instanceof String) { + return Byte.valueOf((String) obj); + } else if (obj instanceof Byte) { + return (Byte) obj; + } + + throw new RuntimeException("not support type of " + obj.getClass() + " convert to Byte."); + } + + public static Short getShort(Object obj) { + if (obj == null) { + return null; + } + + if (obj instanceof String) { + return Short.valueOf((String) obj); + } else if (obj instanceof Short) { + return (Short) obj; + } + + throw new RuntimeException("not support type of " + obj.getClass() + " convert to Short."); + } + + public static BigDecimal getBigDecimal(Object obj) { + if (obj == null) { + return null; + } + if (obj instanceof String) { + return new BigDecimal((String) obj); + } else if (obj instanceof BigDecimal) { + return (BigDecimal) obj; + } else if (obj instanceof BigInteger) { + return new BigDecimal((BigInteger) obj); + } else if (obj instanceof Number) { + return new BigDecimal(((Number) obj).doubleValue()); + } + throw new RuntimeException("not support type of " + obj.getClass() + " convert to BigDecimal."); + } + + public static Date getDate(Object obj) { + if (obj == null) { + return null; + } + if (obj instanceof String) { + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + try { + return new Date(format.parse((String) obj).getTime()); + } catch (ParseException e) { + throw new RuntimeException("String convert to Date fail."); + } + } else if (obj instanceof Timestamp) { + return new Date(((Timestamp) obj).getTime()); + } else if (obj instanceof Date) { + return (Date) obj; + } + throw new RuntimeException("not support type of " + obj.getClass() + " convert to Date."); + } + + public static Timestamp getTimestamp(Object obj) { + if (obj == null) { + return null; + } + if (obj instanceof Timestamp) { + return (Timestamp) obj; + } else if (obj instanceof Date) { + return new Timestamp(((Date) obj).getTime()); + } else if (obj instanceof String) { + return new Timestamp(getDate(obj).getTime()); + } + throw new RuntimeException("not support type of " + obj.getClass() + " convert to Date."); + } + +} \ No newline at end of file diff --git a/rdb/rdb-side/src/main/java/com/dtstack/flink/sql/side/rdb/util/SwitchUtil.java b/rdb/rdb-side/src/main/java/com/dtstack/flink/sql/side/rdb/util/SwitchUtil.java index 62390b47d..02164d1d9 100644 --- a/rdb/rdb-side/src/main/java/com/dtstack/flink/sql/side/rdb/util/SwitchUtil.java +++ b/rdb/rdb-side/src/main/java/com/dtstack/flink/sql/side/rdb/util/SwitchUtil.java @@ -17,7 +17,7 @@ */ package com.dtstack.flink.sql.side.rdb.util; -import com.dtstack.flink.sql.util.MathUtil; +import java.text.ParseException; /** * Reason: @@ -78,9 +78,6 @@ public static Object getTarget(Object obj, String targetType) { case "timestamp": case "datetime": return MathUtil.getTimestamp(obj); - case "time": - return MathUtil.getTime(obj); - default: } return obj; } diff --git a/rdb/rdb-side/src/test/java/com/dtstack/flink/sql/side/rdb/all/AbstractRdbAllReqRowTest.java b/rdb/rdb-side/src/test/java/com/dtstack/flink/sql/side/rdb/all/AbstractRdbAllReqRowTest.java deleted file mode 100644 index b3b0778ed..000000000 --- a/rdb/rdb-side/src/test/java/com/dtstack/flink/sql/side/rdb/all/AbstractRdbAllReqRowTest.java +++ /dev/null @@ -1,118 +0,0 @@ -package com.dtstack.flink.sql.side.rdb.all; - -import com.dtstack.flink.sql.side.BaseAllReqRow; -import com.dtstack.flink.sql.side.rdb.table.RdbSideTableInfo; -import com.dtstack.flink.sql.side.rdb.testutil.ArgFactory; -import com.google.common.collect.Maps; -import org.apache.commons.compress.utils.Lists; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.configuration.Configuration; -import org.apache.flink.table.api.Types; -import org.apache.flink.table.dataformat.BaseRow; -import org.apache.flink.table.dataformat.GenericRow; -import org.apache.flink.types.Row; -import org.apache.flink.util.Collector; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import org.powermock.reflect.Whitebox; - -import java.util.List; -import java.util.Map; - -import static org.powermock.api.support.membermodification.MemberModifier.suppress; - -@RunWith(PowerMockRunner.class) -@PrepareForTest({AbstractRdbAllReqRow.class, BaseAllReqRow.class}) -public class AbstractRdbAllReqRowTest { - - AbstractRdbAllReqRow reqRow; - - @Before - public void setUp() { - RdbAllSideInfo sideInfo = Whitebox.newInstance(RdbAllSideInfo.class); - RdbSideTableInfo sideTableInfo = new RdbSideTableInfo(); - sideInfo.setSideTableInfo(sideTableInfo); - - sideInfo.setOutFieldInfoList( - ArgFactory.genOutFieldInfoList() - ); - Map inIndex = Maps.newHashMap(); - inIndex.put(0, 0); - sideInfo.setInFieldIndex(inIndex); - Map sideIndex = Maps.newHashMap(); - sideIndex.put(1, "id"); - sideInfo.setSideFieldNameIndex(sideIndex); - sideInfo.setRowTypeInfo(ArgFactory.genRowTypeInfo()); - - sideInfo.setSideSelectFields("id, name"); - sideInfo.setSideTableInfo( - ArgFactory.genSideTableInfo() - ); - List equalIndex = Lists.newArrayList(); - equalIndex.add(0); - sideInfo.setEqualValIndex(equalIndex); - List equalList = Lists.newArrayList(); - equalList.add("id"); - sideInfo.setEqualFieldList(equalList); - reqRow = new ConcreteRdbAllReqRow(sideInfo); - } - -// @Test - public void testOpen() throws Exception { - suppress( - BaseAllReqRow.class.getMethod( "open", Configuration.class) - ); - TypeInformation[] types = new TypeInformation[] { - Types.INT(), - Types.STRING() - }; - String[] fieldNames = new String[] { - "id", - "name" - }; - RowTypeInfo rowTypeInfo = new RowTypeInfo(types, fieldNames); - reqRow.open(null); - } - -// @Test -// public void testInitCache() throws Exception { -// Whitebox.invokeMethod(reqRow, "initCache"); -// } -// -// @Test -// public void testReloadCache() throws Exception { -// Whitebox.invokeMethod(reqRow, "reloadCache"); -// } - -// @Test -// public void testFlatMap() throws Exception { -// Whitebox.invokeMethod(reqRow, "initCache"); -// -// Row input = new Row(1); -// input.setField(0, 1); -// Collector out = new Collector() { -// @Override -// public void collect(BaseRow record) { } -// -// @Override -// public void close() { } -// }; -// -// reqRow.flatMap(input, out); -// } - -// @Test - public void testFillData() { - GenericRow input = new GenericRow(1); - input.setField(0, 1); - - Map sideInput = Maps.newHashMap(); - sideInput.put("id", 1); - reqRow.fillData(input, sideInput); - } - -} \ No newline at end of file diff --git a/rdb/rdb-side/src/test/java/com/dtstack/flink/sql/side/rdb/all/ConcreteRdbAllReqRow.java b/rdb/rdb-side/src/test/java/com/dtstack/flink/sql/side/rdb/all/ConcreteRdbAllReqRow.java deleted file mode 100644 index 353c32de2..000000000 --- a/rdb/rdb-side/src/test/java/com/dtstack/flink/sql/side/rdb/all/ConcreteRdbAllReqRow.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.dtstack.flink.sql.side.rdb.all; - -import com.dtstack.flink.sql.side.BaseSideInfo; -import org.powermock.api.mockito.PowerMockito; - -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; - -import static org.mockito.ArgumentMatchers.any; -import static org.powermock.api.mockito.PowerMockito.mock; - -/** - * @program: flink.sql - * @author: wuren - * @create: 2020/07/29 - **/ -public class ConcreteRdbAllReqRow extends AbstractRdbAllReqRow { - - public ConcreteRdbAllReqRow(BaseSideInfo sideInfo) { - super(sideInfo); - } - - @Override - public Connection getConn(String dbURL, String userName, String password) { - Connection connMock = mock(Connection.class); - try { - PowerMockito.doNothing().when(connMock).close(); - Statement stmtMock = mock(Statement.class); - PowerMockito.doReturn(stmtMock).when(connMock).createStatement(); -// PowerMockito.doNothing().when(stmtMock).setFetchSize(any()); - ResultSet setMock = mock(ResultSet.class); - PowerMockito.when(setMock.next()).thenReturn(true).thenReturn(false); - PowerMockito.doReturn(setMock).when(stmtMock).executeQuery(any()); - PowerMockito.doReturn(1).when(setMock).getObject(any()); - } catch (SQLException e) { - - } - return connMock; - } -} diff --git a/rdb/rdb-side/src/test/java/com/dtstack/flink/sql/side/rdb/all/RdbAllReqRowTestBase.java b/rdb/rdb-side/src/test/java/com/dtstack/flink/sql/side/rdb/all/RdbAllReqRowTestBase.java deleted file mode 100644 index cf3f13f45..000000000 --- a/rdb/rdb-side/src/test/java/com/dtstack/flink/sql/side/rdb/all/RdbAllReqRowTestBase.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.dtstack.flink.sql.side.rdb.all; - -import org.junit.Before; -import org.junit.Test; -import org.powermock.reflect.Whitebox; - -/** - * @program: flinkStreamSQL - * @author: wuren - * @create: 2020/11/10 - **/ -public abstract class RdbAllReqRowTestBase { - - protected AbstractRdbAllReqRow reqRow; - protected Class clazz; - - @Before - public void setUp() { - init(); - this.reqRow = Whitebox.newInstance(clazz); - } - - protected abstract void init(); - - @Test - public void testGetConn() { - try { - reqRow.getConn("", "", ""); - } catch (RuntimeException e) {} - } - -} diff --git a/rdb/rdb-side/src/test/java/com/dtstack/flink/sql/side/rdb/all/RdbAllSideInfoTest.java b/rdb/rdb-side/src/test/java/com/dtstack/flink/sql/side/rdb/all/RdbAllSideInfoTest.java deleted file mode 100644 index 224259e15..000000000 --- a/rdb/rdb-side/src/test/java/com/dtstack/flink/sql/side/rdb/all/RdbAllSideInfoTest.java +++ /dev/null @@ -1,178 +0,0 @@ -package com.dtstack.flink.sql.side.rdb.all; - -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.PredicateInfo; -import com.dtstack.flink.sql.side.rdb.table.RdbSideTableInfo; -import com.google.common.collect.Maps; -import org.apache.calcite.config.Lex; -import org.apache.calcite.sql.SqlJoin; -import org.apache.calcite.sql.SqlNode; -import org.apache.calcite.sql.SqlSelect; -import org.apache.calcite.sql.parser.SqlParseException; -import org.apache.calcite.sql.parser.SqlParser; -import org.apache.commons.compress.utils.Lists; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.table.api.Types; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import org.powermock.reflect.Whitebox; - -import java.util.ArrayList; -import java.util.List; - -import static org.powermock.api.support.membermodification.MemberMatcher.method; -import static org.powermock.api.support.membermodification.MemberModifier.suppress; - -@RunWith(PowerMockRunner.class) -@PrepareForTest(RdbAllSideInfo.class) -public class RdbAllSideInfoTest { - - RdbAllSideInfo sideInfo; - - @Before - public void setUp() { - TypeInformation[] types = new TypeInformation[] { - Types.INT(), - Types.STRING() - }; - String[] fieldNames = new String[] { - "id", - "name" - }; - RowTypeInfo rowTypeInfo = new RowTypeInfo(types, fieldNames); - sideInfo = Whitebox.newInstance(RdbAllSideInfo.class); - sideInfo.setRowTypeInfo(rowTypeInfo); - sideInfo.setInFieldIndex(Maps.newHashMap()); - sideInfo.setSideFieldIndex(Maps.newHashMap()); - sideInfo.setSideFieldNameIndex(Maps.newHashMap()); - } - -// @Test - public void testBuildEqualInfo() { - RdbSideTableInfo tableInfo = new RdbSideTableInfo(); - tableInfo.setTableName("TEST_ods"); - List predicateInfoes = new ArrayList<>(); - PredicateInfo info = PredicateInfo.builder() - .setCondition("1") - .setOwnerTable("TEST_dwd") - .setOperatorKind("EQUALS") - .setOperatorName("=") - .setFieldName("id") - .build(); - predicateInfoes.add(info); - tableInfo.setPredicateInfoes(predicateInfoes); - sideInfo.setSideSelectFields("id, name"); - sideInfo.buildEqualInfo(null, tableInfo); - String stmt = sideInfo.getSqlCondition(); - // TODO 需要找到正确的normal值,让后把这个单测case完成。 - final String normal = "SELECT id , name FROM TEST_ods WHERE id = 1"; -// Assert.assertTrue(normal.equals(stmt)); - } - -// @Test - public void testParseSelectFields() throws SqlParseException { - JoinInfo joinInfo = new JoinInfo(); - final String LEFT_TABLE_NAME = "TEST_ods"; - final String RIGHT_TABLE_NAME = "TEST_dim"; - joinInfo.setRightTableAlias(RIGHT_TABLE_NAME); - joinInfo.setLeftTableAlias(LEFT_TABLE_NAME); - String sql = "select \n" + - " x.id \n" + - " ,y.id \n" + - " from TEST_ods x left join TEST_dim y7 \n" + - " on x.id = y.id"; - SqlParser.Config config = SqlParser - .configBuilder() - .setLex(Lex.MYSQL) - .build(); - SqlParser sqlParser = SqlParser.create(sql, config); - SqlNode sqlNode = sqlParser.parseStmt(); - - joinInfo.setCondition(((SqlJoin) ((SqlSelect) sqlNode).getFrom()).getCondition()); - List outFieldInfoList = new ArrayList<>(); - sideInfo.setOutFieldInfoList(outFieldInfoList); - try { - sideInfo.parseSelectFields(joinInfo); - } catch (Exception e) { - final String normalErrorMsg = "select non field from table " + RIGHT_TABLE_NAME; - String errorMsg = e.getMessage(); - Assert.assertTrue(normalErrorMsg.equals(errorMsg)); - } - - FieldInfo field1 = new FieldInfo(); - FieldInfo field2 = new FieldInfo(); - field1.setTable(LEFT_TABLE_NAME); - field1.setFieldName("id"); - field1.setTypeInformation(Types.INT()); - field2.setTable(RIGHT_TABLE_NAME); - field2.setFieldName("name"); - field2.setTypeInformation(Types.STRING()); - outFieldInfoList.add(field1); - outFieldInfoList.add(field2); - suppress(method(RdbAllSideInfo.class, "dealOneEqualCon")); - try { - sideInfo.parseSelectFields(joinInfo); - } catch (Exception e) { - final String normalErrorMsg = "no join condition found after table null"; - String errorMsg = e.getMessage(); - Assert.assertTrue(normalErrorMsg.equals(errorMsg)); - } - List fieldList = Lists.newArrayList(); - fieldList.add("id"); - fieldList.add("name"); - sideInfo.setEqualFieldList(fieldList); - sideInfo.parseSelectFields(joinInfo); - String selectFields = sideInfo.getSideSelectFields(); - final String normalSelectFields = "name,id"; - Assert.assertTrue(normalSelectFields.equals(selectFields)); - } - -// @Test - public void testBuildFilterCondition() { - final String operatorName = ""; - final String ownerTable = "ods_test"; - final String fieldName = "id"; - final String condition = ""; - - final String NOT_IN = "NOT_IN"; - final String NOT_EQUALS = "NOT_EQUALS"; - final String BETWEEN = "BETWEEN"; - final String IS_NULL = "IS_NULL"; - final String DEFAULT = ""; - - PredicateInfo predicateInfo = new PredicateInfo(operatorName, NOT_IN, ownerTable, fieldName, condition); - String notNullCondition = sideInfo.buildFilterCondition(predicateInfo); - predicateInfo.setOperatorKind(NOT_EQUALS); - String notEqualsCondition = sideInfo.buildFilterCondition(predicateInfo); - predicateInfo.setOperatorKind(BETWEEN); - String betweenCondition = sideInfo.buildFilterCondition(predicateInfo); - predicateInfo.setOperatorKind(IS_NULL); - String isNullCondition = sideInfo.buildFilterCondition(predicateInfo); - predicateInfo.setOperatorKind(DEFAULT); - String defaultCondition = sideInfo.buildFilterCondition(predicateInfo); - - } - -// @Test - public void testGetTableName() { - final String TABLE_NAME = "foo_name"; - RdbSideTableInfo tabInfo = PowerMockito.mock(RdbSideTableInfo.class); - PowerMockito.when(tabInfo.getTableName()).thenReturn("foo_name"); - String tableName = sideInfo.getTableName(tabInfo); - Assert.assertTrue(TABLE_NAME.equals(tableName)); - } - -// @Test - public void testQuoteIdentifier() { - String quoteStr = sideInfo.quoteIdentifier("foo"); - Assert.assertTrue(" foo ".equals(quoteStr)); - } - -} \ No newline at end of file diff --git a/rdb/rdb-side/src/test/java/com/dtstack/flink/sql/side/rdb/async/RdbAsyncReqRowTest.java b/rdb/rdb-side/src/test/java/com/dtstack/flink/sql/side/rdb/async/RdbAsyncReqRowTest.java deleted file mode 100644 index 21adc37e7..000000000 --- a/rdb/rdb-side/src/test/java/com/dtstack/flink/sql/side/rdb/async/RdbAsyncReqRowTest.java +++ /dev/null @@ -1,112 +0,0 @@ -package com.dtstack.flink.sql.side.rdb.async; - -import com.dtstack.flink.sql.side.BaseAsyncReqRow; -import com.dtstack.flink.sql.side.BaseSideInfo; -import com.dtstack.flink.sql.side.rdb.testutil.ArgFactory; -import com.google.common.collect.Maps; -import io.vertx.core.json.JsonArray; -import org.apache.commons.compress.utils.Lists; -import org.apache.flink.configuration.Configuration; -import org.apache.flink.streaming.api.functions.async.ResultFuture; -import org.apache.flink.table.dataformat.BaseRow; -import org.apache.flink.table.dataformat.GenericRow; -import org.apache.flink.types.Row; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import org.powermock.reflect.Whitebox; - -import java.sql.Date; -import java.sql.Timestamp; -import java.time.LocalDate; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Map; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -import static org.powermock.api.support.membermodification.MemberModifier.suppress; - -@RunWith(PowerMockRunner.class) -@PrepareForTest({BaseAsyncReqRow.class, ThreadPoolExecutor.class}) -public class RdbAsyncReqRowTest { - - RdbAsyncReqRow reqRow; - - @Before - public void setUp() { - BaseSideInfo sideInfo = ArgFactory.getSideInfo(); - sideInfo.setOutFieldInfoList( - ArgFactory.genOutFieldInfoList() - ); - Map inIndex = Maps.newHashMap(); - inIndex.put(0, 0); - sideInfo.setInFieldIndex(inIndex); - Map sideIndex = Maps.newHashMap(); - sideIndex.put(1, "id"); - sideInfo.setSideFieldNameIndex(sideIndex); - sideInfo.setRowTypeInfo(ArgFactory.genRowTypeInfo()); - reqRow = new RdbAsyncReqRow(sideInfo); - } - - // @Test - public void testOpen() throws Exception { - suppress(BaseAsyncReqRow.class.getMethod("open", Configuration.class)); - reqRow.open(null); - } - -// @Test - public void testFillData() { - GenericRow input = new GenericRow(1); - input.setField(0, 1); - - Map sideInput = Maps.newHashMap(); - sideInput.put("id", 1); - reqRow.fillData(input, null); - ArrayList ll = Lists.newArrayList(); - ll.add(1); - ll.add("TEST_name"); - JsonArray jsonArray = new JsonArray(ll); - reqRow.fillData(input, jsonArray); - } - - // @Test - public void testHandleAsyncInvoke() throws Exception { - GenericRow input = new GenericRow(1); - input.setField(0, 1); - ResultFuture future = new ResultFuture() { - @Override - public void complete(Collection result) { } - - @Override - public void completeExceptionally(Throwable error) { } - }; - Map sideInput = Maps.newHashMap(); - sideInput.put("id", 1); - suppress(ThreadPoolExecutor.class.getMethod("execute", Runnable.class)); - suppress(BaseAsyncReqRow.class.getMethod("open", Configuration.class)); - reqRow.open(null); - - reqRow.handleAsyncInvoke(sideInput, input, future); - } - -// @Test - public void testClose() throws Exception { - reqRow.close(); - } - -// @Test - public void testConvertDataType() throws Exception { - Timestamp ts = new Timestamp(1); - String tsStr = Whitebox.invokeMethod(reqRow, "convertDataType", ts); - Assert.assertEquals("1970-01-01 08:00:00", tsStr); - Date date = new Date(1); - LocalDate localDate = date.toLocalDate(); - String dateStr = Whitebox.invokeMethod(reqRow, "convertDataType", localDate); - System.out.println(dateStr); - } -} \ No newline at end of file diff --git a/rdb/rdb-side/src/test/java/com/dtstack/flink/sql/side/rdb/async/RdbAsyncReqRowTestBase.java b/rdb/rdb-side/src/test/java/com/dtstack/flink/sql/side/rdb/async/RdbAsyncReqRowTestBase.java deleted file mode 100644 index 739b604dd..000000000 --- a/rdb/rdb-side/src/test/java/com/dtstack/flink/sql/side/rdb/async/RdbAsyncReqRowTestBase.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.dtstack.flink.sql.side.rdb.async; - -import com.dtstack.flink.sql.side.BaseSideInfo; -import com.dtstack.flink.sql.side.rdb.all.AbstractRdbAllReqRow; -import com.dtstack.flink.sql.side.rdb.table.RdbSideParser; -import com.dtstack.flink.sql.side.rdb.table.RdbSideTableInfo; -import io.vertx.core.Vertx; -import io.vertx.core.json.JsonObject; -import io.vertx.ext.jdbc.JDBCClient; -import io.vertx.ext.sql.SQLClient; -import org.apache.flink.configuration.Configuration; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import org.powermock.reflect.Whitebox; - -import java.util.HashMap; -import java.util.Map; - -import static org.powermock.api.support.membermodification.MemberModifier.suppress; - -/** - * @program: flinkStreamSQL - * @author: wuren - * @create: 2020/11/10 - **/ -@RunWith(PowerMockRunner.class) -@PrepareForTest({RdbAsyncReqRow.class, JDBCClient.class}) -public abstract class RdbAsyncReqRowTestBase { - - protected RdbAsyncReqRow reqRow; - - protected Class clazz; - - @Before - public void setUp() { - init(); - this.reqRow = Whitebox.newInstance(clazz); - } - - protected abstract void init(); - - @BeforeClass - public static void perpare() throws NoSuchMethodException { - suppress(RdbAsyncReqRow.class.getMethod("buildJdbcConfig")); - suppress(RdbAsyncReqRow.class.getMethod("open", Configuration.class)); - suppress(JDBCClient.class.getMethod("createNonShared", Vertx.class, JsonObject.class)); - } - -// @Test - public void testOpen() throws Exception { - final String tableName = "table_foo"; - final String fieldsInfo = "id INT, name VARCHAR, PRIMARY KEY (id) , PERIOD FOR SYSTEM_TIME"; - Map props = new HashMap(); - props.put("url", "jdbc:mysql://foo.com:21050"); - props.put("tablename", "table_foo"); - props.put("username", "foo"); - props.put("password", "foo"); - RdbSideParser sinkParser = new RdbSideParser(); - RdbSideTableInfo tableInfo = (RdbSideTableInfo) sinkParser.getTableInfo(tableName, fieldsInfo, props); - tableInfo.setAsyncPoolSize(1); - BaseSideInfo sideInfo = Whitebox.newInstance(RdbAsyncSideInfo.class); - Whitebox.setInternalState(sideInfo, "sideTableInfo", tableInfo); - Whitebox.setInternalState(reqRow, "sideInfo", sideInfo); - reqRow.open(null); - } - -} diff --git a/rdb/rdb-side/src/test/java/com/dtstack/flink/sql/side/rdb/async/RdbAsyncSideInfoTest.java b/rdb/rdb-side/src/test/java/com/dtstack/flink/sql/side/rdb/async/RdbAsyncSideInfoTest.java deleted file mode 100644 index b951afa83..000000000 --- a/rdb/rdb-side/src/test/java/com/dtstack/flink/sql/side/rdb/async/RdbAsyncSideInfoTest.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.dtstack.flink.sql.side.rdb.async; - -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.PredicateInfo; -import com.dtstack.flink.sql.side.rdb.table.RdbSideTableInfo; -import com.dtstack.flink.sql.side.rdb.testutil.ArgFactory; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.table.api.Types; -import org.junit.Before; -import org.junit.Test; -import org.powermock.reflect.Whitebox; - -public class RdbAsyncSideInfoTest { - - RdbAsyncSideInfo sideInfo; - - @Before - public void setUp() { - - sideInfo = Whitebox.newInstance(RdbAsyncSideInfo.class); - - sideInfo = new RdbAsyncSideInfo( - ArgFactory.genRowTypeInfo(), - ArgFactory.genJoinInfo(), - ArgFactory.genOutFieldInfoList(), - ArgFactory.genSideTableInfo() - ); - - } - -// @Test - public void testBuildEqualInfo() { - JoinInfo joinInfo = ArgFactory.genJoinInfo(); - joinInfo.setLeftIsSideTable(true); - sideInfo.buildEqualInfo(joinInfo, ArgFactory.genSideTableInfo()); - } - -// @Test - public void testBuildFilterCondition() { - final String operatorName = ""; - final String ownerTable = "ods_test"; - final String fieldName = "id"; - final String condition = ""; - - final String NOT_IN = "NOT_IN"; - final String NOT_EQUALS = "NOT_EQUALS"; - final String BETWEEN = "BETWEEN"; - final String IS_NULL = "IS_NULL"; - final String DEFAULT = ""; - - PredicateInfo predicateInfo = new PredicateInfo(operatorName, NOT_IN, ownerTable, fieldName, condition); - String notNullCondition = sideInfo.buildFilterCondition(predicateInfo); - predicateInfo.setOperatorKind(NOT_EQUALS); - String notEqualsCondition = sideInfo.buildFilterCondition(predicateInfo); - predicateInfo.setOperatorKind(BETWEEN); - String betweenCondition = sideInfo.buildFilterCondition(predicateInfo); - predicateInfo.setOperatorKind(IS_NULL); - String isNullCondition = sideInfo.buildFilterCondition(predicateInfo); - predicateInfo.setOperatorKind(DEFAULT); - String defaultCondition = sideInfo.buildFilterCondition(predicateInfo); - - } - -} \ No newline at end of file diff --git a/rdb/rdb-side/src/test/java/com/dtstack/flink/sql/side/rdb/provider/DTC3P0DataSourceProviderTest.java b/rdb/rdb-side/src/test/java/com/dtstack/flink/sql/side/rdb/provider/DTC3P0DataSourceProviderTest.java deleted file mode 100644 index 8fcc2565c..000000000 --- a/rdb/rdb-side/src/test/java/com/dtstack/flink/sql/side/rdb/provider/DTC3P0DataSourceProviderTest.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.dtstack.flink.sql.side.rdb.provider; - -import com.google.common.collect.Maps; -import io.vertx.core.json.JsonObject; -import org.junit.Test; - -import javax.sql.DataSource; - -import java.sql.SQLException; -import java.util.Map; - -public class DTC3P0DataSourceProviderTest { - - private static String TEST_STR = "TEST"; - private static int TEST_INT = 1; - private static boolean TEST_BOOLEAN = false; - - @Test - public void testGetDataSource() throws SQLException { - Map map = Maps.newHashMap(); - DTC3P0DataSourceProvider provider = new DTC3P0DataSourceProvider(); - try { - JsonObject json = new JsonObject(map); - provider.getDataSource(json); - } catch (NullPointerException e) { } - map.put("url", "jdbc://"); - map.put("driver_class", "com.mysql.jdbc.Driver"); - map.put("user", TEST_STR); - map.put("password", TEST_STR); - map.put("max_pool_size", TEST_INT); - map.put("initial_pool_size", TEST_INT); - map.put("min_pool_size", TEST_INT); - map.put("max_statements", TEST_INT); - map.put("max_statements_per_connection", TEST_INT); - map.put("max_idle_time", TEST_INT); - map.put("acquire_retry_attempts", TEST_INT); - map.put("acquire_retry_delay", TEST_INT); - map.put("break_after_acquire_failure", TEST_BOOLEAN); - - map.put("preferred_test_query", TEST_STR); - map.put("idle_connection_test_period", TEST_INT); - map.put("test_connection_on_checkin", TEST_BOOLEAN); - - JsonObject json = new JsonObject(map); - DataSource ds = provider.getDataSource(json); - } - -} \ No newline at end of file diff --git a/rdb/rdb-side/src/test/java/com/dtstack/flink/sql/side/rdb/table/RdbSideParserTest.java b/rdb/rdb-side/src/test/java/com/dtstack/flink/sql/side/rdb/table/RdbSideParserTest.java deleted file mode 100644 index 070ad5d09..000000000 --- a/rdb/rdb-side/src/test/java/com/dtstack/flink/sql/side/rdb/table/RdbSideParserTest.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.dtstack.flink.sql.side.rdb.table; - -import com.dtstack.flink.sql.table.AbstractTableInfo; -import com.dtstack.flink.sql.table.RdbParserTestBase; -import org.junit.Assert; -import org.junit.Test; - -import java.util.HashMap; -import java.util.Map; - -/** - * @program: flinkStreamSQL - * @author: wuren - * @create: 2020/11/09 - **/ -public class RdbSideParserTest extends RdbParserTestBase { - - @Override - public void setUp() { - this.parser = new RdbSideParser(); - } - - public void parpare(RdbSideParser parser, String type) { - this.parser = parser; - this.type = type; - } - - // @Test - public void testGetTableInfo() { - RdbSideParser parser = (RdbSideParser) this.parser; - final String tableName = "table_foo"; - final String fieldsInfo = "id INT, name VARCHAR"; - - Map props = new HashMap(); - props.put("url", "jdbc:mysql://foo:3306/db_foo"); - props.put("tablename", "table_foo"); - props.put("username", "foo"); - props.put("password", "foo"); - AbstractTableInfo tableInfo = parser.getTableInfo(tableName, fieldsInfo, props); - if (this.type != null) { - final String tableType = tableInfo.getType(); - Assert.assertTrue(this.type.equals(tableType)); - } - } - -} diff --git a/rdb/rdb-side/src/test/java/com/dtstack/flink/sql/side/rdb/table/RdbSideTableInfoTest.java b/rdb/rdb-side/src/test/java/com/dtstack/flink/sql/side/rdb/table/RdbSideTableInfoTest.java deleted file mode 100644 index 6bc0a335b..000000000 --- a/rdb/rdb-side/src/test/java/com/dtstack/flink/sql/side/rdb/table/RdbSideTableInfoTest.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.dtstack.flink.sql.side.rdb.table; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -public class RdbSideTableInfoTest { - - private RdbSideTableInfo tableInfo; - private static String SCHEMA = "TEST_schema"; - - @Before - public void setUp() { - tableInfo = new RdbSideTableInfo(); - tableInfo.setUrl("jdbc://mysql"); - tableInfo.setUserName("TEST_root"); - tableInfo.setPassword("TEST_pass"); - tableInfo.setTableName("foo_tablename"); - tableInfo.setSchema(SCHEMA); - } - -// @Test - public void testCheck() { - Boolean success = tableInfo.check(); - Assert.assertTrue(success); - } - -// @Test - public void testToString() { - tableInfo.toString(); - } - -// @Test - public void testGetSchema() { - Assert.assertEquals(SCHEMA, tableInfo.getSchema()); - } - -} \ No newline at end of file diff --git a/rdb/rdb-side/src/test/java/com/dtstack/flink/sql/side/rdb/testutil/ArgFactory.java b/rdb/rdb-side/src/test/java/com/dtstack/flink/sql/side/rdb/testutil/ArgFactory.java deleted file mode 100644 index f3793ce6e..000000000 --- a/rdb/rdb-side/src/test/java/com/dtstack/flink/sql/side/rdb/testutil/ArgFactory.java +++ /dev/null @@ -1,139 +0,0 @@ -package com.dtstack.flink.sql.side.rdb.testutil; - -import com.dtstack.flink.sql.side.BaseSideInfo; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.rdb.async.RdbAsyncSideInfo; -import com.dtstack.flink.sql.side.rdb.table.RdbSideTableInfo; -import org.apache.calcite.config.Lex; -import org.apache.calcite.sql.SqlJoin; -import org.apache.calcite.sql.SqlNode; -import org.apache.calcite.sql.SqlSelect; -import org.apache.calcite.sql.parser.SqlParseException; -import org.apache.calcite.sql.parser.SqlParser; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.table.api.Types; - -import java.util.*; - -/** - * @program: flink.sql - * @author: wuren - * @create: 2020/07/30 - **/ -public class ArgFactory { - - public static List genOutFieldInfoList() { - List outFieldInfoList = new ArrayList<>(); - FieldInfo fieldInfoa = new FieldInfo(); - fieldInfoa.setTable("x"); - fieldInfoa.setFieldName("id"); - fieldInfoa.setTypeInformation(TypeInformation.of(Integer.class)); - outFieldInfoList.add(fieldInfoa); - FieldInfo fieldInfob = new FieldInfo(); - fieldInfob.setTable("x"); - fieldInfob.setFieldName("name"); - fieldInfob.setTypeInformation(TypeInformation.of(String.class)); - outFieldInfoList.add(fieldInfob); - FieldInfo fieldInfoc = new FieldInfo(); - fieldInfoc.setTable("y"); - fieldInfoc.setFieldName("id"); - fieldInfoc.setTypeInformation(TypeInformation.of(Integer.class)); - outFieldInfoList.add(fieldInfoc); - FieldInfo fieldInfod = new FieldInfo(); - fieldInfod.setTable("y"); - fieldInfod.setFieldName("name"); - fieldInfod.setTypeInformation(TypeInformation.of(String.class)); - outFieldInfoList.add(fieldInfod); - return outFieldInfoList; - } - - public static JoinInfo genJoinInfo() { - String sql = "select \n" + - " x.id \n" + - " ,y.id \n" + - " from TEST_ods x left join TEST_dim y \n" + - " on x.id = y.id"; - -// String sql = "select \n" + -// " m.id as mid \n" + -// " ,m.bb mbb \n" + -// " ,s.channel as sid\n" + -// " ,s.name as sbb \n" + -// " from MyTable m left join hbaseSide s\n" + -// " on m.id = s.rowkey"; - SqlParser.Config config = SqlParser - .configBuilder() - .setLex(Lex.MYSQL) - .build(); - SqlParser sqlParser = SqlParser.create(sql, config); - SqlNode sqlNode = null; - try { - sqlNode = sqlParser.parseStmt(); - } catch (SqlParseException e) { - throw new RuntimeException("", e); - } - - JoinInfo joinInfo = new JoinInfo(); - joinInfo.setLeftIsSideTable(false); - joinInfo.setRightIsSideTable(true); - final String LEFT_TABLE_NAME = "TEST_ods"; - final String RIGHT_TABLE_NAME = "TEST_dim"; - joinInfo.setRightTableAlias(RIGHT_TABLE_NAME); - joinInfo.setLeftTableAlias(LEFT_TABLE_NAME); - joinInfo.setLeftTableAlias("x"); - joinInfo.setRightTableAlias("y"); - joinInfo.setLeftNode(((SqlJoin) ((SqlSelect) sqlNode).getFrom()).getLeft()); - joinInfo.setRightNode(((SqlJoin) ((SqlSelect) sqlNode).getFrom()).getRight()); - joinInfo.setCondition(((SqlJoin) ((SqlSelect) sqlNode).getFrom()).getCondition()); - joinInfo.setSelectFields(((SqlSelect) sqlNode).getSelectList()); - joinInfo.setSelectNode(((SqlSelect) sqlNode).getSelectList()); - joinInfo.setJoinType(((SqlJoin) ((SqlSelect) sqlNode).getFrom()).getJoinType()); - joinInfo.setScope("0"); - Map leftSelectField = new HashMap(); - leftSelectField.put("name", "name"); - leftSelectField.put("id", "id"); - joinInfo.setLeftSelectFieldInfo(leftSelectField); - Map rightSelectField = new HashMap(); - rightSelectField.put("id", "id"); - rightSelectField.put("name", "name"); - joinInfo.setRightSelectFieldInfo(rightSelectField); - return joinInfo; - } - - public static RdbSideTableInfo genSideTableInfo() { - RdbSideTableInfo sideTableInfo = new RdbSideTableInfo(); - sideTableInfo.setTableName("TEST_dim"); - sideTableInfo.setName("TEST_dim"); - sideTableInfo.setType("mysql"); - sideTableInfo.setFields(new String[]{"id", "name"}); - sideTableInfo.setFieldTypes(new String[]{"varchar", "varchar"}); - sideTableInfo.setFieldClasses(new Class[]{Integer.class, String.class}); - - sideTableInfo.addField("id"); - sideTableInfo.addField("name"); - sideTableInfo.addFieldType("int"); - sideTableInfo.addFieldType("varchar"); - sideTableInfo.addFieldClass(Integer.class); - sideTableInfo.addFieldClass(String.class); - return sideTableInfo; - } - - public static RowTypeInfo genRowTypeInfo() { - TypeInformation[] types = new TypeInformation[] { - Types.INT(), - Types.STRING() - }; - String[] fieldNames = new String[] { - "id", - "name" - }; - RowTypeInfo rowTypeInfo = new RowTypeInfo(types, fieldNames); - return rowTypeInfo; - } - - public static BaseSideInfo getSideInfo() { - return new RdbAsyncSideInfo(genRowTypeInfo(), genJoinInfo(), genOutFieldInfoList(), genSideTableInfo()); - } -} diff --git a/rdb/rdb-side/src/test/java/com/dtstack/flink/sql/side/rdb/util/SwitchUtilTest.java b/rdb/rdb-side/src/test/java/com/dtstack/flink/sql/side/rdb/util/SwitchUtilTest.java deleted file mode 100644 index 4cfeacd20..000000000 --- a/rdb/rdb-side/src/test/java/com/dtstack/flink/sql/side/rdb/util/SwitchUtilTest.java +++ /dev/null @@ -1,93 +0,0 @@ -package com.dtstack.flink.sql.side.rdb.util; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import java.math.BigDecimal; -import java.sql.Date; -import java.sql.Timestamp; - -public class SwitchUtilTest { - - private int INT_NUMBER = 1; - - @Test - public void testGetTargetInt() { - Object o = SwitchUtil.getTarget(INT_NUMBER, "INT"); - Assert.assertTrue((Integer) o == INT_NUMBER); - } - - @Test - public void testGetTargetLong() { - Object o = SwitchUtil.getTarget(INT_NUMBER, "IntegerUnsigned"); - Assert.assertTrue((Long) o == INT_NUMBER); - } - - @Test - public void testGetTargetBoolean() { - Object o = SwitchUtil.getTarget(true, "Boolean"); - Assert.assertTrue((Boolean) o); - } - - @Test - public void testGetTargetBlob() { - byte b = 65; - Object o = SwitchUtil.getTarget(b, "Blob"); - System.out.println(o); - Assert.assertTrue(((Byte) o) == b); - } - - @Test - public void testGetTargetString() { - Object o = SwitchUtil.getTarget(INT_NUMBER, "Text"); - Assert.assertTrue( - ((String) o).equals(String.valueOf(INT_NUMBER)) - ); - } - - @Test - public void testGetTargetFloat() { - Object o = SwitchUtil.getTarget(String.valueOf(INT_NUMBER), "FloatUnsigned"); - Assert.assertTrue((Float) o == 1.0); - } - - @Test - public void testGetTargetDouble() { - Object o = SwitchUtil.getTarget(String.valueOf(INT_NUMBER), "DoubleUnsigned"); - Assert.assertTrue((Double) o == 1.0); - } - - @Test - public void testGetTargetDecimal() { - Object o = SwitchUtil.getTarget(String.valueOf(INT_NUMBER), "DecimalUnsigned"); - Assert.assertTrue( - ((BigDecimal) o).equals(BigDecimal.valueOf(INT_NUMBER)) - ); - } - - @Test - public void testGetTargeDate() { - String dateString = "2020-02-02"; - Date date = (Date) SwitchUtil.getTarget("2020-02-02", "Date"); - Assert.assertTrue( - dateString.equals(date.toString()) - ); - } - - @Test - public void testGetTargetTimestamp() { - String timestampStr = "2020-02-02 12:12:12"; - Timestamp timestamp = (Timestamp) SwitchUtil.getTarget(timestampStr, "DateTime"); - Assert.assertTrue( - (timestampStr + ".0").equals(timestamp.toString()) - ); - } - - @Test - public void testDefault() { - String normal = "TEST"; - String str = (String) SwitchUtil.getTarget(normal, "NONE"); - Assert.assertEquals(normal, str); - } -} \ No newline at end of file diff --git a/rdb/rdb-sink/pom.xml b/rdb/rdb-sink/pom.xml index e0a0d1078..176615769 100644 --- a/rdb/rdb-sink/pom.xml +++ b/rdb/rdb-sink/pom.xml @@ -15,12 +15,4 @@ rdb-sink jar - - - com.dtstack.flink - sql.core.rdb - 1.0-SNAPSHOT - - - \ No newline at end of file diff --git a/rdb/rdb-sink/src/main/java/com/dtstack/flink/sql/sink/rdb/AbstractRdbSink.java b/rdb/rdb-sink/src/main/java/com/dtstack/flink/sql/sink/rdb/AbstractRdbSink.java deleted file mode 100644 index b81725274..000000000 --- a/rdb/rdb-sink/src/main/java/com/dtstack/flink/sql/sink/rdb/AbstractRdbSink.java +++ /dev/null @@ -1,167 +0,0 @@ -/** - * 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 com.dtstack.flink.sql.sink.rdb; - -import com.dtstack.flink.sql.sink.IStreamSinkGener; -import com.dtstack.flink.sql.sink.rdb.format.JDBCUpsertOutputFormat; -import com.dtstack.flink.sql.sink.rdb.table.RdbTableInfo; -import com.dtstack.flink.sql.table.AbstractTableInfo; -import com.dtstack.flink.sql.table.AbstractTargetTableInfo; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.api.java.typeutils.TupleTypeInfo; -import org.apache.flink.streaming.api.datastream.DataStream; -import org.apache.flink.streaming.api.datastream.DataStreamSink; -import org.apache.flink.streaming.api.functions.sink.OutputFormatSinkFunction; -import org.apache.flink.table.sinks.RetractStreamTableSink; -import org.apache.flink.table.sinks.TableSink; -import org.apache.flink.types.Row; -import com.dtstack.flink.sql.sink.rdb.dialect.JDBCDialect; - -import java.io.Serializable; -import java.util.Arrays; -import java.util.List; - -/** - * Reason: - * Date: 2018/11/27 - * Company: www.dtstack.com - * - * @author maqi - */ -public abstract class AbstractRdbSink implements RetractStreamTableSink, Serializable, IStreamSinkGener { - protected String name; - - protected String dbUrl; - - protected String userName; - - protected String password; - - protected String dbType; - - protected int batchNum = 100; - - protected long batchWaitInterval = 10000; - - protected int[] sqlTypes; - - protected String tableName; - - protected String registerTabName; - - protected String sql; - - protected List primaryKeys; - - protected String[] fieldNames; - - private TypeInformation[] fieldTypes; - - private int parallelism = 1; - - protected String schema; - - protected JDBCDialect jdbcDialect; - - protected boolean allReplace; - - protected String updateMode; - - protected long errorLimit; - - public List fieldList; - public List fieldTypeList; - public List fieldExtraInfoList; - - public AbstractRdbSink(JDBCDialect jdbcDialect) { - this.jdbcDialect = jdbcDialect; - } - - @Override - public AbstractRdbSink genStreamSink(AbstractTargetTableInfo targetTableInfo) { - RdbTableInfo rdbTableInfo = (RdbTableInfo) targetTableInfo; - this.name = rdbTableInfo.getName(); - this.batchNum = rdbTableInfo.getBatchSize() == null ? batchNum : rdbTableInfo.getBatchSize(); - this.batchWaitInterval = rdbTableInfo.getBatchWaitInterval() == null ? - batchWaitInterval : rdbTableInfo.getBatchWaitInterval(); - this.parallelism = rdbTableInfo.getParallelism() == null ? parallelism : rdbTableInfo.getParallelism(); - this.dbUrl = rdbTableInfo.getUrl(); - this.userName = rdbTableInfo.getUserName(); - this.password = rdbTableInfo.getPassword(); - this.tableName = rdbTableInfo.getTableName(); - this.registerTabName = rdbTableInfo.getName(); - this.primaryKeys = rdbTableInfo.getPrimaryKeys(); - this.dbType = rdbTableInfo.getType(); - this.schema = rdbTableInfo.getSchema(); - List fieldTypeArray = Arrays.asList(rdbTableInfo.getFieldClasses()); - this.sqlTypes = JDBCTypeConvertUtils.buildSqlTypes(fieldTypeArray); - this.allReplace = rdbTableInfo.isAllReplace(); - this.updateMode = rdbTableInfo.getUpdateMode(); - this.fieldList = rdbTableInfo.getFieldList(); - this.fieldTypeList = rdbTableInfo.getFieldTypeList(); - this.fieldExtraInfoList = rdbTableInfo.getFieldExtraInfoList(); - this.errorLimit = rdbTableInfo.getErrorLimit(); - return this; - } - - - @Override - public void emitDataStream(DataStream> dataStream) { - consumeDataStream(dataStream); - } - - @Override - public DataStreamSink consumeDataStream(DataStream> dataStream) { - DataStreamSink dataStreamSink = dataStream.addSink(new OutputFormatSinkFunction(getOutputFormat())) - .setParallelism(parallelism) - .name(registerTabName); - return dataStreamSink; - } - - @Override - public TableSink> configure(String[] fieldNames, TypeInformation[] fieldTypes) { - this.fieldNames = fieldNames; - this.fieldTypes = fieldTypes; - return this; - } - - @Override - public TupleTypeInfo> getOutputType() { - return new TupleTypeInfo(org.apache.flink.table.api.Types.BOOLEAN(), getRecordType()); - } - - @Override - public TypeInformation getRecordType() { - return new RowTypeInfo(fieldTypes, fieldNames); - } - - @Override - public String[] getFieldNames() { - return fieldNames; - } - - @Override - public TypeInformation[] getFieldTypes() { - return fieldTypes; - } - - public abstract JDBCUpsertOutputFormat getOutputFormat(); - -} diff --git a/rdb/rdb-sink/src/main/java/com/dtstack/flink/sql/sink/rdb/JDBCOptions.java b/rdb/rdb-sink/src/main/java/com/dtstack/flink/sql/sink/rdb/JDBCOptions.java deleted file mode 100644 index eacdc9b37..000000000 --- a/rdb/rdb-sink/src/main/java/com/dtstack/flink/sql/sink/rdb/JDBCOptions.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.rdb; - - -import com.dtstack.flink.sql.core.rdb.JdbcCheckKeys; -import com.dtstack.flink.sql.resource.ResourceCheck; -import com.dtstack.flink.sql.sink.rdb.dialect.JDBCDialect; -import com.google.common.collect.Maps; - -import java.util.Map; -import java.util.Objects; -import java.util.Optional; - -import static org.apache.flink.util.Preconditions.checkNotNull; - - -public class JDBCOptions { - - private String dbUrl; - private String tableName; - private String driverName; - private String username; - private String password; - private String schema; - private JDBCDialect dialect; - - private JDBCOptions(String dbUrl, String tableName, String driverName, String username, - String password, String schema, JDBCDialect dialect) { - this.dbUrl = dbUrl; - this.tableName = tableName; - this.driverName = driverName; - this.username = username; - this.password = password; - this.schema = schema; - this.dialect = dialect; - } - - public String getDbUrl() { - return dbUrl; - } - - public String getTableName() { - return tableName; - } - - public String getDriverName() { - return driverName; - } - - public String getUsername() { - return username; - } - - public String getPassword() { - return password; - } - - public JDBCDialect getDialect() { - return dialect; - } - - public String getSchema() { - return schema; - } - - public Map buildCheckProperties() { - Map properties = Maps.newHashMap(); - properties.put(JdbcCheckKeys.DRIVER_NAME, getDriverName()); - properties.put(JdbcCheckKeys.URL_KEY, getDbUrl()); - properties.put(JdbcCheckKeys.USER_NAME_KEY, getUsername()); - properties.put(JdbcCheckKeys.PASSWORD_KEY, getPassword()); - properties.put(JdbcCheckKeys.SCHEMA_KEY, getSchema()); - properties.put(JdbcCheckKeys.TABLE_NAME_KEY, getTableName()); - properties.put(JdbcCheckKeys.OPERATION_NAME_KEY, "jdbcOutputFormat"); - properties.put(JdbcCheckKeys.TABLE_TYPE_KEY, "sink"); - properties.put(JdbcCheckKeys.NEED_CHECK, String.valueOf(ResourceCheck.NEED_CHECK)); - return properties; - } - - public static Builder builder() { - return new Builder(); - } - - @Override - public boolean equals(Object o) { - if (o instanceof JDBCOptions) { - JDBCOptions options = (JDBCOptions) o; - return Objects.equals(dbUrl, options.dbUrl) && - Objects.equals(tableName, options.tableName) && - Objects.equals(driverName, options.driverName) && - Objects.equals(username, options.username) && - Objects.equals(password, options.password) && - Objects.equals(schema, options.schema) && - Objects.equals(dialect.getClass().getName(), options.dialect.getClass().getName()); - } else { - return false; - } - } - - /** - * Builder of {@link JDBCOptions}. - */ - public static class Builder { - private String dbUrl; - private String tableName; - private String driverName; - private String username; - private String password; - private String schema; - private JDBCDialect dialect; - - /** - * required, table name. - */ - public Builder setTableName(String tableName) { - this.tableName = tableName; - return this; - } - - /** - * optional, user name. - */ - public Builder setUsername(String username) { - this.username = username; - return this; - } - - /** - * optional, password. - */ - public Builder setPassword(String password) { - this.password = password; - return this; - } - - /** - * optional, driver name, dialect has a default driver name, - * See {@link JDBCDialect#defaultDriverName}. - */ - public Builder setDriverName(String driverName) { - this.driverName = driverName; - return this; - } - - /** - * optional, schema info - */ - public Builder setSchema(String schema) { - this.schema = schema; - return this; - } - - /** - * required, JDBC DB url. - */ - public Builder setDbUrl(String dbUrl) { - this.dbUrl = dbUrl; - return this; - } - - public Builder setDialect(JDBCDialect dialect) { - this.dialect = dialect; - return this; - } - - public JDBCOptions build() { - checkNotNull(dbUrl, "No dbURL supplied."); - checkNotNull(tableName, "No tableName supplied."); - - if (this.driverName == null) { - Optional optional = dialect.defaultDriverName(); - this.driverName = optional.orElseGet(() -> { - throw new NullPointerException("No driverName supplied."); - }); - } - - return new JDBCOptions(dbUrl, tableName, driverName, username, password, schema, dialect); - } - } -} diff --git a/rdb/rdb-sink/src/main/java/com/dtstack/flink/sql/sink/rdb/JDBCTypeConvertUtils.java b/rdb/rdb-sink/src/main/java/com/dtstack/flink/sql/sink/rdb/JDBCTypeConvertUtils.java deleted file mode 100644 index 5191cd400..000000000 --- a/rdb/rdb-sink/src/main/java/com/dtstack/flink/sql/sink/rdb/JDBCTypeConvertUtils.java +++ /dev/null @@ -1,296 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.rdb; - -import org.apache.flink.types.Row; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.StringReader; -import java.math.BigDecimal; -import java.sql.Clob; -import java.sql.Date; -import java.sql.NClob; -import java.sql.PreparedStatement; -import java.sql.SQLException; -import java.sql.Time; -import java.sql.Timestamp; -import java.sql.Types; -import java.util.List; - -/** - * Utils for jdbc connectors. - */ -public class JDBCTypeConvertUtils { - - private static final Logger LOG = LoggerFactory.getLogger(JDBCTypeConvertUtils.class); - - /** - * Adds a record to the prepared statement. - * - *

When this method is called, the output format is guaranteed to be opened. - * - *

WARNING: this may fail when no column types specified (because a best effort approach is attempted in order to - * insert a null value but it's not guaranteed that the JDBC driver handles PreparedStatement.setObject(pos, null)) - * - * @param upload The prepared statement. - * @param typesArray The jdbc types of the row. - * @param row The records to add to the output. - * @see PreparedStatement - */ - public static void setRecordToStatement(PreparedStatement upload, int[] typesArray, Row row) throws SQLException { - setRecordToStatement(upload, typesArray, row, null); - } - - public static void setRecordToStatement(PreparedStatement upload, int[] typesArray, Row row, int[] pkFieldIndices) throws SQLException { - if (typesArray != null && typesArray.length > 0 && typesArray.length != row.getArity()) { - LOG.warn("Column SQL types array doesn't match arity of passed Row! Check the passed array..."); - } - if (typesArray == null) { - // no types provided - for (int index = 0; index < row.getArity(); index++) { - LOG.warn("Unknown column type for column {}. Best effort approach to set its value: {}.", index + 1, row.getField(index)); - upload.setObject(index + 1, row.getField(index)); - } - } else { - // types provided - int placeIndex = 0; - for (int i = 0; i < row.getArity(); i++) { - if (isPrimaryKeyField(pkFieldIndices, i)) { - continue; - } - setField(upload, typesArray[i], row.getField(i), placeIndex++); - } - - //填充whereClause中的主键占位符 - if (pkFieldIndices != null && pkFieldIndices.length > 0) { - for (int j = 0; j < pkFieldIndices.length; j++) { - int pkIndex = pkFieldIndices[j]; - setField(upload, typesArray[pkIndex], row.getField(pkIndex), placeIndex + j); - } - } - } - } - - private static boolean isPrimaryKeyField(int[] pkFieldIndices, int fieldIndex) { - if (pkFieldIndices == null || pkFieldIndices.length <= 0) { - return false; - } - for (int index : pkFieldIndices) { - if (index == fieldIndex) { - return true; - } - } - return false; - } - - public static void setField(PreparedStatement upload, int type, Object field, int index) throws SQLException { - if (field == null) { - upload.setNull(index + 1, type); - } else { - try { - // casting values as suggested by http://docs.oracle.com/javase/1.5.0/docs/guide/jdbc/getstart/mapping.html - switch (type) { - case java.sql.Types.NULL: - upload.setNull(index + 1, type); - break; - case java.sql.Types.BOOLEAN: - case java.sql.Types.BIT: - upload.setBoolean(index + 1, (boolean) field); - break; - case java.sql.Types.CHAR: - case java.sql.Types.NCHAR: - case java.sql.Types.VARCHAR: - case java.sql.Types.LONGVARCHAR: - case java.sql.Types.LONGNVARCHAR: - upload.setString(index + 1, (String) field); - break; - case java.sql.Types.TINYINT: - upload.setByte(index + 1, (byte) field); - break; - case java.sql.Types.SMALLINT: - upload.setShort(index + 1, (short) field); - break; - case java.sql.Types.INTEGER: - upload.setInt(index + 1, (int) field); - break; - case java.sql.Types.BIGINT: - upload.setLong(index + 1, (long) field); - break; - case java.sql.Types.REAL: - upload.setFloat(index + 1, (float) field); - break; - case java.sql.Types.FLOAT: - case java.sql.Types.DOUBLE: - upload.setDouble(index + 1, Double.parseDouble(field.toString())); - break; - case java.sql.Types.DECIMAL: - case java.sql.Types.NUMERIC: - upload.setBigDecimal(index + 1, (java.math.BigDecimal) field); - break; - case java.sql.Types.DATE: - upload.setDate(index + 1, (java.sql.Date) field); - break; - case java.sql.Types.TIME: - upload.setTime(index + 1, (java.sql.Time) field); - break; - case java.sql.Types.TIMESTAMP: - upload.setTimestamp(index + 1, (java.sql.Timestamp) field); - break; - case java.sql.Types.BINARY: - case java.sql.Types.VARBINARY: - case java.sql.Types.LONGVARBINARY: - upload.setBytes(index + 1, (byte[]) field); - break; - case Types.CLOB: - case Types.NCLOB: - try (StringReader reader = new StringReader(field.toString())) { - upload.setClob(index + 1, reader); - } - break; - default: - upload.setObject(index + 1, field); - LOG.warn("Unmanaged sql type ({}) for column {}. Best effort approach to set its value: {}.", - type, index + 1, field); - // case java.sql.Types.SQLXML - // case java.sql.Types.ARRAY: - // case java.sql.Types.JAVA_OBJECT: - // case java.sql.Types.BLOB: -// case java.sql.Types.NCLOB: - // case java.sql.Types.DATALINK: - // case java.sql.Types.DISTINCT: - // case java.sql.Types.OTHER: - // case java.sql.Types.REF: - // case java.sql.Types.ROWID: - // case java.sql.Types.STRUC - } - } catch (ClassCastException e) { - // enrich the exception with detailed information. - String errorMessage = String.format( - "%s, field index: %s, field value: %s.", e.getMessage(), index, field); - ClassCastException enrichedException = new ClassCastException(errorMessage); - enrichedException.setStackTrace(e.getStackTrace()); - throw enrichedException; - } - } - } - - /** - * according to Java type, get the corresponding SQL type - * - * @param fieldTypeList the Java type - * @return the type number of the corresponding type - */ - public static int[] getSqlTypeFromFieldType(List fieldTypeList) { - int[] tmpFieldsType = new int[fieldTypeList.size()]; - for (int i = 0; i < fieldTypeList.size(); i++) { - String fieldType = fieldTypeList.get(i).toUpperCase(); - switch (fieldType) { - case "INT": - tmpFieldsType[i] = Types.INTEGER; - break; - case "BOOLEAN": - tmpFieldsType[i] = Types.BOOLEAN; - break; - case "BIGINT": - tmpFieldsType[i] = Types.BIGINT; - break; - case "SHORT": - tmpFieldsType[i] = Types.SMALLINT; - break; - case "STRING": - case "CHAR": - tmpFieldsType[i] = Types.CHAR; - break; - case "BYTE": - tmpFieldsType[i] = Types.BINARY; - break; - case "FLOAT": - tmpFieldsType[i] = Types.FLOAT; - break; - case "DOUBLE": - tmpFieldsType[i] = Types.DOUBLE; - break; - case "TIMESTAMP": - tmpFieldsType[i] = Types.TIMESTAMP; - break; - case "BIGDECIMAL": - tmpFieldsType[i] = Types.DECIMAL; - break; - case "DATE": - tmpFieldsType[i] = Types.DATE; - break; - case "TIME": - tmpFieldsType[i] = Types.TIME; - break; - default: - throw new RuntimeException("no support field type for sql. the input type:" + fieldType); - } - } - return tmpFieldsType; - } - - /** - * By now specified class type conversion. - * FIXME Follow-up has added a new type of time needs to be modified - * - * @param fieldTypeArray - */ - public static int[] buildSqlTypes(List fieldTypeArray) { - - int[] tmpFieldsType = new int[fieldTypeArray.size()]; - for (int i = 0; i < fieldTypeArray.size(); i++) { - String fieldType = fieldTypeArray.get(i).getName(); - if (fieldType.equals(Integer.class.getName())) { - tmpFieldsType[i] = Types.INTEGER; - } else if (fieldType.equals(Boolean.class.getName())) { - tmpFieldsType[i] = Types.BOOLEAN; - } else if (fieldType.equals(Long.class.getName())) { - tmpFieldsType[i] = Types.BIGINT; - } else if (fieldType.equals(Byte.class.getName())) { - tmpFieldsType[i] = Types.TINYINT; - } else if (fieldType.equals(Short.class.getName())) { - tmpFieldsType[i] = Types.SMALLINT; - } else if (fieldType.equals(String.class.getName())) { - tmpFieldsType[i] = Types.CHAR; - } else if (fieldType.equals(Float.class.getName())) { - tmpFieldsType[i] = Types.FLOAT; - } else if (fieldType.equals(Double.class.getName())) { - tmpFieldsType[i] = Types.DOUBLE; - } else if (fieldType.equals(Timestamp.class.getName())) { - tmpFieldsType[i] = Types.TIMESTAMP; - } else if (fieldType.equals(BigDecimal.class.getName())) { - tmpFieldsType[i] = Types.DECIMAL; - } else if (fieldType.equals(Date.class.getName())) { - tmpFieldsType[i] = Types.DATE; - } else if (fieldType.equals(Time.class.getName())) { - tmpFieldsType[i] = Types.TIME; - }else if (fieldType.equals(Clob.class.getName())){ - tmpFieldsType[i] = Types.CLOB; - } else if (fieldType.equals(NClob.class.getName())) { - tmpFieldsType[i] = Types.NCLOB; - } else { - throw new RuntimeException("no support field type for sql. the input type:" + fieldType); - } - } - - return tmpFieldsType; - } - -} diff --git a/rdb/rdb-sink/src/main/java/com/dtstack/flink/sql/sink/rdb/RdbSink.java b/rdb/rdb-sink/src/main/java/com/dtstack/flink/sql/sink/rdb/RdbSink.java new file mode 100644 index 000000000..babff68f9 --- /dev/null +++ b/rdb/rdb-sink/src/main/java/com/dtstack/flink/sql/sink/rdb/RdbSink.java @@ -0,0 +1,277 @@ +/** + * 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 com.dtstack.flink.sql.sink.rdb; + +import com.dtstack.flink.sql.sink.IStreamSinkGener; +import com.dtstack.flink.sql.sink.rdb.format.RetractJDBCOutputFormat; +import com.dtstack.flink.sql.sink.rdb.table.RdbTableInfo; +import com.dtstack.flink.sql.table.TargetTableInfo; +import org.apache.flink.api.common.typeinfo.TypeInformation; +import org.apache.flink.api.java.tuple.Tuple2; +import org.apache.flink.api.java.typeutils.RowTypeInfo; +import org.apache.flink.api.java.typeutils.TupleTypeInfo; +import org.apache.flink.streaming.api.datastream.DataStream; +import org.apache.flink.streaming.api.datastream.DataStreamSink; +import org.apache.flink.streaming.api.functions.sink.OutputFormatSinkFunction; +import org.apache.flink.streaming.api.functions.sink.RichSinkFunction; +import org.apache.flink.table.sinks.RetractStreamTableSink; +import org.apache.flink.table.sinks.TableSink; +import org.apache.flink.types.Row; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.sql.Date; +import java.sql.Timestamp; +import java.sql.Types; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +/** + * Reason: + * Date: 2018/11/27 + * Company: www.dtstack.com + * + * @author maqi + */ +public abstract class RdbSink implements RetractStreamTableSink, Serializable, IStreamSinkGener { + + protected String driverName; + + protected String dbURL; + + protected String userName; + + protected String password; + + protected String dbType; + + protected int batchNum = 100; + + protected long batchWaitInterval = 10000; + + protected int[] sqlTypes; + + protected String tableName; + + protected String registerTabName; + + protected String sql; + + protected List primaryKeys; + + protected String[] fieldNames; + + private TypeInformation[] fieldTypes; + + private int parallelism = -1; + + private String schema; + + public RichSinkFunction createJdbcSinkFunc() { + if (driverName == null || dbURL == null || userName == null + || password == null || sqlTypes == null || tableName == null) { + throw new RuntimeException("any of params in(driverName, dbURL, userName, password, type, tableName) " + + " must not be null. please check it!!!"); + } + RetractJDBCOutputFormat outputFormat = getOutputFormat(); + outputFormat.setDbURL(dbURL); + outputFormat.setDrivername(driverName); + outputFormat.setUsername(userName); + outputFormat.setPassword(password); + outputFormat.setInsertQuery(sql); + outputFormat.setBatchNum(batchNum); + outputFormat.setBatchWaitInterval(batchWaitInterval); + outputFormat.setTypesArray(sqlTypes); + outputFormat.setTableName(tableName); + outputFormat.setDbType(dbType); + outputFormat.setSchema(schema); + outputFormat.setDbSink(this); + + outputFormat.verifyField(); + OutputFormatSinkFunction outputFormatSinkFunc = new OutputFormatSinkFunction(outputFormat); + return outputFormatSinkFunc; + } + + + @Override + public RdbSink genStreamSink(TargetTableInfo targetTableInfo) { + RdbTableInfo rdbTableInfo = (RdbTableInfo) targetTableInfo; + + String tmpDbURL = rdbTableInfo.getUrl(); + String tmpUserName = rdbTableInfo.getUserName(); + String tmpPassword = rdbTableInfo.getPassword(); + String tmpTableName = rdbTableInfo.getTableName(); + String tmpRegisterName = rdbTableInfo.getName(); + + Integer tmpSqlBatchSize = rdbTableInfo.getBatchSize(); + if (tmpSqlBatchSize != null) { + setBatchNum(tmpSqlBatchSize); + } + + Long batchWaitInterval = rdbTableInfo.getBatchWaitInterval(); + if (batchWaitInterval != null) { + setBatchWaitInterval(batchWaitInterval); + } + + Integer tmpSinkParallelism = rdbTableInfo.getParallelism(); + if (tmpSinkParallelism != null) { + setParallelism(tmpSinkParallelism); + } + + List fields = Arrays.asList(rdbTableInfo.getFields()); + List fieldTypeArray = Arrays.asList(rdbTableInfo.getFieldClasses()); + + this.driverName = getDriverName(); + this.dbURL = tmpDbURL; + this.userName = tmpUserName; + this.password = tmpPassword; + this.tableName = tmpTableName; + this.registerTabName = tmpRegisterName; + this.primaryKeys = rdbTableInfo.getPrimaryKeys(); + this.dbType = rdbTableInfo.getType(); + this.schema = rdbTableInfo.getSchema(); + + buildSql(schema, tableName, fields); + buildSqlTypes(fieldTypeArray); + return this; + } + + + /** + * By now specified class type conversion. + * FIXME Follow-up has added a new type of time needs to be modified + * + * @param fieldTypeArray + */ + protected void buildSqlTypes(List fieldTypeArray) { + + int[] tmpFieldsType = new int[fieldTypeArray.size()]; + for (int i = 0; i < fieldTypeArray.size(); i++) { + String fieldType = fieldTypeArray.get(i).getName(); + if (fieldType.equals(Integer.class.getName())) { + tmpFieldsType[i] = Types.INTEGER; + }else if (fieldType.equals(Boolean.class.getName())) { + tmpFieldsType[i] = Types.BOOLEAN; + }else if (fieldType.equals(Long.class.getName())) { + tmpFieldsType[i] = Types.BIGINT; + } else if (fieldType.equals(Byte.class.getName())) { + tmpFieldsType[i] = Types.TINYINT; + } else if (fieldType.equals(Short.class.getName())) { + tmpFieldsType[i] = Types.SMALLINT; + } else if (fieldType.equals(String.class.getName())) { + tmpFieldsType[i] = Types.CHAR; + } else if (fieldType.equals(Byte.class.getName())) { + tmpFieldsType[i] = Types.BINARY; + } else if (fieldType.equals(Float.class.getName())) { + tmpFieldsType[i] = Types.FLOAT; + } else if (fieldType.equals(Double.class.getName())) { + tmpFieldsType[i] = Types.DOUBLE; + } else if (fieldType.equals(Timestamp.class.getName())) { + tmpFieldsType[i] = Types.TIMESTAMP; + } else if (fieldType.equals(BigDecimal.class.getName())) { + tmpFieldsType[i] = Types.DECIMAL; + } else if (fieldType.equals(Date.class.getName())) { + tmpFieldsType[i] = Types.DATE; + } else { + throw new RuntimeException("no support field type for sql. the input type:" + fieldType); + } + } + + this.sqlTypes = tmpFieldsType; + } + + + @Override + public void emitDataStream(DataStream> dataStream) { + RichSinkFunction richSinkFunction = createJdbcSinkFunc(); + DataStreamSink streamSink = dataStream.addSink(richSinkFunction); + streamSink.name(registerTabName); + if (parallelism > 0) { + streamSink.setParallelism(parallelism); + } + } + + @Override + public TableSink> configure(String[] fieldNames, TypeInformation[] fieldTypes) { + this.fieldNames = fieldNames; + this.fieldTypes = fieldTypes; + return this; + } + + + public void setBatchNum(int batchNum) { + this.batchNum = batchNum; + } + + public void setBatchWaitInterval(long batchWaitInterval) { + this.batchWaitInterval = batchWaitInterval; + } + + @Override + public TupleTypeInfo> getOutputType() { + return new TupleTypeInfo(org.apache.flink.table.api.Types.BOOLEAN(), getRecordType()); + } + + @Override + public TypeInformation getRecordType() { + return new RowTypeInfo(fieldTypes, fieldNames); + } + + @Override + public String[] getFieldNames() { + return fieldNames; + } + + @Override + public TypeInformation[] getFieldTypes() { + return fieldTypes; + } + + + public void setParallelism(int parallelism) { + this.parallelism = parallelism; + } + + public void setDbType(String dbType) { + this.dbType = dbType; + } + + /** + * you need to implements this method in your own class. + * + * @param tableName + * @param fields + */ + public abstract void buildSql(String schema, String tableName, List fields); + + /** + * sqlserver and oracle maybe implement + * + * @param tableName + * @param fieldNames + * @param realIndexes + * @return + */ + public abstract String buildUpdateSql(String schema, String tableName, List fieldNames, Map> realIndexes, List fullField); + + public abstract String getDriverName(); + + public abstract RetractJDBCOutputFormat getOutputFormat(); + +} diff --git a/rdb/rdb-sink/src/main/java/com/dtstack/flink/sql/sink/rdb/dialect/JDBCDialect.java b/rdb/rdb-sink/src/main/java/com/dtstack/flink/sql/sink/rdb/dialect/JDBCDialect.java deleted file mode 100644 index 48108246a..000000000 --- a/rdb/rdb-sink/src/main/java/com/dtstack/flink/sql/sink/rdb/dialect/JDBCDialect.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.rdb.dialect; - -import org.apache.commons.lang3.StringUtils; - -import java.io.Serializable; -import java.util.Arrays; -import java.util.Optional; -import java.util.stream.Collectors; - -/** - * Handle the SQL dialect of jdbc driver. - */ -public interface JDBCDialect extends Serializable { - - /** - * Check if this dialect instance can handle a certain jdbc url. - * @param url the jdbc url. - * @return True if the dialect can be applied on the given jdbc url. - */ - boolean canHandle(String url); - - /** - * @return the default driver class name, if user not configure the driver class name, - * then will use this one. - */ - default Optional defaultDriverName() { - return Optional.empty(); - } - - /** - * Quotes the identifier. This is used to put quotes around the identifier in case the column - * name is a reserved keyword, or in case it contains characters that require quotes (e.g. space). - * Default using double quotes {@code "} to quote. - */ - default String quoteIdentifier(String identifier) { - return "\"" + identifier + "\""; - } - - - /** - * Get dialect upsert statement, the database has its own upsert syntax, such as Mysql - * using DUPLICATE KEY UPDATE, and PostgresSQL using ON CONFLICT... DO UPDATE SET.. - * - * if allReplace is true, new data will replace previous values such as mysql replace into .. - * - * @return None if dialect does not support upsert statement, the writer will degrade to - * the use of select + update/insert, this performance is poor. - * - */ - default Optional getUpsertStatement( - String schema, String tableName, String[] fieldNames, String[] uniqueKeyFields, boolean allReplace) { - return Optional.empty(); - } - - /** - * Get row exists statement by condition fields. Default use SELECT. - */ - default String getRowExistsStatement(String tableName, String[] conditionFields) { - String fieldExpressions = Arrays.stream(conditionFields) - .map(f -> quoteIdentifier(f) + "=?") - .collect(Collectors.joining(" AND ")); - return "SELECT 1 FROM " + quoteIdentifier(tableName) + " WHERE " + fieldExpressions; - } - - /** - * Get insert into statement. - */ - default String getInsertIntoStatement(String schema, String tableName, String[] fieldNames, String[] partitionFields) { - String schemaInfo = StringUtils.isEmpty(schema) ? "" : quoteIdentifier(schema) + "."; - String columns = Arrays.stream(fieldNames) - .map(this::quoteIdentifier) - .collect(Collectors.joining(", ")); - String placeholders = Arrays.stream(fieldNames) - .map(f -> "?") - .collect(Collectors.joining(", ")); - return "INSERT INTO " + schemaInfo + quoteIdentifier(tableName) + - "(" + columns + ")" + " VALUES (" + placeholders + ")"; - } - - /** - * Get update one row statement by condition fields, default not use limit 1, - * because limit 1 is a sql dialect. - */ - default String getUpdateStatement(String tableName, String[] fieldNames, String[] conditionFields) { - String setClause = Arrays.stream(fieldNames) - .map(f -> quoteIdentifier(f) + "=?") - .collect(Collectors.joining(", ")); - String conditionClause = Arrays.stream(conditionFields) - .map(f -> quoteIdentifier(f) + "=?") - .collect(Collectors.joining(" AND ")); - return "UPDATE " + quoteIdentifier(tableName) + - " SET " + setClause + - " WHERE " + conditionClause; - } - - default String getDeleteStatement(String schema, String tableName, String[] conditionFields) { - String schemaInfo = StringUtils.isEmpty(schema) ? "" : quoteIdentifier(schema) + "."; - String conditionClause = Arrays.stream(conditionFields) - .map(f -> quoteIdentifier(f) + "=?") - .collect(Collectors.joining(" AND ")); - return "DELETE FROM " + schemaInfo + quoteIdentifier(tableName) + " WHERE " + conditionClause; - } - - /** - * Get select fields statement by condition fields. Default use SELECT. - */ - default String getSelectFromStatement(String tableName, String[] selectFields, String[] conditionFields) { - String selectExpressions = Arrays.stream(selectFields) - .map(this::quoteIdentifier) - .collect(Collectors.joining(", ")); - String fieldExpressions = Arrays.stream(conditionFields) - .map(f -> quoteIdentifier(f) + "=?") - .collect(Collectors.joining(" AND ")); - return "SELECT " + selectExpressions + " FROM " + - quoteIdentifier(tableName) + (conditionFields.length > 0 ? " WHERE " + fieldExpressions : ""); - } -} diff --git a/rdb/rdb-sink/src/main/java/com/dtstack/flink/sql/sink/rdb/format/AbstractJDBCOutputFormat.java b/rdb/rdb-sink/src/main/java/com/dtstack/flink/sql/sink/rdb/format/AbstractJDBCOutputFormat.java deleted file mode 100644 index afacd2cbc..000000000 --- a/rdb/rdb-sink/src/main/java/com/dtstack/flink/sql/sink/rdb/format/AbstractJDBCOutputFormat.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.rdb.format; - -import com.dtstack.flink.sql.outputformat.AbstractDtRichOutputFormat; -import org.apache.flink.configuration.Configuration; -import org.apache.flink.types.Row; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.SQLException; - -/** - * OutputFormat to write Rows into a JDBC database. - * - * @see Row - * @see DriverManager - */ -public abstract class AbstractJDBCOutputFormat extends AbstractDtRichOutputFormat { - - private static final long serialVersionUID = 1L; - public static final int DEFAULT_FLUSH_MAX_SIZE = 100; - public static final long DEFAULT_FLUSH_INTERVAL_MILLS = 10000L; - public static final boolean DEFAULT_ALLREPLACE_VALUE = false; - - private static final Logger LOG = LoggerFactory.getLogger(AbstractJDBCOutputFormat.class); - - protected final String username; - protected final String password; - protected final String driverName; - protected final String dbURL; - - protected transient Connection connection; - - public AbstractJDBCOutputFormat(String username, String password, String driverName, String dbUrl) { - this.username = username; - this.password = password; - this.driverName = driverName; - this.dbURL = dbUrl; - } - - @Override - public void configure(Configuration parameters) { - } - - protected void closeDbConnection() throws IOException { - if (connection != null) { - try { - connection.close(); - } catch (SQLException se) { - LOG.warn("JDBC connection could not be closed: " + se.getMessage()); - } finally { - connection = null; - } - } - } -} diff --git a/rdb/rdb-sink/src/main/java/com/dtstack/flink/sql/sink/rdb/format/ExtendOutputFormat.java b/rdb/rdb-sink/src/main/java/com/dtstack/flink/sql/sink/rdb/format/ExtendOutputFormat.java new file mode 100644 index 000000000..6265bbadd --- /dev/null +++ b/rdb/rdb-sink/src/main/java/com/dtstack/flink/sql/sink/rdb/format/ExtendOutputFormat.java @@ -0,0 +1,116 @@ +/* + * 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 com.dtstack.flink.sql.sink.rdb.format; + +import com.dtstack.flink.sql.util.DtStringUtil; +import org.apache.commons.lang3.StringUtils; +import com.google.common.collect.Maps; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +/** + * Reason: + * Date: 2018/11/30 + * Company: www.dtstack.com + * + * @author maqi + */ +public class ExtendOutputFormat extends RetractJDBCOutputFormat { + + + @Override + public boolean isReplaceInsertQuery() throws SQLException { + fillRealIndexes(); + fillFullColumns(); + + if (!getRealIndexes().isEmpty()) { + for (List value : getRealIndexes().values()) { + for (String fieldName : getDbSink().getFieldNames()) { + if (containsIgnoreCase(value, fieldName)) { + return true; + } + } + } + } + return false; + } + + /** + * get db all index + * + * @throws SQLException + */ + public void fillRealIndexes() throws SQLException { + Map> map = Maps.newHashMap(); + + ResultSet rs = getDbConn().getMetaData().getIndexInfo(null, getSchema(), DtStringUtil.addQuoteForStr(getTableName()), true, false); + + while (rs.next()) { + String indexName = rs.getString("INDEX_NAME"); + if (StringUtils.isNotBlank(indexName) && !map.containsKey(indexName)) { + map.put(indexName, new ArrayList<>()); + } + String column_name = rs.getString("COLUMN_NAME"); + if (StringUtils.isNotBlank(column_name)) { + map.get(indexName).add(column_name); + } + } + + for (Map.Entry> entry : map.entrySet()) { + String k = entry.getKey(); + List v = entry.getValue(); + if (v != null && v.size() != 0 && v.get(0) != null) { + realIndexesAdd(k, v); + } + } + } + + + + /** + * get db all column name + * + * @throws SQLException + */ + public void fillFullColumns() throws SQLException { + // table name not quote + ResultSet rs = getDbConn().getMetaData().getColumns(null, getSchema(), getTableName(), null); + while (rs.next()) { + String columnName = rs.getString("COLUMN_NAME"); + if (StringUtils.isNotBlank(columnName)) { + fullFieldAdd(columnName); + } + } + } + + public boolean containsIgnoreCase(List l, String s) { + Iterator it = l.iterator(); + while (it.hasNext()) { + if (it.next().equalsIgnoreCase(s)) + return true; + } + return false; + } + +} diff --git a/rdb/rdb-sink/src/main/java/com/dtstack/flink/sql/sink/rdb/format/JDBCUpsertOutputFormat.java b/rdb/rdb-sink/src/main/java/com/dtstack/flink/sql/sink/rdb/format/JDBCUpsertOutputFormat.java deleted file mode 100644 index 4e6fb0a6c..000000000 --- a/rdb/rdb-sink/src/main/java/com/dtstack/flink/sql/sink/rdb/format/JDBCUpsertOutputFormat.java +++ /dev/null @@ -1,372 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.rdb.format; - - -import com.dtstack.flink.sql.core.rdb.JdbcResourceCheck; -import com.dtstack.flink.sql.core.rdb.util.JdbcConnectionUtil; -import com.dtstack.flink.sql.enums.EUpdateMode; -import com.dtstack.flink.sql.exception.ExceptionTrace; -import com.dtstack.flink.sql.factory.DTThreadFactory; -import com.dtstack.flink.sql.sink.rdb.JDBCOptions; -import com.dtstack.flink.sql.sink.rdb.dialect.JDBCDialect; -import com.dtstack.flink.sql.sink.rdb.writer.AbstractUpsertWriter; -import com.dtstack.flink.sql.sink.rdb.writer.AppendOnlyWriter; -import com.dtstack.flink.sql.sink.rdb.writer.JDBCWriter; -import org.apache.commons.lang3.StringUtils; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.types.Row; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.sql.SQLException; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -import static org.apache.flink.util.Preconditions.checkNotNull; - -/** - * An upsert OutputFormat for JDBC. - * - * @author maqi - */ -public class JDBCUpsertOutputFormat extends AbstractJDBCOutputFormat> { - - private static final long serialVersionUID = 1L; - - private static final Logger LOG = LoggerFactory.getLogger(JDBCUpsertOutputFormat.class); - - static final int RECEIVEDATA_PRINT_FREQUENTY = 1000; - - private final String name; - private final String schema; - private final String tableName; - private final JDBCDialect dialect; - private final String[] fieldNames; - private final String[] keyFields; - private final String[] partitionFields; - private final int[] fieldTypes; - private final long errorLimit; - - private Map checkProperties; - - private final int flushMaxSize; - private final long flushIntervalMills; - private final boolean allReplace; - private final String updateMode; - - private transient JDBCWriter jdbcWriter; - private transient int batchCount = 0; - private transient volatile boolean closed = false; - private static volatile boolean resourceCheck = true; - - private transient ScheduledExecutorService scheduler; - private transient ScheduledFuture scheduledFuture; - - public JDBCUpsertOutputFormat( - String name, - JDBCOptions options, - String[] fieldNames, - String[] keyFields, - String[] partitionFields, - int[] fieldTypes, - int flushMaxSize, - long flushIntervalMills, - boolean allReplace, - String updateMode, - JDBCWriter jdbcWriter, - long errorLimit) { - super(options.getUsername(), options.getPassword(), options.getDriverName(), options.getDbUrl()); - this.name = name; - this.schema = options.getSchema(); - this.tableName = options.getTableName(); - this.dialect = options.getDialect(); - this.fieldNames = fieldNames; - this.keyFields = keyFields; - this.partitionFields = partitionFields; - this.fieldTypes = fieldTypes; - this.flushMaxSize = flushMaxSize; - this.flushIntervalMills = flushIntervalMills; - this.allReplace = allReplace; - this.updateMode = updateMode; - this.jdbcWriter = jdbcWriter; - this.errorLimit = errorLimit; - this.checkProperties = options.buildCheckProperties(); - } - - /** - * Connects to the target database and initializes the prepared statement. - * - * @param taskNumber The number of the parallel instance. - * @throws IOException Thrown, if the output could not be opened due to an - * I/O problem. - */ - @Override - public void open(int taskNumber, int numTasks) throws IOException { - synchronized (JDBCUpsertOutputFormat.class) { - if (resourceCheck) { - resourceCheck = false; - JdbcResourceCheck.getInstance().checkResourceStatus(this.checkProperties); - } - } - openJdbc(); - } - - public void openJdbc() throws IOException { - try { - connection = JdbcConnectionUtil.getConnectionWithRetry( - driverName, - dbURL, - username, - password - ); - initMetric(); - if(jdbcWriter == null){ - if (StringUtils.equalsIgnoreCase(updateMode, EUpdateMode.APPEND.name()) || keyFields == null || keyFields.length == 0) { - String insertSql = dialect.getInsertIntoStatement(schema, tableName, fieldNames, partitionFields); - LOG.info("execute insert sql: {}", insertSql); - jdbcWriter = new AppendOnlyWriter(insertSql, fieldTypes, this, errorLimit); - } else { - jdbcWriter = AbstractUpsertWriter.create( - dialect, schema, tableName, fieldNames, fieldTypes, keyFields, partitionFields, - getRuntimeContext().getExecutionConfig().isObjectReuseEnabled(), allReplace, this, errorLimit); - } - } else { - jdbcWriter.initMetricOutput(this); - } - jdbcWriter.open(connection); - } catch (SQLException sqe) { - throw new IllegalArgumentException("open() failed.", sqe); - } - - if (flushIntervalMills != 0) { - this.scheduler = new ScheduledThreadPoolExecutor(1, - new DTThreadFactory("jdbc-upsert-output-format")); - this.scheduledFuture = this.scheduler.scheduleWithFixedDelay(() -> { - synchronized (JDBCUpsertOutputFormat.this) { - if (closed) { - return; - } - flush(); - } - }, flushIntervalMills, flushIntervalMills, TimeUnit.MILLISECONDS); - } - } - - @Override - public synchronized void writeRecord(Tuple2 tuple2) throws IOException { - checkConnectionOpen(); - if (outRecords.getCount() % RECEIVEDATA_PRINT_FREQUENTY == 0 || LOG.isDebugEnabled()) { - LOG.info("Receive data : {}", tuple2); - } - // Receive data - outRecords.inc(); - - jdbcWriter.addRecord(tuple2); - batchCount++; - if (batchCount >= flushMaxSize) { - flush(); - } - } - - private void checkConnectionOpen() { - try { - if (!connection.isValid(10)) { - LOG.info("db connection reconnect.."); - connection = JdbcConnectionUtil.getConnectionWithRetry( - driverName, - dbURL, - username, - password - ); - jdbcWriter.prepareStatement(connection); - } - } catch (SQLException e) { - LOG.error("check connection open failed..", e); - } - } - - public synchronized void flush() { - try { - jdbcWriter.executeBatch(connection); - } catch (SQLException e) { - String errorMsg = String.format( - "Writing records to JDBC failed. Cause: [%s]", - ExceptionTrace.traceOriginalCause(e)); - throw new RuntimeException(errorMsg); - } finally { - batchCount = 0; - } - } - - /** - * Executes prepared statement and closes all resources of this instance. - * - * @throws IOException Thrown, if the input could not be closed properly. - */ - @Override - public synchronized void close() throws IOException { - if (closed) { - return; - } - closed = true; - if (this.scheduledFuture != null) { - scheduledFuture.cancel(false); - this.scheduler.shutdown(); - } - - if (batchCount > 0) { - flush(); - } - - try { - if(jdbcWriter != null){ - jdbcWriter.close(); - } - } catch (SQLException e) { - LOG.warn("Close JDBC writer failed.", e); - } - - closeDbConnection(); - } - - public static Builder builder() { - return new Builder(); - } - - /** - * Builder for a {@link JDBCUpsertOutputFormat}. - */ - public static class Builder { - protected JDBCOptions options; - protected String[] fieldNames; - protected String[] keyFields; - protected String[] partitionFields; - protected int[] fieldTypes; - protected int flushMaxSize = DEFAULT_FLUSH_MAX_SIZE; - protected long flushIntervalMills = DEFAULT_FLUSH_INTERVAL_MILLS; - protected boolean allReplace = DEFAULT_ALLREPLACE_VALUE; - protected String updateMode; - protected JDBCWriter jdbcWriter; - protected String name; - protected long errorLimit; - - /** - * required, jdbc options. - */ - public Builder setOptions(JDBCOptions options) { - this.options = options; - return this; - } - - /** - * required, field names of this jdbc sink. - */ - public Builder setFieldNames(String[] fieldNames) { - this.fieldNames = fieldNames; - return this; - } - - /** - * required, upsert unique keys. - */ - public Builder setKeyFields(List keyFields) { - this.keyFields = keyFields == null ? null : keyFields.toArray(new String[keyFields.size()]); - return this; - } - - /** - * required, field types of this jdbc sink. - */ - public Builder setFieldTypes(int[] fieldTypes) { - this.fieldTypes = fieldTypes; - return this; - } - - /** - * optional, partition Fields - * - * @param partitionFields - * @return - */ - public Builder setPartitionFields(String[] partitionFields) { - this.partitionFields = partitionFields; - return this; - } - - /** - * optional, flush max size (includes all append, upsert and delete records), - * over this number of records, will flush data. - */ - public Builder setFlushMaxSize(int flushMaxSize) { - this.flushMaxSize = flushMaxSize; - return this; - } - - /** - * optional, flush interval mills, over this time, asynchronous threads will flush data. - */ - public Builder setFlushIntervalMills(long flushIntervalMills) { - this.flushIntervalMills = flushIntervalMills; - return this; - } - - public Builder setAllReplace(boolean allReplace) { - this.allReplace = allReplace; - return this; - } - - public Builder setUpdateMode(String updateMode) { - this.updateMode = updateMode; - return this; - } - - public Builder setJDBCWriter(JDBCWriter jdbcWriter) { - this.jdbcWriter = jdbcWriter; - return this; - } - - public Builder setName(String name) { - this.name = name; - return this; - } - - public Builder setErrorLimit(long errorLimit) { - this.errorLimit = errorLimit; - return this; - } - - /** - * Finalizes the configuration and checks validity. - * - * @return Configured JDBCUpsertOutputFormat - */ - public JDBCUpsertOutputFormat build() { - checkNotNull(options, "No options supplied."); - checkNotNull(fieldNames, "No fieldNames supplied."); - return new JDBCUpsertOutputFormat( - name, options, fieldNames, keyFields, partitionFields, fieldTypes, flushMaxSize, flushIntervalMills, allReplace, updateMode, jdbcWriter, errorLimit); - } - } -} diff --git a/rdb/rdb-sink/src/main/java/com/dtstack/flink/sql/sink/rdb/format/RetractJDBCOutputFormat.java b/rdb/rdb-sink/src/main/java/com/dtstack/flink/sql/sink/rdb/format/RetractJDBCOutputFormat.java new file mode 100644 index 000000000..7653c847c --- /dev/null +++ b/rdb/rdb-sink/src/main/java/com/dtstack/flink/sql/sink/rdb/format/RetractJDBCOutputFormat.java @@ -0,0 +1,491 @@ +/* + * 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 com.dtstack.flink.sql.sink.rdb.format; + +import com.dtstack.flink.sql.sink.rdb.RdbSink; +import com.dtstack.flink.sql.util.JDBCUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.flink.api.java.tuple.Tuple2; +import org.apache.flink.configuration.Configuration; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import org.apache.flink.types.Row; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.IOException; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import com.dtstack.flink.sql.sink.MetricOutputFormat; +import sun.rmi.runtime.Log; + +/** + * OutputFormat to write tuples into a database. + * The OutputFormat has to be configured using the supplied OutputFormatBuilder. + * + */ +public class RetractJDBCOutputFormat extends MetricOutputFormat { + private static final long serialVersionUID = 1L; + + private static final Logger LOG = LoggerFactory.getLogger(RetractJDBCOutputFormat.class); + + private static int dirtyDataPrintFrequency = 1000; + + private static int receiveDataPrintFrequency = 1000; + + private String username; + private String password; + private String drivername; + private String dbURL; + private String tableName; + private String dbType; + private String schema; + private RdbSink dbSink; + // trigger preparedStatement execute batch interval + private long batchWaitInterval = 10000l; + // PreparedStatement execute batch num + private int batchNum = 100; + private String insertQuery; + public int[] typesArray; + + /** 存储用于批量写入的数据 */ + protected List rows = new ArrayList(); + + private Connection dbConn; + private PreparedStatement upload; + private transient ScheduledThreadPoolExecutor timerService; + + + //index field + private Map> realIndexes = Maps.newHashMap(); + //full field + private List fullField = Lists.newArrayList(); + + public RetractJDBCOutputFormat() { + } + + @Override + public void configure(Configuration parameters) { + } + + /** + * Connects to the target database and initializes the prepared statement. + * + * @param taskNumber The number of the parallel instance. + * @throws IOException Thrown, if the output could not be opened due to an + * I/O problem. + */ + @Override + public void open(int taskNumber, int numTasks) throws IOException { + try { + LOG.info("PreparedStatement execute batch num is {}", batchNum); + dbConn = establishConnection(); + initMetric(); + + if (existTabname()) { + if (isReplaceInsertQuery()) { + insertQuery = dbSink.buildUpdateSql(schema , tableName, Arrays.asList(dbSink.getFieldNames()), realIndexes, fullField); + } + upload = dbConn.prepareStatement(insertQuery); + } else { + throw new SQLException("Table " + tableName + " doesn't exist"); + } + + if (batchWaitInterval > 0 && batchNum > 1) { + LOG.info("open batch wait interval scheduled, interval is {} ms", batchWaitInterval); + + timerService = new ScheduledThreadPoolExecutor(1); + timerService.scheduleAtFixedRate(() -> { + submitExecuteBatch(); + }, 0, batchWaitInterval, TimeUnit.MILLISECONDS); + + } + + } catch (SQLException sqe) { + LOG.error("", sqe); + throw new IllegalArgumentException("open() failed.", sqe); + } catch (ClassNotFoundException cnfe) { + LOG.error("", cnfe); + throw new IllegalArgumentException("JDBC driver class not found.", cnfe); + } + } + + + private Connection establishConnection() throws SQLException, ClassNotFoundException { + Connection connection ; + JDBCUtils.forName(drivername, getClass().getClassLoader()); + if (username == null) { + connection = DriverManager.getConnection(dbURL); + } else { + connection = DriverManager.getConnection(dbURL, username, password); + } + connection.setAutoCommit(false); + return connection; + } + + /** + * Adds a record to the prepared statement. + *

+ * When this method is called, the output format is guaranteed to be opened. + *

+ *

+ * WARNING: this may fail when no column types specified (because a best effort approach is attempted in order to + * insert a null value but it's not guaranteed that the JDBC driver handles PreparedStatement.setObject(pos, null)) + * + * @param tuple2 The records to add to the output. + * @throws IOException Thrown, if the records could not be added due to an I/O problem. + * @see PreparedStatement + */ + @Override + public void writeRecord(Tuple2 tuple2) { + + Tuple2 tupleTrans = tuple2; + Boolean retract = tupleTrans.getField(0); + Row row = tupleTrans.getField(1); + + if (typesArray != null && typesArray.length > 0 && typesArray.length != row.getArity()) { + LOG.warn("Column SQL types array doesn't match arity of passed Row! Check the passed array..."); + } + + if (retract) { + outRecords.inc(); + if (outRecords.getCount() % receiveDataPrintFrequency == 0) { + LOG.info("Receive data : {}", row); + } + insertWrite(row); + } else { + //do nothing + } + } + + + private void insertWrite(Row row) { + checkConnectionOpen(dbConn); + try { + if (batchNum == 1) { + writeSingleRecord(row); + } else { + updatePreparedStmt(row, upload); + rows.add(row); + upload.addBatch(); + if (rows.size() >= batchNum) { + submitExecuteBatch(); + } + } + } catch (SQLException e) { + LOG.error("", e); + } + + } + + private void writeSingleRecord(Row row) { + try { + updatePreparedStmt(row, upload); + upload.executeUpdate(); + dbConn.commit(); + } catch (SQLException e) { + outDirtyRecords.inc(); + if (outDirtyRecords.getCount() % dirtyDataPrintFrequency == 0 || LOG.isDebugEnabled()) { + LOG.error("record insert failed ..", row.toString()); + LOG.error("", e); + } + } + } + + private void updatePreparedStmt(Row row, PreparedStatement pstmt) throws SQLException { + if (typesArray == null) { + // no types provided + for (int index = 0; index < row.getArity(); index++) { + LOG.warn("Unknown column type for column %s. Best effort approach to set its value: %s.", index + 1, row.getField(index)); + pstmt.setObject(index + 1, row.getField(index)); + } + } else { + // types provided + for (int index = 0; index < row.getArity(); index++) { + + if (row.getField(index) == null) { + pstmt.setNull(index + 1, typesArray[index]); + } else { + // casting values as suggested by http://docs.oracle.com/javase/1.5.0/docs/guide/jdbc/getstart/mapping.html + switch (typesArray[index]) { + case java.sql.Types.NULL: + pstmt.setNull(index + 1, typesArray[index]); + break; + case java.sql.Types.BOOLEAN: + case java.sql.Types.BIT: + pstmt.setBoolean(index + 1, (boolean) row.getField(index)); + break; + case java.sql.Types.CHAR: + case java.sql.Types.NCHAR: + case java.sql.Types.VARCHAR: + case java.sql.Types.LONGVARCHAR: + case java.sql.Types.LONGNVARCHAR: + pstmt.setString(index + 1, (String) row.getField(index)); + break; + case java.sql.Types.TINYINT: + pstmt.setByte(index + 1, (byte) row.getField(index)); + break; + case java.sql.Types.SMALLINT: + pstmt.setShort(index + 1, (short) row.getField(index)); + break; + case java.sql.Types.INTEGER: + pstmt.setInt(index + 1, (int) row.getField(index)); + break; + case java.sql.Types.BIGINT: + pstmt.setLong(index + 1, (long) row.getField(index)); + break; + case java.sql.Types.REAL: + case java.sql.Types.FLOAT: + pstmt.setFloat(index + 1, (float) row.getField(index)); + break; + case java.sql.Types.DOUBLE: + pstmt.setDouble(index + 1, (double) row.getField(index)); + break; + case java.sql.Types.DECIMAL: + case java.sql.Types.NUMERIC: + pstmt.setBigDecimal(index + 1, (java.math.BigDecimal) row.getField(index)); + break; + case java.sql.Types.DATE: + pstmt.setDate(index + 1, (java.sql.Date) row.getField(index)); + break; + case java.sql.Types.TIME: + pstmt.setTime(index + 1, (java.sql.Time) row.getField(index)); + break; + case java.sql.Types.TIMESTAMP: + pstmt.setTimestamp(index + 1, (java.sql.Timestamp) row.getField(index)); + break; + case java.sql.Types.BINARY: + case java.sql.Types.VARBINARY: + case java.sql.Types.LONGVARBINARY: + pstmt.setBytes(index + 1, (byte[]) row.getField(index)); + break; + default: + pstmt.setObject(index + 1, row.getField(index)); + LOG.warn("Unmanaged sql type (%s) for column %s. Best effort approach to set its value: %s.", + typesArray[index], index + 1, row.getField(index)); + // case java.sql.Types.SQLXML + // case java.sql.Types.ARRAY: + // case java.sql.Types.JAVA_OBJECT: + // case java.sql.Types.BLOB: + // case java.sql.Types.CLOB: + // case java.sql.Types.NCLOB: + // case java.sql.Types.DATALINK: + // case java.sql.Types.DISTINCT: + // case java.sql.Types.OTHER: + // case java.sql.Types.REF: + // case java.sql.Types.ROWID: + // case java.sql.Types.STRUC + } + } + } + } + } + + + private synchronized void submitExecuteBatch() { + try { + this.upload.executeBatch(); + dbConn.commit(); + } catch (SQLException e) { + try { + dbConn.rollback(); + } catch (SQLException e1) { + LOG.error("rollback data error !", e); + } + + rows.forEach(this::writeSingleRecord); + } finally { + rows.clear(); + } + } + + private void checkConnectionOpen(Connection dbConn) { + try { + if (dbConn.isClosed()) { + LOG.info("db connection reconnect.."); + dbConn= establishConnection(); + upload = dbConn.prepareStatement(insertQuery); + this.dbConn = dbConn; + } + } catch (SQLException e) { + LOG.error("check connection open failed..", e); + } catch (ClassNotFoundException e) { + LOG.error("load jdbc class error when reconnect db..", e); + } + } + + /** + * Executes prepared statement and closes all resources of this instance. + * + * @throws IOException Thrown, if the input could not be closed properly. + */ + @Override + public void close() throws IOException { + try { + if (upload != null) { + upload.executeBatch(); + upload.close(); + } + if (null != timerService) { + timerService.shutdown(); + LOG.info("batch wait interval scheduled service closed "); + } + } catch (SQLException se) { + LOG.info("Inputformat couldn't be closed - ", se); + } finally { + upload = null; + rows.clear(); + } + + try { + if (dbConn != null) { + dbConn.close(); + } + } catch (SQLException se) { + LOG.info("Inputformat couldn't be closed - ", se); + } finally { + dbConn = null; + } + } + + + public boolean isReplaceInsertQuery() throws SQLException { + return false; + } + + public void verifyField() { + if (StringUtils.isBlank(username)) { + LOG.info("Username was not supplied separately."); + } + if (StringUtils.isBlank(password)) { + LOG.info("Password was not supplied separately."); + } + if (StringUtils.isBlank(dbURL)) { + throw new IllegalArgumentException("No dababase URL supplied."); + } + if (StringUtils.isBlank(insertQuery)) { + throw new IllegalArgumentException("No insertQuery suplied"); + } + if (StringUtils.isBlank(drivername)) { + throw new IllegalArgumentException("No driver supplied"); + } + } + + + public void setUsername(String username) { + this.username = username; + } + + public String getSchema() { + if (StringUtils.isNotEmpty(schema)) { + return schema; + } + return null; + } + + public void setSchema(String schema) { + this.schema = schema; + } + + public boolean existTabname() throws SQLException { + return dbConn.getMetaData().getTables(null, getSchema(), tableName, null).next(); + } + + public void setPassword(String password) { + this.password = password; + } + + public void setDrivername(String drivername) { + this.drivername = drivername; + } + + public void setDbURL(String dbURL) { + this.dbURL = dbURL; + } + + public void setTableName(String tableName) { + this.tableName = tableName; + } + + public void setDbType(String dbType) { + this.dbType = dbType; + } + + public void setDbSink(RdbSink dbSink) { + this.dbSink = dbSink; + } + + public void setBatchNum(int batchNum) { + this.batchNum = batchNum; + } + + public void setInsertQuery(String insertQuery) { + this.insertQuery = insertQuery; + } + + public void setTypesArray(int[] typesArray) { + this.typesArray = typesArray; + } + + public String getDbType() { + return dbType; + } + + public RdbSink getDbSink() { + return dbSink; + } + + public Connection getDbConn() { + return dbConn; + } + + public String getTableName() { + return tableName; + } + + public void realIndexesAdd(String index, List fieldes) { + this.realIndexes.put(index, fieldes); + } + + public Map> getRealIndexes() { + return realIndexes; + } + + + public void setBatchWaitInterval(long batchWaitInterval) { + this.batchWaitInterval = batchWaitInterval; + } + + public List getFullField() { + return fullField; + } + + public void fullFieldAdd(String colName) { + this.fullField.add(colName); + } +} diff --git a/rdb/rdb-sink/src/main/java/com/dtstack/flink/sql/sink/rdb/table/RdbSinkParser.java b/rdb/rdb-sink/src/main/java/com/dtstack/flink/sql/sink/rdb/table/RdbSinkParser.java index 3e1fb86f1..beb51ffaa 100644 --- a/rdb/rdb-sink/src/main/java/com/dtstack/flink/sql/sink/rdb/table/RdbSinkParser.java +++ b/rdb/rdb-sink/src/main/java/com/dtstack/flink/sql/sink/rdb/table/RdbSinkParser.java @@ -17,8 +17,8 @@ */ package com.dtstack.flink.sql.sink.rdb.table; -import com.dtstack.flink.sql.table.AbstractTableParser; -import com.dtstack.flink.sql.table.AbstractTableInfo; +import com.dtstack.flink.sql.table.AbsTableParser; +import com.dtstack.flink.sql.table.TableInfo; import com.dtstack.flink.sql.util.MathUtil; import java.util.Map; @@ -30,9 +30,9 @@ * * @author maqi */ -public class RdbSinkParser extends AbstractTableParser { +public class RdbSinkParser extends AbsTableParser { @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { + public TableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { RdbTableInfo rdbTableInfo = new RdbTableInfo(); rdbTableInfo.setName(tableName); parseFieldsInfo(fieldsInfo, rdbTableInfo); @@ -47,12 +47,7 @@ public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map 0, "updateMode mode primary is required"); - } - - if (null != getPrimaryKeys()) { - getPrimaryKeys().forEach(pk -> { - Preconditions.checkArgument(getFieldList().contains(pk), "primary key " + pk + " not found in sink table field"); - }); - } - - - Preconditions.checkArgument(getFieldList().size() == getFieldExtraInfoList().size(), - "fields and fieldExtraInfoList attributes must be the same length"); - - // 是否在client端快速检测表资源是否可用,这样在client能访问资源的情况下快速失败,不用提交到集群检测 - if (getFastCheck()) { - JdbcResourceCheck.getInstance().checkResourceStatus(getCheckProperties()); - } return true; } @@ -220,21 +152,4 @@ public String getType() { // return super.getType().toLowerCase() + TARGET_SUFFIX; return super.getType().toLowerCase(); } - - @Override - public Map buildCheckProperties() { - Map properties = Maps.newHashMap(); - - properties.put(JdbcCheckKeys.DRIVER_NAME, getDriverName()); - properties.put(JdbcCheckKeys.URL_KEY, getUrl()); - properties.put(JdbcCheckKeys.USER_NAME_KEY, getUserName()); - properties.put(JdbcCheckKeys.PASSWORD_KEY, getPassword()); - properties.put(JdbcCheckKeys.SCHEMA_KEY, getSchema()); - properties.put(JdbcCheckKeys.TABLE_NAME_KEY, getTableName()); - properties.put(JdbcCheckKeys.OPERATION_NAME_KEY, getName()); - properties.put(JdbcCheckKeys.TABLE_TYPE_KEY, "sink"); - properties.put(JdbcCheckKeys.NEED_CHECK, String.valueOf(ResourceCheck.NEED_CHECK)); - - return properties; - } } diff --git a/rdb/rdb-sink/src/main/java/com/dtstack/flink/sql/sink/rdb/writer/AbstractUpsertWriter.java b/rdb/rdb-sink/src/main/java/com/dtstack/flink/sql/sink/rdb/writer/AbstractUpsertWriter.java deleted file mode 100644 index ecd94c95f..000000000 --- a/rdb/rdb-sink/src/main/java/com/dtstack/flink/sql/sink/rdb/writer/AbstractUpsertWriter.java +++ /dev/null @@ -1,374 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.rdb.writer; - -import com.dtstack.flink.sql.outputformat.AbstractDtRichOutputFormat; -import com.dtstack.flink.sql.sink.rdb.dialect.JDBCDialect; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.types.Row; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.function.Function; - -import static com.dtstack.flink.sql.sink.rdb.JDBCTypeConvertUtils.setRecordToStatement; -import static org.apache.flink.util.Preconditions.checkNotNull; - -/** - * Upsert writer to deal with upsert, delete message.dd - * @author maqi - */ -public abstract class AbstractUpsertWriter implements JDBCWriter { - - private static final long serialVersionUID = 1L; - private static final Logger LOG = LoggerFactory.getLogger(AbstractUpsertWriter.class); - - - public static AbstractUpsertWriter create( - JDBCDialect dialect, - String schema, - String tableName, - String[] fieldNames, - int[] fieldTypes, - String[] keyFields, - String[] partitionFields, - boolean objectReuse, - boolean allReplace, - AbstractDtRichOutputFormat metricOutputFormat, - long errorLimit) { - - checkNotNull(keyFields); - - List nameList = Arrays.asList(fieldNames); - int[] pkFields = Arrays.stream(keyFields).mapToInt(nameList::indexOf).toArray(); - int[] pkTypes = fieldTypes == null ? null : - Arrays.stream(pkFields).map(f -> fieldTypes[f]).toArray(); - - String deleteSql = dialect.getDeleteStatement(schema, tableName, keyFields); - // LOG.info("deleteSQL is :{}", deleteSql); - - Optional upsertSql = dialect.getUpsertStatement(schema, tableName, fieldNames, keyFields, allReplace); - LOG.info("execute UpsertStatement: {}", upsertSql.orElse("use UsingInsertUpdateStatement")); - - return upsertSql.map((Function) sql -> - new UpsertWriterUsingUpsertStatement( - fieldTypes, pkFields, pkTypes, objectReuse, deleteSql, sql, metricOutputFormat, errorLimit)) - .orElseGet(() -> - new UpsertWriterUsingInsertUpdateStatement( - fieldTypes, pkFields, pkTypes, objectReuse, deleteSql, - dialect.getRowExistsStatement(tableName, keyFields), - dialect.getInsertIntoStatement(schema, tableName, fieldNames, partitionFields), - dialect.getUpdateStatement(tableName, fieldNames, keyFields), - metricOutputFormat, errorLimit)); - } - - final int[] fieldTypes; - final int[] pkTypes; - private final int[] pkFields; - private final String deleteSql; - private final boolean objectReuse; - - private transient Map> keyToRows; - private transient PreparedStatement deleteStatement; - // only use metric - private transient AbstractDtRichOutputFormat metricOutputFormat; - - /** - * dirty data count limit. Once count over limit then throw exception. - */ - protected long errorLimit; - - private AbstractUpsertWriter(int[] fieldTypes, int[] pkFields, int[] pkTypes, String deleteSql, boolean objectReuse, AbstractDtRichOutputFormat metricOutputFormat, long errorLimit) { - this.fieldTypes = fieldTypes; - this.pkFields = pkFields; - this.pkTypes = pkTypes; - this.deleteSql = deleteSql; - this.objectReuse = objectReuse; - this.metricOutputFormat = metricOutputFormat; - this.errorLimit = errorLimit; - } - - @Override - public void open(Connection connection) throws SQLException { - this.keyToRows = new HashMap<>(); - prepareStatement(connection); - } - - @Override - public void prepareStatement(Connection connection) throws SQLException { - this.deleteStatement = connection.prepareStatement(deleteSql); - } - - @Override - public void addRecord(Tuple2 record) { - // we don't need perform a deep copy, because jdbc field are immutable object. - Tuple2 tuple2 = objectReuse ? new Tuple2<>(record.f0, Row.copy(record.f1)) : record; - // add records to buffer - if (tuple2.f0) { - keyToRows.put(getPrimaryKey(tuple2.f1), tuple2); - } - } - - @Override - public void executeBatch(Connection connection) throws SQLException { - try { - if (keyToRows.size() > 0) { - for (Map.Entry> entry : keyToRows.entrySet()) { - Row pk = entry.getKey(); - Tuple2 tuple = entry.getValue(); - if (tuple.f0) { - processOneRowInBatch(pk, tuple.f1); - } else { - setRecordToStatement(deleteStatement, pkTypes, pk); - deleteStatement.addBatch(); - } - } - internalExecuteBatch(); - deleteStatement.executeBatch(); - connection.commit(); - keyToRows.clear(); - } - } catch (Exception e) { - // 清理批处理中的正确字段,防止重复写入 - connection.rollback(); - connection.commit(); - cleanBatchWhenError(); - executeUpdate(connection); - } - } - - @Override - public void executeUpdate(Connection connection) throws SQLException { - if (keyToRows.size() > 0) { - for (Map.Entry> entry : keyToRows.entrySet()) { - try { - Row pk = entry.getKey(); - Tuple2 tuple = entry.getValue(); - if (tuple.f0) { - processOneRowInBatch(pk, tuple.f1); - internalExecuteBatch(); - } else { - setRecordToStatement(deleteStatement, pkTypes, pk); - deleteStatement.executeUpdate(); - } - connection.commit(); - } catch (Exception e) { - dealExecuteError( - connection, - e, - metricOutputFormat, - entry.getValue().f1, - errorLimit, - LOG - ); - } - } - keyToRows.clear(); - } - } - - abstract void processOneRowInBatch(Row pk, Row row) throws SQLException; - - abstract void internalExecuteBatch() throws SQLException; - - @Override - public void close() throws SQLException { - if (deleteStatement != null) { - deleteStatement.close(); - deleteStatement = null; - } - } - - private Row getPrimaryKey(Row row) { - Row pks = new Row(pkFields.length); - for (int i = 0; i < pkFields.length; i++) { - pks.setField(i, row.getField(pkFields[i])); - } - return pks; - } - - // ---------------------------------------------------------------------------------------- - - private static final class UpsertWriterUsingUpsertStatement extends AbstractUpsertWriter { - - private static final long serialVersionUID = 1L; - private final String upsertSql; - - private transient PreparedStatement upsertStatement; - - private UpsertWriterUsingUpsertStatement( - int[] fieldTypes, - int[] pkFields, - int[] pkTypes, - boolean objectReuse, - String deleteSql, - String upsertSql, - AbstractDtRichOutputFormat metricOutputFormat, - long errorLimit) { - super(fieldTypes, pkFields, pkTypes, deleteSql, objectReuse, metricOutputFormat, errorLimit); - this.upsertSql = upsertSql; - } - - @Override - public void initMetricOutput(AbstractDtRichOutputFormat metricOutputFormat) { - - } - - @Override - public void open(Connection connection) throws SQLException { - super.open(connection); - } - - @Override - public void prepareStatement(Connection connection) throws SQLException { - super.prepareStatement(connection); - upsertStatement = connection.prepareStatement(upsertSql); - } - - @Override - void processOneRowInBatch(Row pk, Row row) throws SQLException { - setRecordToStatement(upsertStatement, fieldTypes, row); - upsertStatement.addBatch(); - } - - @Override - public void cleanBatchWhenError() throws SQLException { - upsertStatement.clearBatch(); - upsertStatement.clearParameters(); - } - - @Override - void internalExecuteBatch() throws SQLException { - upsertStatement.executeBatch(); - } - - @Override - public void close() throws SQLException { - super.close(); - if (upsertStatement != null) { - upsertStatement.close(); - upsertStatement = null; - } - } - } - - private static final class UpsertWriterUsingInsertUpdateStatement extends AbstractUpsertWriter { - - private static final long serialVersionUID = 1L; - private final String existSql; - private final String insertSql; - private final String updateSql; - private final int[] pkFields; - - private transient PreparedStatement existStatement; - private transient PreparedStatement insertStatement; - private transient PreparedStatement updateStatement; - - private UpsertWriterUsingInsertUpdateStatement( - int[] fieldTypes, - int[] pkFields, - int[] pkTypes, - boolean objectReuse, - String deleteSql, - String existSql, - String insertSql, - String updateSql, - AbstractDtRichOutputFormat metricOutputFormat, - long errorLimit) { - super(fieldTypes, pkFields, pkTypes, deleteSql, objectReuse, metricOutputFormat, errorLimit); - this.existSql = existSql; - this.insertSql = insertSql; - this.updateSql = updateSql; - this.pkFields = pkFields; - } - - @Override - public void initMetricOutput(AbstractDtRichOutputFormat metricOutputFormat) { - - } - - @Override - public void open(Connection connection) throws SQLException { - super.open(connection); - } - - @Override - public void prepareStatement(Connection connection) throws SQLException { - super.prepareStatement(connection); - existStatement = connection.prepareStatement(existSql); - insertStatement = connection.prepareStatement(insertSql); - updateStatement = connection.prepareStatement(updateSql); - } - - @Override - void processOneRowInBatch(Row pk, Row row) throws SQLException { - setRecordToStatement(existStatement, pkTypes, pk); - ResultSet resultSet = existStatement.executeQuery(); - boolean exist = resultSet.next(); - resultSet.close(); - if (exist) { - // do update - setRecordToStatement(updateStatement, fieldTypes, row, pkFields); - updateStatement.addBatch(); - } else { - // do insert - setRecordToStatement(insertStatement, fieldTypes, row); - insertStatement.addBatch(); - } - } - - @Override - public void cleanBatchWhenError() throws SQLException { - updateStatement.clearBatch(); - insertStatement.clearBatch(); - } - - @Override - void internalExecuteBatch() throws SQLException { - updateStatement.executeBatch(); - insertStatement.executeBatch(); - } - - @Override - public void close() throws SQLException { - super.close(); - if (existStatement != null) { - existStatement.close(); - existStatement = null; - } - if (insertStatement != null) { - insertStatement.close(); - insertStatement = null; - } - if (updateStatement != null) { - updateStatement.close(); - updateStatement = null; - } - } - } -} diff --git a/rdb/rdb-sink/src/main/java/com/dtstack/flink/sql/sink/rdb/writer/AppendOnlyWriter.java b/rdb/rdb-sink/src/main/java/com/dtstack/flink/sql/sink/rdb/writer/AppendOnlyWriter.java deleted file mode 100644 index 829e9de7f..000000000 --- a/rdb/rdb-sink/src/main/java/com/dtstack/flink/sql/sink/rdb/writer/AppendOnlyWriter.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.rdb.writer; - -import com.dtstack.flink.sql.outputformat.AbstractDtRichOutputFormat; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.types.Row; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; - -import static com.dtstack.flink.sql.sink.rdb.JDBCTypeConvertUtils.setRecordToStatement; - -/** - * Just append record to jdbc, can not receive retract/delete message. - * @author maqi - */ -public class AppendOnlyWriter implements JDBCWriter { - - private static final long serialVersionUID = 1L; - - private static final Logger LOG = LoggerFactory.getLogger(AppendOnlyWriter.class); - - private final String insertSql; - private final int[] fieldTypes; - - private transient PreparedStatement statement; - private transient List rows; - // only use metric - private transient AbstractDtRichOutputFormat metricOutputFormat; - - /** - * dirty data count limit. Once count over limit then throw exception. - */ - protected long errorLimit; - - public AppendOnlyWriter(String insertSql, int[] fieldTypes, AbstractDtRichOutputFormat metricOutputFormat, long errorLimit) { - this.insertSql = insertSql; - this.fieldTypes = fieldTypes; - this.metricOutputFormat = metricOutputFormat; - this.errorLimit = errorLimit; - } - - @Override - public void initMetricOutput(AbstractDtRichOutputFormat metricOutputFormat) { - this.metricOutputFormat = metricOutputFormat; - } - - @Override - public void open(Connection connection) throws SQLException { - this.rows = new ArrayList(); - prepareStatement(connection); - } - - @Override - public void prepareStatement(Connection connection) throws SQLException { - this.statement = connection.prepareStatement(insertSql); - } - - /** - * Append mode retract/delete message will not execute - * @param record - * @throws SQLException - */ - @Override - public void addRecord(Tuple2 record) { - if (!record.f0) { - return; - } - rows.add(Row.copy(record.f1)); - } - - @Override - public void executeBatch(Connection connection) throws SQLException { - try { - rows.forEach(row -> { - try { - setRecordToStatement(statement, fieldTypes, row); - statement.addBatch(); - } catch (SQLException e) { - throw new RuntimeException(e); - } - }); - statement.executeBatch(); - connection.commit(); - rows.clear(); - } catch (Exception e) { - LOG.debug("AppendOnlyWriter executeBatch error ", e); - connection.rollback(); - connection.commit(); - cleanBatchWhenError(); - executeUpdate(connection); - } - } - - - @Override - public void executeUpdate(Connection connection) { - rows.forEach(row -> { - try { - setRecordToStatement(statement, fieldTypes, row); - statement.executeUpdate(); - connection.commit(); - } catch (Exception e) { - dealExecuteError( - connection, - e, - metricOutputFormat, - row, - errorLimit, - LOG - ); - } - }); - rows.clear(); - } - - - @Override - public void cleanBatchWhenError() throws SQLException { - statement.clearBatch(); - } - - @Override - public void close() throws SQLException { - if (statement != null) { - statement.close(); - statement = null; - } - } - -} diff --git a/rdb/rdb-sink/src/main/java/com/dtstack/flink/sql/sink/rdb/writer/JDBCWriter.java b/rdb/rdb-sink/src/main/java/com/dtstack/flink/sql/sink/rdb/writer/JDBCWriter.java deleted file mode 100644 index 2d4fc8826..000000000 --- a/rdb/rdb-sink/src/main/java/com/dtstack/flink/sql/sink/rdb/writer/JDBCWriter.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.rdb.writer; - -import com.dtstack.flink.sql.core.rdb.util.JdbcConnectionUtil; -import com.dtstack.flink.sql.exception.ExceptionTrace; -import com.dtstack.flink.sql.outputformat.AbstractDtRichOutputFormat; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.runtime.execution.SuppressRestartsException; -import org.apache.flink.types.Row; -import org.slf4j.Logger; - -import java.io.Serializable; -import java.sql.Connection; -import java.sql.SQLException; - -/** - * JDBCWriter used to execute statements (e.g. INSERT, UPSERT, DELETE). - */ -public interface JDBCWriter extends Serializable { - - int DIRTYDATA_PRINT_FREQUENTY = 1000; - - void initMetricOutput(AbstractDtRichOutputFormat metricOutputFormat); - - /** - * Open the writer by JDBC Connection. - */ - void open(Connection connection) throws SQLException; - - /** - * Create Statement from Connection. Used where the connection is created - * @throws SQLException - */ - void prepareStatement(Connection connection) throws SQLException; - - /** - * Add record to writer, the writer may cache the data. - */ - void addRecord(Tuple2 record); - - /** - * Submits a batch of commands to the database for execution. - */ - void executeBatch(Connection connection) throws SQLException; - - /** - * clean batch cache when addBatch error - * @throws SQLException - */ - void cleanBatchWhenError() throws SQLException; - - /** - * Submits a single of commands to the database for execution. - */ - void executeUpdate(Connection connection) throws SQLException; - - /** - * Close JDBC related statements and other classes. - */ - void close() throws SQLException; - - default void dealExecuteError(Connection connection, - Exception e, - AbstractDtRichOutputFormat metricOutputFormat, - Row row, - long errorLimit, - Logger LOG) { - JdbcConnectionUtil.rollBack(connection); - JdbcConnectionUtil.commit(connection); - - if (metricOutputFormat.outDirtyRecords.getCount() % DIRTYDATA_PRINT_FREQUENTY == 0 || - LOG.isDebugEnabled()) { - LOG.error( - String.format( - "record insert failed. \nRow: [%s]. \nCause: [%s]", - row.toString(), - ExceptionTrace.traceOriginalCause(e))); - } - metricOutputFormat.outDirtyRecords.inc(); - - if (errorLimit > -1) { - if (metricOutputFormat.outDirtyRecords.getCount() > errorLimit) { - throw new SuppressRestartsException(e); - } - } - } -} diff --git a/rdb/rdb-sink/src/test/java/com/dtstack/flink/sql/sink/rdb/AbstractRdbSinkTest.java b/rdb/rdb-sink/src/test/java/com/dtstack/flink/sql/sink/rdb/AbstractRdbSinkTest.java deleted file mode 100644 index 4e663946d..000000000 --- a/rdb/rdb-sink/src/test/java/com/dtstack/flink/sql/sink/rdb/AbstractRdbSinkTest.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.dtstack.flink.sql.sink.rdb; - -import com.dtstack.flink.sql.sink.rdb.table.RdbTableInfo; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.api.java.typeutils.TupleTypeInfo; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.powermock.reflect.Whitebox; - -public class AbstractRdbSinkTest { - - AbstractRdbSink rdbSink; - - @Before - public void setUp() { - rdbSink = Whitebox.newInstance(ConcreteRdbSink.class); - } - -// @Test - public void testGenStreamSink() { - RdbTableInfo tableInfo = Whitebox.newInstance(RdbTableInfo.class); - tableInfo.setType("mysql"); - tableInfo.setFieldClasses(new Class[] {Integer.class}); - AbstractRdbSink streamSink = rdbSink.genStreamSink(tableInfo); - Assert.assertEquals(streamSink, rdbSink); - } - -// @Test - public void testConfigure() { - final String[] fieldNames = new String[] {"id", "name"}; - final TypeInformation[] fieldTypes = new TypeInformation[] { - TypeInformation.of(Integer.class), - TypeInformation.of(String.class) - }; - rdbSink.configure(fieldNames, fieldTypes); - Assert.assertArrayEquals(fieldNames, rdbSink.getFieldNames()); - Assert.assertArrayEquals(fieldTypes, rdbSink.getFieldTypes()); - Assert.assertEquals( - new RowTypeInfo(fieldTypes, fieldNames), - rdbSink.getRecordType() - ); - Assert.assertEquals( - new TupleTypeInfo( - org.apache.flink.table.api.Types.BOOLEAN(), - rdbSink.getRecordType() - ), - rdbSink.getOutputType() - ); - } -} \ No newline at end of file diff --git a/rdb/rdb-sink/src/test/java/com/dtstack/flink/sql/sink/rdb/ConcreteRdbSink.java b/rdb/rdb-sink/src/test/java/com/dtstack/flink/sql/sink/rdb/ConcreteRdbSink.java deleted file mode 100644 index deac44de7..000000000 --- a/rdb/rdb-sink/src/test/java/com/dtstack/flink/sql/sink/rdb/ConcreteRdbSink.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.dtstack.flink.sql.sink.rdb; - -import com.dtstack.flink.sql.sink.rdb.dialect.JDBCDialect; -import com.dtstack.flink.sql.sink.rdb.format.JDBCUpsertOutputFormat; - -/** - * @program: flink.sql - * @author: wuren - * @create: 2020/07/31 - **/ -public class ConcreteRdbSink extends AbstractRdbSink { - - public ConcreteRdbSink(JDBCDialect jdbcDialect) { - super(jdbcDialect); - } - - @Override - public JDBCUpsertOutputFormat getOutputFormat() { - return null; - } -} diff --git a/rdb/rdb-sink/src/test/java/com/dtstack/flink/sql/sink/rdb/JDBCOptionsTest.java b/rdb/rdb-sink/src/test/java/com/dtstack/flink/sql/sink/rdb/JDBCOptionsTest.java deleted file mode 100644 index f903cbe26..000000000 --- a/rdb/rdb-sink/src/test/java/com/dtstack/flink/sql/sink/rdb/JDBCOptionsTest.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.dtstack.flink.sql.sink.rdb; - -import com.dtstack.flink.sql.sink.rdb.dialect.ConcreteJDBCDialect; -import com.dtstack.flink.sql.sink.rdb.dialect.JDBCDialect; -import org.junit.Assert; -import org.junit.Test; - -public class JDBCOptionsTest { - - @Test - public void testBuilder() { - JDBCOptions.Builder builder = JDBCOptions.builder(); - final String diverName = "org.postgresql.Driver"; - final String dbUrl = "jdbc:postgres://"; - final String tableName = "TEST_tablename"; - final String username = "TEST_user"; - final String password = "TEST_pass"; - final String schema = "TEST_schema"; - - try { - JDBCOptions options = builder - .setDbUrl(dbUrl) - .setUsername(username) - .setPassword(password) - .setTableName(tableName) - .setDialect(new ConcreteJDBCDialect()) - .setSchema(schema).build(); - } catch (NullPointerException e) { - Assert.assertEquals(e.getMessage(), "No driverName supplied."); - } - - final JDBCDialect dialect = new ConcreteJDBCDialect(); - JDBCOptions options = builder - .setDriverName(diverName) - .setDbUrl(dbUrl) - .setUsername(username) - .setPassword(password) - .setTableName(tableName) - .setDialect(dialect) - .setSchema(schema).build(); - - Assert.assertEquals(options, options); - Assert.assertNotEquals(options, null); - Assert.assertEquals(options.getDriverName(), diverName); - Assert.assertEquals(options.getDbUrl(), dbUrl); - Assert.assertEquals(options.getUsername(), username); - Assert.assertEquals(options.getPassword(), password); - Assert.assertEquals(options.getTableName(), tableName); - Assert.assertEquals(options.getDialect(), dialect); - Assert.assertEquals(options.getSchema(), schema); - } - -} \ No newline at end of file diff --git a/rdb/rdb-sink/src/test/java/com/dtstack/flink/sql/sink/rdb/JDBCTypeConvertUtilsTest.java b/rdb/rdb-sink/src/test/java/com/dtstack/flink/sql/sink/rdb/JDBCTypeConvertUtilsTest.java deleted file mode 100644 index 63e59410e..000000000 --- a/rdb/rdb-sink/src/test/java/com/dtstack/flink/sql/sink/rdb/JDBCTypeConvertUtilsTest.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.dtstack.flink.sql.sink.rdb; - -import org.apache.commons.compress.utils.Lists; -import org.apache.flink.types.Row; -import org.junit.Test; -import org.powermock.api.mockito.PowerMockito; - -import java.math.BigDecimal; -import java.sql.Connection; -import java.sql.Date; -import java.sql.PreparedStatement; -import java.sql.SQLException; -import java.sql.Timestamp; -import java.sql.Types; -import java.util.List; - -import static org.mockito.ArgumentMatchers.any; -import static org.powermock.api.mockito.PowerMockito.mock; - -public class JDBCTypeConvertUtilsTest { - - @Test - public void testSetField() { - - } - - @Test - public void testBuildSqlTypes() { - List fieldTypes = Lists.newArrayList(); - fieldTypes.add(Integer.class); - fieldTypes.add(Boolean.class); - fieldTypes.add(Long.class); - fieldTypes.add(Byte.class); - fieldTypes.add(Short.class); - fieldTypes.add(String.class); - - fieldTypes.add(Float.class); - fieldTypes.add(Double.class); - fieldTypes.add(Timestamp.class); - fieldTypes.add(BigDecimal.class); - fieldTypes.add(Date.class); - fieldTypes.add(Double.class); - JDBCTypeConvertUtils.buildSqlTypes(fieldTypes); - } - - @Test - public void testSetRecordToStatement() throws SQLException { - PreparedStatement upload = mock(PreparedStatement.class); - int[] typesArray = new int[] {java.sql.Types.INTEGER, Types.VARCHAR}; - Row row = Row.of(1, "a"); -// PowerMockito.doNothing().when(upload).setObject(any(), any()); - JDBCTypeConvertUtils.setRecordToStatement(upload, typesArray, row); - } -} \ No newline at end of file diff --git a/rdb/rdb-sink/src/test/java/com/dtstack/flink/sql/sink/rdb/dialect/ConcreteJDBCDialect.java b/rdb/rdb-sink/src/test/java/com/dtstack/flink/sql/sink/rdb/dialect/ConcreteJDBCDialect.java deleted file mode 100644 index 66e992732..000000000 --- a/rdb/rdb-sink/src/test/java/com/dtstack/flink/sql/sink/rdb/dialect/ConcreteJDBCDialect.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.dtstack.flink.sql.sink.rdb.dialect; - -/** - * @program: flink.sql - * @author: wuren - * @create: 2020/07/31 - **/ -public class ConcreteJDBCDialect implements JDBCDialect { - - @Override - public boolean canHandle(String url) { - return false; - } - -} diff --git a/rdb/rdb-sink/src/test/java/com/dtstack/flink/sql/sink/rdb/dialect/JDBCDialectTest.java b/rdb/rdb-sink/src/test/java/com/dtstack/flink/sql/sink/rdb/dialect/JDBCDialectTest.java deleted file mode 100644 index 1c2d02830..000000000 --- a/rdb/rdb-sink/src/test/java/com/dtstack/flink/sql/sink/rdb/dialect/JDBCDialectTest.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.dtstack.flink.sql.sink.rdb.dialect; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import java.util.NoSuchElementException; -import java.util.Optional; - -public class JDBCDialectTest { - - JDBCDialect dialect; - final String TABLE_NAME = "TEST_table_name"; - final String[] fieldNames = new String[] {"id", "ct"}; - final String[] conditionFields = new String[] {"id"}; - final String SCHEMA = "schema"; - @Before - public void setUp() { - dialect = new ConcreteJDBCDialect(); - } - - @Test - public void testDefaultDriverName() { - Optional o = dialect.defaultDriverName(); - try { - o.get(); - } catch (NoSuchElementException e) { } - } - - @Test - public void testQuoteIdentifier() { - String identifier = dialect.quoteIdentifier("foo"); - String normal = "\"foo\""; - Assert.assertTrue(normal.equals(identifier)); - } - - @Test - public void testGetUpsertStatement() { - Optional o = dialect.getUpsertStatement( - null, null, null, null, false - ); - final String normal = "foo"; - Assert.assertTrue( - o.orElse(normal).equals(normal) - ); - } - - @Test - public void testGetRowExistsStatement() { - String[] conditionFields = new String[] {"id"}; - String stmt = dialect.getRowExistsStatement(TABLE_NAME, conditionFields); - String normal = "SELECT 1 FROM \"TEST_table_name\" WHERE \"id\"=?"; - Assert.assertTrue(normal.equals(stmt)); - } - - @Test - public void testGetInsertIntoStatement() { - String[] partitionFields = new String[] {"ct"}; - String stmt = dialect.getInsertIntoStatement("schema", TABLE_NAME, fieldNames, partitionFields); - String normal = "INSERT INTO \"schema\".\"TEST_table_name\"(\"id\", \"ct\") VALUES (?, ?)"; - Assert.assertTrue(normal.equals(stmt)); - } - - @Test - public void testGetUpdateStatement() { - String stmt = dialect.getUpdateStatement(TABLE_NAME, fieldNames, conditionFields); - String normal = "UPDATE \"TEST_table_name\" SET \"id\"=?, \"ct\"=? WHERE \"id\"=?"; - Assert.assertTrue(normal.equals(stmt)); - - } - - @Test - public void testGetDeleteStatement() { - String stmt = dialect.getDeleteStatement(SCHEMA, TABLE_NAME, conditionFields); - String normal = "DELETE FROM \"schema\".\"TEST_table_name\" WHERE \"id\"=?"; - Assert.assertTrue(normal.equals(stmt)); - - } - - @Test - public void testGetSelectFromStatement() { - String stmt = dialect.getSelectFromStatement(TABLE_NAME, fieldNames, conditionFields); - String normal = "SELECT \"id\", \"ct\" FROM \"TEST_table_name\" WHERE \"id\"=?"; - Assert.assertTrue(normal.equals(stmt)); - } -} \ No newline at end of file diff --git a/rdb/rdb-sink/src/test/java/com/dtstack/flink/sql/sink/rdb/format/JDBCUpsertOutputFormatTest.java b/rdb/rdb-sink/src/test/java/com/dtstack/flink/sql/sink/rdb/format/JDBCUpsertOutputFormatTest.java deleted file mode 100644 index 34de1db59..000000000 --- a/rdb/rdb-sink/src/test/java/com/dtstack/flink/sql/sink/rdb/format/JDBCUpsertOutputFormatTest.java +++ /dev/null @@ -1,151 +0,0 @@ -package com.dtstack.flink.sql.sink.rdb.format; - -import com.dtstack.flink.sql.classloader.ClassLoaderManager; -import com.dtstack.flink.sql.sink.rdb.JDBCOptions; -import com.dtstack.flink.sql.sink.rdb.dialect.ConcreteJDBCDialect; -import com.dtstack.flink.sql.sink.rdb.dialect.JDBCDialect; -import com.dtstack.flink.sql.sink.rdb.writer.AppendOnlyWriter; -import com.dtstack.flink.sql.sink.rdb.writer.JDBCWriter; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.metrics.SimpleCounter; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import org.powermock.reflect.Whitebox; - -import java.io.IOException; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.SQLException; - -import static org.mockito.ArgumentMatchers.anyInt; -import static org.powermock.api.mockito.PowerMockito.mock; -import static org.powermock.api.support.membermodification.MemberMatcher.method; -import static org.powermock.api.support.membermodification.MemberModifier.suppress; -// -//@RunWith(PowerMockRunner.class) -//@PrepareForTest({ -// JDBCUpsertOutputFormat.class, -// JDBCWriter.class, -// ClassLoaderManager.class, -// AppendOnlyWriter.class, -// DriverManager.class, -// Connection.class -//}) -public class JDBCUpsertOutputFormatTest { - - JDBCUpsertOutputFormat outputFormat; - -// @Before - public void setUp() throws SQLException { - JDBCUpsertOutputFormat.Builder builder = JDBCUpsertOutputFormat.builder(); - - JDBCOptions.Builder optionsBuilder = JDBCOptions.builder(); - final String diverName = "org.postgresql.Driver"; - final String dbUrl = "jdbc:postgres://"; - final String tableName = "TEST_tablename"; - final String username = "TEST_user"; - final String password = "TEST_pass"; - final String schema = "TEST_schema"; - final JDBCDialect dialect = new ConcreteJDBCDialect(); - JDBCOptions options = optionsBuilder - .setDriverName(diverName) - .setDbUrl(dbUrl) - .setUsername(username) - .setPassword(password) - .setTableName(tableName) - .setDialect(dialect) - .setSchema(schema).build(); - - final String[] fieldNames = new String[] {"id", "name"}; - - outputFormat = - builder - .setOptions(options) - .setFieldNames(fieldNames) - .build(); - - AppendOnlyWriter writer = Whitebox.newInstance(AppendOnlyWriter.class); - Whitebox.setInternalState(outputFormat, "jdbcWriter", writer); - suppress(method(JDBCUpsertOutputFormat.class, "establishConnection")); - Connection connMock = mock(Connection.class); - PowerMockito.doReturn(false).when(connMock).isValid(anyInt()); - Whitebox.setInternalState(outputFormat, "connection", connMock); - } - -// @Test - public void testBuilder() { - JDBCUpsertOutputFormat.Builder builder = JDBCUpsertOutputFormat.builder(); - - JDBCOptions.Builder optionsBuilder = JDBCOptions.builder(); - final String diverName = "org.postgresql.Driver"; - final String dbUrl = "jdbc:postgres://"; - final String tableName = "TEST_tablename"; - final String username = "TEST_user"; - final String password = "TEST_pass"; - final String schema = "TEST_schema"; - final JDBCDialect dialect = new ConcreteJDBCDialect(); - JDBCOptions options = optionsBuilder - .setDriverName(diverName) - .setDbUrl(dbUrl) - .setUsername(username) - .setPassword(password) - .setTableName(tableName) - .setDialect(dialect) - .setSchema(schema).build(); - - final String[] fieldNames = new String[] {"id", "name"}; - JDBCUpsertOutputFormat outputFormat = - builder - .setOptions(options) - .setFieldNames(fieldNames) - .build(); - } - -// @Test - public void testOpen() throws IOException { - suppress(method( - ClassLoaderManager.class, - "forName", - String.class, - ClassLoader.class)); - suppress(method(DriverManager.class, "getConnection", String.class)); - suppress(method( - DriverManager.class, - "getConnection", - String.class, - String.class, - String.class - )); - - suppress(method(Connection.class, "setAutoCommit")); - - suppress(method(JDBCUpsertOutputFormat.class, "initMetric")); - suppress(method(AppendOnlyWriter.class, "open")); - outputFormat.open(1, 1); - } - -// @Test - public void testWriteRecord() throws NoSuchMethodException, IOException { - try { - outputFormat.writeRecord(null); - } catch (RuntimeException e) { } - - suppress(method(JDBCUpsertOutputFormat.class, "checkConnectionOpen")); - suppress(AppendOnlyWriter.class.getMethod("addRecord", Tuple2.class)); - suppress(JDBCWriter.class.getMethod("executeBatch", Connection.class)); - - outputFormat.outRecords = new SimpleCounter(); - outputFormat.writeRecord(null); - } - -// @Test - public void testClose() { - try { - outputFormat.close(); - } catch (IOException e) {} - } -} \ No newline at end of file diff --git a/rdb/rdb-sink/src/test/java/com/dtstack/flink/sql/sink/rdb/table/RdbSinkParserTest.java b/rdb/rdb-sink/src/test/java/com/dtstack/flink/sql/sink/rdb/table/RdbSinkParserTest.java deleted file mode 100644 index 83a9a3108..000000000 --- a/rdb/rdb-sink/src/test/java/com/dtstack/flink/sql/sink/rdb/table/RdbSinkParserTest.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.dtstack.flink.sql.sink.rdb.table; - -import com.dtstack.flink.sql.table.RdbParserTestBase; -import org.apache.commons.compress.utils.Lists; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * @program: flinkStreamSQL - * @author: wuren - * @create: 2020/11/09 - **/ -public class RdbSinkParserTest extends RdbParserTestBase { - - @Before - public void setUp() { - this.parser = new RdbSinkParser(); - } - -// @Test - public void testGetTableInfo() { - RdbSinkParser parser = (RdbSinkParser) this.parser; - - final String tableName = "table_foo"; - final String fieldsInfo = "id INT, name VARCHAR"; - - Map props = new HashMap(); - props.put("url", "jdbc:mysql://foo:3306/db_foo"); - props.put("tablename", "table_foo"); - props.put("username", "foo"); - props.put("password", "foo"); - props.put("batchsize", "100"); - - RdbTableInfo tableInfo = (RdbTableInfo) parser.getTableInfo(tableName, fieldsInfo, props); - List pk = Lists.newArrayList(); - pk.add("id"); - tableInfo.setUpdateMode("UPSERT"); - tableInfo.setPrimaryKeys(pk); - Assert.assertTrue(tableInfo.check()); - if (this.type != null) { - final String tableType = tableInfo.getType(); - Assert.assertTrue(this.type.equals(tableType)); - } - } - -} diff --git a/rdb/rdb-sink/src/test/java/com/dtstack/flink/sql/sink/rdb/table/RdbTableInfoTest.java b/rdb/rdb-sink/src/test/java/com/dtstack/flink/sql/sink/rdb/table/RdbTableInfoTest.java deleted file mode 100644 index 8422091ef..000000000 --- a/rdb/rdb-sink/src/test/java/com/dtstack/flink/sql/sink/rdb/table/RdbTableInfoTest.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.dtstack.flink.sql.sink.rdb.table; - -import org.junit.Assert; -import org.junit.Test; - -public class RdbTableInfoTest { - - @Test - public void test() { - RdbTableInfo tablaInfo = new RdbTableInfo(); - final String type = "mysql"; - tablaInfo.setType(type); - Assert.assertEquals(type, tablaInfo.getType()); - } - -} \ No newline at end of file diff --git a/redis5/pom.xml b/redis5/pom.xml index 3cf9d0914..894f786ef 100644 --- a/redis5/pom.xml +++ b/redis5/pom.xml @@ -15,18 +15,6 @@ redis5-sink redis5-side - - - com.dtstack.flink - sql.core - 1.0-SNAPSHOT - provided - - - redis.clients - jedis - 2.9.0 - - + \ No newline at end of file diff --git a/redis5/redis5-side/pom.xml b/redis5/redis5-side/pom.xml index 10462574c..c6623b9d2 100644 --- a/redis5/redis5-side/pom.xml +++ b/redis5/redis5-side/pom.xml @@ -11,6 +11,20 @@ 4.0.0 sql.side.redis redis-side + + + com.dtstack.flink + sql.core + 1.0-SNAPSHOT + provided + + + redis.clients + jedis + 2.8.0 + + + redis-side-core diff --git a/redis5/redis5-side/redis-all-side/pom.xml b/redis5/redis5-side/redis-all-side/pom.xml index 245b289b3..5d8a4a7d0 100644 --- a/redis5/redis5-side/redis-all-side/pom.xml +++ b/redis5/redis5-side/redis-all-side/pom.xml @@ -66,14 +66,14 @@ - + - + diff --git a/redis5/redis5-side/redis-all-side/src/main/java/com/dtstack/flink/sql/side/redis/RedisAllReqRow.java b/redis5/redis5-side/redis-all-side/src/main/java/com/dtstack/flink/sql/side/redis/RedisAllReqRow.java index 1334b48af..fba7197c6 100644 --- a/redis5/redis5-side/redis-all-side/src/main/java/com/dtstack/flink/sql/side/redis/RedisAllReqRow.java +++ b/redis5/redis5-side/redis-all-side/src/main/java/com/dtstack/flink/sql/side/redis/RedisAllReqRow.java @@ -18,56 +18,30 @@ package com.dtstack.flink.sql.side.redis; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.BaseAllReqRow; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.redis.enums.RedisType; +import com.dtstack.flink.sql.side.*; import com.dtstack.flink.sql.side.redis.table.RedisSideReqRow; import com.dtstack.flink.sql.side.redis.table.RedisSideTableInfo; -import com.dtstack.flink.sql.util.RowDataComplete; -import com.esotericsoftware.minlog.Log; -import com.google.common.collect.Maps; import org.apache.calcite.sql.JoinType; -import org.apache.commons.collections.CollectionUtils; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.table.dataformat.BaseRow; -import org.apache.flink.table.dataformat.GenericRow; +import com.google.common.collect.Maps; +import org.apache.flink.types.Row; import org.apache.flink.util.Collector; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import redis.clients.jedis.HostAndPort; -import redis.clients.jedis.Jedis; -import redis.clients.jedis.JedisCluster; -import redis.clients.jedis.JedisCommands; -import redis.clients.jedis.JedisPool; -import redis.clients.jedis.JedisSentinelPool; +import redis.clients.jedis.*; import java.io.Closeable; import java.io.IOException; import java.sql.SQLException; -import java.util.Arrays; -import java.util.Calendar; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.TreeSet; +import java.util.*; import java.util.concurrent.atomic.AtomicReference; -import java.util.regex.Matcher; -import java.util.regex.Pattern; +import java.util.stream.Collectors; -/** - * @author yanxi - */ -public class RedisAllReqRow extends BaseAllReqRow { +public class RedisAllReqRow extends AllReqRow{ private static final long serialVersionUID = 7578879189085344807L; - private static final Pattern HOST_PORT_PATTERN = Pattern.compile("(?(.*)):(?\\d+)*"); - private static final Logger LOG = LoggerFactory.getLogger(RedisAllReqRow.class); private static final int CONN_RETRY_NUM = 3; @@ -78,17 +52,17 @@ public class RedisAllReqRow extends BaseAllReqRow { private RedisSideTableInfo tableInfo; - private final AtomicReference>> cacheRef = new AtomicReference<>(); + private AtomicReference>> cacheRef = new AtomicReference<>(); - private final RedisSideReqRow redisSideReqRow; + private RedisSideReqRow redisSideReqRow; - public RedisAllReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { + public RedisAllReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, SideTableInfo sideTableInfo) { super(new RedisAllSideInfo(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo)); - this.redisSideReqRow = new RedisSideReqRow(super.sideInfo, (RedisSideTableInfo) sideTableInfo); + this.redisSideReqRow = new RedisSideReqRow(super.sideInfo); } @Override - public BaseRow fillData(BaseRow input, Object sideInput) { + public Row fillData(Row input, Object sideInput) { return redisSideReqRow.fillData(input, sideInput); } @@ -107,7 +81,6 @@ protected void reloadCache() { loadData(newCache); } catch (SQLException e) { LOG.error("", e); - throw new RuntimeException(e); } cacheRef.set(newCache); @@ -115,64 +88,122 @@ protected void reloadCache() { } @Override - public void flatMap(BaseRow input, Collector out) throws Exception { - GenericRow genericRow = (GenericRow) input; - Map inputParams = Maps.newHashMap(); - for (Integer conValIndex : sideInfo.getEqualValIndex()) { - Object equalObj = genericRow.getField(conValIndex); - if (equalObj == null) { - if (sideInfo.getJoinType() == JoinType.LEFT) { - BaseRow data = fillData(input, null); - RowDataComplete.collectBaseRow(out, data); - } - return; + public void flatMap(Row row, Collector out) throws Exception { + Map inputParams = Maps.newHashMap(); + for(Integer conValIndex : sideInfo.getEqualValIndex()){ + Object equalObj = row.getField(conValIndex); + if(equalObj == null){ + out.collect(null); } String columnName = sideInfo.getEqualFieldList().get(conValIndex); inputParams.put(columnName, equalObj.toString()); } - String key = redisSideReqRow.buildCacheKey(inputParams); + String key = buildKey(inputParams); Map cacheMap = cacheRef.get().get(key); - if (cacheMap == null) { - if (sideInfo.getJoinType() == JoinType.LEFT) { - BaseRow data = fillData(input, null); - RowDataComplete.collectBaseRow(out, data); - } else { + if (cacheMap == null){ + if(sideInfo.getJoinType() == JoinType.LEFT){ + Row data = fillData(row, null); + out.collect(data); + }else{ return; } return; } - BaseRow newRow = fillData(input, cacheMap); - RowDataComplete.collectBaseRow(out, newRow); + Row newRow = fillData(row, cacheMap); + out.collect(newRow); + } + + private String buildKey(Map inputParams) { + String tableName = tableInfo.getTableName(); + StringBuilder key = new StringBuilder(); + for (int i=0; i> tmpCache) throws SQLException { JedisCommands jedis = null; + try { - StringBuilder keyPattern = new StringBuilder(tableInfo.getTableName()); - for (int i = 0; i < tableInfo.getPrimaryKeys().size(); i++) { - keyPattern.append("_").append("*"); - } - jedis = getJedisWithRetry(CONN_RETRY_NUM); - if (null == jedis) { - throw new RuntimeException("redis all load data error,get jedis commands error!"); - } - Set keys = getRedisKeys(RedisType.parse(tableInfo.getRedisType()), jedis, keyPattern.toString()); - if (CollectionUtils.isEmpty(keys)) { - return; + for(int i=0; i keys = ((Jedis) jedis).keys(perKey); + List newPerKeys = new LinkedList<>(); + for (String key : keys){ + String[] splitKey = key.split(":"); + String newKey = splitKey[0] + ":" + splitKey[1] + ":" + splitKey[2]; + newPerKeys.add(newKey); + } + List list = newPerKeys.stream().distinct().collect(Collectors.toList()); + for(String key : list){ + Map kv = Maps.newHashMap(); + String[] primaryKv = key.split(":"); + kv.put(primaryKv[1], primaryKv[2]); + String pattern = key + "*"; + Set realKeys = ((Jedis) jedis).keys(pattern); + for (String realKey : realKeys){ + kv.put(realKey.split(":")[3], jedis.get(realKey)); + } + tmpCache.put(key, kv); + } + } else { + String perKey = tableInfo.getTableName() + "*"; + Set keys = keys((JedisCluster) jedis, perKey); + List newPerKeys = new LinkedList<>(); + for (String key : keys){ + String[] splitKey = key.split(":"); + String newKey = splitKey[0] + ":" + splitKey[1] + ":" + splitKey[2]; + newPerKeys.add(newKey); + } + List list = newPerKeys.stream().distinct().collect(Collectors.toList()); + for(String key : list){ + Map kv = Maps.newHashMap(); + String[] primaryKv = key.split(":"); + kv.put(primaryKv[1], primaryKv[2]); + String pattern = key + "*"; + Set realKeys = keys((JedisCluster) jedis, pattern); + for (String realKey : realKeys){ + kv.put(realKey.split(":")[3], jedis.get(realKey)); + } + tmpCache.put(key, kv); + } } + + + } catch (Exception e){ + LOG.error("", e); } finally { - if (jedis != null) { + if (jedis != null){ try { ((Closeable) jedis).close(); } catch (IOException e) { - Log.error("", e); + e.printStackTrace(); } } if (jedisSentinelPool != null) { @@ -187,108 +218,73 @@ private void loadData(Map> tmpCache) throws SQLExcep private JedisCommands getJedis(RedisSideTableInfo tableInfo) { String url = tableInfo.getUrl(); String password = tableInfo.getPassword(); - String database = tableInfo.getDatabase() == null ? "0" : tableInfo.getDatabase(); - String masterName = tableInfo.getMasterName(); + String database = tableInfo.getDatabase(); int timeout = tableInfo.getTimeout(); - if (timeout == 0) { - timeout = 10000; + if (timeout == 0){ + timeout = 1000; } String[] nodes = url.split(","); + String[] firstIpPort = nodes[0].split(":"); + String firstIp = firstIpPort[0]; + String firstPort = firstIpPort[1]; + Set addresses = new HashSet<>(); + Set ipPorts = new HashSet<>(); + for (String ipPort : nodes) { + ipPorts.add(ipPort); + String[] ipPortPair = ipPort.split(":"); + addresses.add(new HostAndPort(ipPortPair[0].trim(), Integer.valueOf(ipPortPair[1].trim()))); + } + if (timeout == 0){ + timeout = 1000; + } JedisCommands jedis = null; GenericObjectPoolConfig poolConfig = setPoolConfig(tableInfo.getMaxTotal(), tableInfo.getMaxIdle(), tableInfo.getMinIdle()); - switch (RedisType.parse(tableInfo.getRedisType())) { - case STANDALONE: - String firstIp = null; - String firstPort = null; - Matcher standalone = HOST_PORT_PATTERN.matcher(nodes[0]); - if (standalone.find()) { - firstIp = standalone.group("host").trim(); - firstPort = standalone.group("port").trim(); - } - if (Objects.nonNull(firstIp)) { - pool = new JedisPool(poolConfig, firstIp, Integer.parseInt(firstPort), timeout, password, Integer.parseInt(database)); - jedis = pool.getResource(); - } else { - throw new IllegalArgumentException( - String.format("redis url error. current url [%s]", nodes[0])); - } + switch (tableInfo.getRedisType()){ + //单机 + case 1: + pool = new JedisPool(poolConfig, firstIp, Integer.parseInt(firstPort), timeout, password, Integer.parseInt(database)); + jedis = pool.getResource(); break; - case SENTINEL: - Set ipPorts = new HashSet<>(Arrays.asList(nodes)); - jedisSentinelPool = new JedisSentinelPool(masterName, ipPorts, poolConfig, timeout, password, Integer.parseInt(database)); + //哨兵 + case 2: + jedisSentinelPool = new JedisSentinelPool(tableInfo.getMasterName(), ipPorts, poolConfig, timeout, password, Integer.parseInt(database)); jedis = jedisSentinelPool.getResource(); break; - case CLUSTER: - Set addresses = new HashSet<>(); - // 对ipv6 支持 - for (String node : nodes) { - Matcher matcher = HOST_PORT_PATTERN.matcher(node); - if (matcher.find()) { - String host = matcher.group("host").trim(); - String portStr = matcher.group("port").trim(); - if (org.apache.commons.lang3.StringUtils.isNotBlank(host) && org.apache.commons.lang3.StringUtils.isNotBlank(portStr)) { - // 转化为int格式的端口 - int port = Integer.parseInt(portStr); - addresses.add(new HostAndPort(host, port)); - } - } - } - jedis = new JedisCluster(addresses, timeout, timeout, 10, password, poolConfig); - break; - default: - break; + //集群 + case 3: + jedis = new JedisCluster(addresses, timeout, timeout,1, poolConfig); } return jedis; } - private JedisCommands getJedisWithRetry(int retryNum) { - while (retryNum-- > 0) { - try { - return getJedis(tableInfo); - } catch (Exception e) { - if (retryNum <= 0) { - throw new RuntimeException("getJedisWithRetry error", e); - } - try { - String jedisInfo = "url:" + tableInfo.getUrl() + ",pwd:" + tableInfo.getPassword() + ",database:" + tableInfo.getDatabase(); - LOG.warn("get conn fail, wait for 5 sec and try again, connInfo:" + jedisInfo); - Thread.sleep(LOAD_DATA_ERROR_SLEEP_TIME); - } catch (InterruptedException e1) { - LOG.error("", e1); - } - } - } - return null; - } - - private Set getRedisKeys(RedisType redisType, JedisCommands jedis, String keyPattern) { - if (!redisType.equals(RedisType.CLUSTER)) { - return ((Jedis) jedis).keys(keyPattern); - } + private Set keys(JedisCluster jedisCluster, String pattern){ Set keys = new TreeSet<>(); - Map clusterNodes = ((JedisCluster) jedis).getClusterNodes(); - for (String k : clusterNodes.keySet()) { + Map clusterNodes = jedisCluster.getClusterNodes(); + for(String k : clusterNodes.keySet()){ JedisPool jp = clusterNodes.get(k); - try (Jedis connection = jp.getResource()) { - keys.addAll(connection.keys(keyPattern)); - } catch (Exception e) { - LOG.error("Getting keys error", e); + Jedis connection = jp.getResource(); + try { + keys.addAll(connection.keys(pattern)); + } catch (Exception e){ + LOG.error("Getting keys error: {}", e); + } finally { + connection.close(); } } return keys; } - private GenericObjectPoolConfig setPoolConfig(String maxTotal, String maxIdle, String minIdle) { + private GenericObjectPoolConfig setPoolConfig(String maxTotal, String maxIdle, String minIdle){ GenericObjectPoolConfig config = new GenericObjectPoolConfig(); - if (maxTotal != null) { + if (maxTotal != null){ config.setMaxTotal(Integer.parseInt(maxTotal)); } - if (maxIdle != null) { + if (maxIdle != null){ config.setMaxIdle(Integer.parseInt(maxIdle)); } - if (minIdle != null) { + if (minIdle != null){ config.setMinIdle(Integer.parseInt(minIdle)); } return config; diff --git a/redis5/redis5-side/redis-all-side/src/main/java/com/dtstack/flink/sql/side/redis/RedisAllSideInfo.java b/redis5/redis5-side/redis-all-side/src/main/java/com/dtstack/flink/sql/side/redis/RedisAllSideInfo.java index ec0fa0d15..81e7b1f4f 100644 --- a/redis5/redis5-side/redis-all-side/src/main/java/com/dtstack/flink/sql/side/redis/RedisAllSideInfo.java +++ b/redis5/redis5-side/redis-all-side/src/main/java/com/dtstack/flink/sql/side/redis/RedisAllSideInfo.java @@ -20,27 +20,25 @@ import com.dtstack.flink.sql.side.FieldInfo; import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.BaseSideInfo; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; +import com.dtstack.flink.sql.side.SideInfo; +import com.dtstack.flink.sql.side.SideTableInfo; import com.dtstack.flink.sql.util.ParseUtils; import org.apache.calcite.sql.SqlNode; import org.apache.flink.api.java.typeutils.RowTypeInfo; import com.google.common.collect.Lists; import java.util.List; -/** - * @author yanxi - */ -public class RedisAllSideInfo extends BaseSideInfo { + +public class RedisAllSideInfo extends SideInfo { private static final long serialVersionUID = 1998703966487857613L; - public RedisAllSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { + public RedisAllSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, SideTableInfo sideTableInfo) { super(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); } @Override - public void buildEqualInfo(JoinInfo joinInfo, AbstractSideTableInfo sideTableInfo) { + public void buildEqualInfo(JoinInfo joinInfo, SideTableInfo sideTableInfo) { String sideTableName = joinInfo.getSideTableName(); SqlNode conditionNode = joinInfo.getCondition(); diff --git a/redis5/redis5-side/redis-all-side/src/test/java/com/dtstack/flink/sql/side/redis/RedisAllReqRowTest.java b/redis5/redis5-side/redis-all-side/src/test/java/com/dtstack/flink/sql/side/redis/RedisAllReqRowTest.java deleted file mode 100644 index 24ef684dd..000000000 --- a/redis5/redis5-side/redis-all-side/src/test/java/com/dtstack/flink/sql/side/redis/RedisAllReqRowTest.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.redis; - -import com.dtstack.flink.sql.side.BaseAllReqRow; -import com.dtstack.flink.sql.side.BaseSideInfo; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.redis.table.RedisSideReqRow; -import com.dtstack.flink.sql.side.redis.table.RedisSideTableInfo; -import com.google.common.collect.Maps; -import org.apache.calcite.sql.JoinType; -import org.apache.commons.compress.utils.Lists; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.table.dataformat.BaseRow; -import org.apache.flink.table.dataformat.GenericRow; -import org.apache.flink.types.Row; -import org.apache.flink.util.Collector; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PowerMockIgnore; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import org.powermock.reflect.Whitebox; -import redis.clients.jedis.Jedis; -import redis.clients.jedis.JedisPool; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicReference; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.powermock.api.support.membermodification.MemberMatcher.constructor; -import static org.powermock.api.support.membermodification.MemberModifier.suppress; - -/** - * @author: chuixue - * @create: 2020-07-20 14:43 - * @description: - **/ -@RunWith(PowerMockRunner.class) -@PrepareForTest({BaseAllReqRow.class - , RedisAllSideInfo.class - , RedisAllReqRow.class - , JedisPool.class - , RedisSideReqRow.class}) -@PowerMockIgnore({"javax.*"}) -public class RedisAllReqRowTest { - - private RedisAllReqRow redisAllReqRow; - private RowTypeInfo rowTypeInfo; - private JoinInfo joinInfo; - private List outFieldInfoList = new ArrayList<>(); - private RedisSideTableInfo tableInfo; - private BaseSideInfo sideInfo; - private AtomicReference>> cacheRef = new AtomicReference<>(); - - @Before - public void setUp() { - rowTypeInfo = PowerMockito.mock(RowTypeInfo.class); - joinInfo = PowerMockito.mock(JoinInfo.class); - tableInfo = PowerMockito.mock(RedisSideTableInfo.class); - List primaryKeys = Lists.newArrayList(); - primaryKeys.add("rowkey"); - - suppress(constructor(BaseAllReqRow.class)); - suppress(constructor(RedisAllSideInfo.class)); - when(tableInfo.getTableName()).thenReturn("sideTable"); - when(tableInfo.getPrimaryKeys()).thenReturn(primaryKeys); - - redisAllReqRow = new RedisAllReqRow(rowTypeInfo, joinInfo, outFieldInfoList, tableInfo); - Whitebox.setInternalState(redisAllReqRow, "tableInfo", tableInfo); - } - - @Test - public void testReloadCache() throws Exception { - JedisPool jedisPool = mock(JedisPool.class); - Jedis jedis = mock(Jedis.class); - - when(tableInfo.getUrl()).thenReturn("localhost:6379,localhost:6379"); - when(tableInfo.getPassword()).thenReturn("pass"); - when(tableInfo.getMaxTotal()).thenReturn("100"); - when(tableInfo.getMaxIdle()).thenReturn("100"); - when(tableInfo.getMinIdle()).thenReturn("100"); - when(tableInfo.getRedisType()).thenReturn(1); - PowerMockito.whenNew(JedisPool.class).withAnyArguments().thenReturn(jedisPool); - when(jedisPool.getResource()).thenReturn(jedis); - - redisAllReqRow.reloadCache(); - } - - //@Test - public void testFlatMap() throws Exception { - sideInfo = PowerMockito.mock(BaseSideInfo.class); - cacheRef.set(Maps.newHashMap()); - - List equalValIndex = Lists.newArrayList(); - equalValIndex.add(0); - - List equalFieldList = Lists.newArrayList(); - equalFieldList.add("rowkey"); - - GenericRow row = new GenericRow(3); - row.setField(0, 1); - row.setField(1, "bbbbbb"); - row.setField(2, "2020-07-14 01:27:43.969"); - Collector out = mock(Collector.class); - - Whitebox.setInternalState(redisAllReqRow, "sideInfo", sideInfo); - Whitebox.setInternalState(redisAllReqRow, "cacheRef", cacheRef); - when(sideInfo.getEqualValIndex()).thenReturn(equalValIndex); - when(sideInfo.getJoinType()).thenReturn(JoinType.INNER); - when(sideInfo.getEqualFieldList()).thenReturn(equalFieldList); - suppress(RedisSideReqRow.class.getMethod("fillData", Row.class, Object.class)); - - redisAllReqRow.flatMap(row, out); - } -} diff --git a/redis5/redis5-side/redis-all-side/src/test/java/com/dtstack/flink/sql/side/redis/RedisAllSideInfoTest.java b/redis5/redis5-side/redis-all-side/src/test/java/com/dtstack/flink/sql/side/redis/RedisAllSideInfoTest.java deleted file mode 100644 index 033d17e49..000000000 --- a/redis5/redis5-side/redis-all-side/src/test/java/com/dtstack/flink/sql/side/redis/RedisAllSideInfoTest.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.redis; - -import com.dtstack.flink.sql.side.*; -import com.dtstack.flink.sql.side.redis.table.RedisSideTableInfo; -import com.dtstack.flink.sql.util.ParseUtils; -import org.apache.calcite.sql.SqlNode; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -import java.util.ArrayList; -import java.util.List; - -import static org.powermock.api.support.membermodification.MemberMatcher.constructor; -import static org.powermock.api.support.membermodification.MemberMatcher.method; -import static org.powermock.api.support.membermodification.MemberModifier.suppress; - -/** - * @author: chuixue - * @create: 2020-07-20 20:16 - * @description: - **/ -@RunWith(PowerMockRunner.class) -@PrepareForTest({ - ParseUtils.class - , RedisAllSideInfo.class -}) -public class RedisAllSideInfoTest { - private RowTypeInfo rowTypeInfo; - private JoinInfo joinInfo; - private List outFieldInfoList = new ArrayList<>(); - private AbstractSideTableInfo sideTableInfo; - private RedisAllSideInfo redisAllSideInfo; - - @Before - public void setUp() { - rowTypeInfo = PowerMockito.mock(RowTypeInfo.class); - joinInfo = PowerMockito.mock(JoinInfo.class); - sideTableInfo = PowerMockito.mock(RedisSideTableInfo.class); - suppress(constructor(BaseSideInfo.class)); - redisAllSideInfo = new RedisAllSideInfo(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); - } - - @Test - public void testBuildEqualInfo() { - SqlNode conditionNode = PowerMockito.mock(SqlNode.class); - PowerMockito.when(joinInfo.getSideTableName()).thenReturn("dd"); - PowerMockito.when(joinInfo.getCondition()).thenReturn(conditionNode); - suppress(method(ParseUtils.class, "parseAnd", SqlNode.class, List.class)); - redisAllSideInfo.buildEqualInfo(joinInfo, sideTableInfo); - } -} diff --git a/redis5/redis5-side/redis-async-side/pom.xml b/redis5/redis5-side/redis-async-side/pom.xml index f3a56de22..39a6280cc 100644 --- a/redis5/redis5-side/redis-async-side/pom.xml +++ b/redis5/redis5-side/redis-async-side/pom.xml @@ -35,7 +35,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.0.0 + 1.4 package @@ -43,12 +43,6 @@ shade - - - io.netty - com.dtstack.flink.sql.side.redis.io.netty - - @@ -82,14 +76,14 @@ - + - + diff --git a/redis5/redis5-side/redis-async-side/src/main/java/com/dtstack/flink/sql/side/redis/RedisAsyncReqRow.java b/redis5/redis5-side/redis-async-side/src/main/java/com/dtstack/flink/sql/side/redis/RedisAsyncReqRow.java index b97bc4d36..e2b256421 100644 --- a/redis5/redis5-side/redis-async-side/src/main/java/com/dtstack/flink/sql/side/redis/RedisAsyncReqRow.java +++ b/redis5/redis5-side/redis-async-side/src/main/java/com/dtstack/flink/sql/side/redis/RedisAsyncReqRow.java @@ -19,42 +19,31 @@ package com.dtstack.flink.sql.side.redis; import com.dtstack.flink.sql.enums.ECacheContentType; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.BaseAsyncReqRow; -import com.dtstack.flink.sql.side.CacheMissVal; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; +import com.dtstack.flink.sql.side.*; import com.dtstack.flink.sql.side.cache.CacheObj; -import com.dtstack.flink.sql.side.redis.enums.RedisType; import com.dtstack.flink.sql.side.redis.table.RedisSideReqRow; import com.dtstack.flink.sql.side.redis.table.RedisSideTableInfo; -import com.dtstack.flink.sql.util.RowDataComplete; +import io.lettuce.core.KeyValue; import io.lettuce.core.RedisClient; import io.lettuce.core.RedisFuture; -import io.lettuce.core.RedisURI; import io.lettuce.core.api.StatefulRedisConnection; -import io.lettuce.core.api.async.RedisHashAsyncCommands; import io.lettuce.core.api.async.RedisKeyAsyncCommands; +import io.lettuce.core.api.async.RedisStringAsyncCommands; import io.lettuce.core.cluster.RedisClusterClient; import io.lettuce.core.cluster.api.StatefulRedisClusterConnection; -import io.lettuce.core.internal.HostAndPort; -import org.apache.commons.collections.MapUtils; -import org.apache.commons.lang.StringUtils; import org.apache.flink.api.java.typeutils.RowTypeInfo; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; import org.apache.flink.configuration.Configuration; import org.apache.flink.streaming.api.functions.async.ResultFuture; -import org.apache.flink.table.dataformat.BaseRow; +import org.apache.flink.types.Row; -import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.Objects; -import java.util.regex.Matcher; +import java.util.function.Consumer; -/** - * @author yanxi - */ -public class RedisAsyncReqRow extends BaseAsyncReqRow { +public class RedisAsyncReqRow extends AsyncReqRow { private static final long serialVersionUID = -2079908694523987738L; @@ -70,11 +59,11 @@ public class RedisAsyncReqRow extends BaseAsyncReqRow { private RedisSideTableInfo redisSideTableInfo; - private final RedisSideReqRow redisSideReqRow; + private RedisSideReqRow redisSideReqRow; - public RedisAsyncReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { + public RedisAsyncReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, SideTableInfo sideTableInfo) { super(new RedisAsyncSideInfo(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo)); - redisSideReqRow = new RedisSideReqRow(super.sideInfo, (RedisSideTableInfo) sideTableInfo); + redisSideReqRow = new RedisSideReqRow(super.sideInfo); } @Override @@ -87,124 +76,122 @@ public void open(Configuration parameters) throws Exception { private void buildRedisClient(RedisSideTableInfo tableInfo){ String url = redisSideTableInfo.getUrl(); String password = redisSideTableInfo.getPassword(); - + if (password != null){ + password = password + "@"; + } else { + password = ""; + } String database = redisSideTableInfo.getDatabase(); if (database == null){ database = "0"; } - switch (RedisType.parse(tableInfo.getRedisType())){ - case STANDALONE: - RedisURI redisURI = RedisURI.create("redis://" + url); - redisURI.setPassword(password); - redisURI.setDatabase(Integer.parseInt(database)); - redisClient = RedisClient.create(redisURI); + switch (tableInfo.getRedisType()){ + case 1: + StringBuilder redisUri = new StringBuilder(); + redisUri.append("redis://").append(password).append(url).append("/").append(database); + redisClient = RedisClient.create(redisUri.toString()); connection = redisClient.connect(); async = connection.async(); break; - case SENTINEL: - String[] urlSplit = StringUtils.split(url, ","); - RedisURI.Builder builder = null; - for (String item : urlSplit) { - Matcher mather = RedisSideReqRow.HOST_PORT_PATTERN.matcher(item); - if (mather.find()) { - builder = buildSentinelUri( - mather.group("host"), - mather.group("port"), - builder - ); - } else { - throw new IllegalArgumentException( - String.format("Illegal format with redis url [%s]", item) - ); - } - } - - if (Objects.nonNull(builder)) { - builder - .withPassword(tableInfo.getPassword()) - .withDatabase(Integer.parseInt(tableInfo.getDatabase())) - .withSentinelMasterId(tableInfo.getMasterName()); - } else { - throw new NullPointerException("build redis uri error!"); - } - - RedisURI uri = builder.build(); - redisClient = RedisClient.create(uri); + case 2: + StringBuilder sentinelUri = new StringBuilder(); + sentinelUri.append("redis-sentinel://").append(password) + .append(url).append("/").append(database).append("#").append(redisSideTableInfo.getMasterName()); + redisClient = RedisClient.create(sentinelUri.toString()); connection = redisClient.connect(); async = connection.async(); break; - case CLUSTER: - List clusterURIs = buildClusterURIs(url); - clusterClient = RedisClusterClient.create(clusterURIs); + case 3: + StringBuilder clusterUri = new StringBuilder(); + clusterUri.append("redis://").append(password).append(url); + clusterClient = RedisClusterClient.create(clusterUri.toString()); clusterConnection = clusterClient.connect(); async = clusterConnection.async(); - default: - break; } } - private List buildClusterURIs(String url) { - String password = redisSideTableInfo.getPassword(); - String database = redisSideTableInfo.getDatabase(); - String[] addresses = StringUtils.split(url, ","); - List redisURIs = new ArrayList<>(addresses.length); - for (String addr : addresses){ - HostAndPort hostAndPort = HostAndPort.parse(addr); - RedisURI redisURI = RedisURI.create(hostAndPort.hostText, hostAndPort.port); - if (StringUtils.isNotEmpty(password)) { - redisURI.setPassword(password); - } - if (StringUtils.isNotEmpty(database)) { - redisURI.setDatabase(Integer.valueOf(database)); - } - redisURIs.add(redisURI); - } - return redisURIs; - } - - private RedisURI.Builder buildSentinelUri( - String host, - String port, - RedisURI.Builder builder) { - if (Objects.nonNull(builder)) { - builder.withSentinel(host, Integer.parseInt(port)); - } else { - builder = RedisURI.Builder.sentinel(host, Integer.parseInt(port)); - } - return builder; - } - @Override - public BaseRow fillData(BaseRow input, Object sideInput) { + public Row fillData(Row input, Object sideInput) { return redisSideReqRow.fillData(input, sideInput); } @Override - public void handleAsyncInvoke(Map inputParams, BaseRow input, ResultFuture resultFuture) throws Exception { - String key = buildCacheKey(inputParams); - if(StringUtils.isBlank(key)){ - return; + public void asyncInvoke(Row input, ResultFuture resultFuture) throws Exception { + List keyData = Lists.newLinkedList(); + for (int i = 0; i < sideInfo.getEqualValIndex().size(); i++) { + Integer conValIndex = sideInfo.getEqualValIndex().get(i); + Object equalObj = input.getField(conValIndex); + if(equalObj == null){ + dealMissKey(input, resultFuture); + return; + } + String value = equalObj.toString(); + keyData.add(sideInfo.getEqualFieldList().get(i)); + keyData.add(value); } - RedisFuture> future = ((RedisHashAsyncCommands) async).hgetall(key); - future.thenAccept(values -> { - if (MapUtils.isNotEmpty(values)) { - try { - BaseRow row = fillData(input, values); - dealCacheData(key, CacheObj.buildCacheObj(ECacheContentType.SingleLine, values)); - RowDataComplete.completeBaseRow(resultFuture, row); - } catch (Exception e) { - dealFillDataError(input, resultFuture, e); + + String key = buildCacheKey(keyData); + + if(openCache()){ + CacheObj val = getFromCache(key); + if(val != null){ + + if(ECacheContentType.MissVal == val.getType()){ + dealMissKey(input, resultFuture); + return; + }else if(ECacheContentType.MultiLine == val.getType()){ + List rowList = Lists.newArrayList(); + for (Object jsonArray : (List) val.getContent()) { + Row row = fillData(input, val.getContent()); + rowList.add(row); + } + resultFuture.complete(rowList); + }else{ + RuntimeException exception = new RuntimeException("not support cache obj type " + val.getType()); + resultFuture.completeExceptionally(exception); } - } else { - dealMissKey(input, resultFuture); - dealCacheData(key, CacheMissVal.getMissKeyObj()); + return; } - }); + } + + Map keyValue = Maps.newHashMap(); + List value = async.keys(key + ":*").get(); + String[] values = value.toArray(new String[value.size()]); + if (values.length == 0){ + dealMissKey(input, resultFuture); + } else { + RedisFuture>> future = ((RedisStringAsyncCommands) async).mget(values); + future.thenAccept(new Consumer>>() { + @Override + public void accept(List> keyValues) { + if (keyValues.size() != 0) { + for (int i = 0; i < keyValues.size(); i++) { + String[] splitKeys = keyValues.get(i).getKey().split(":"); + keyValue.put(splitKeys[1], splitKeys[2]); + keyValue.put(splitKeys[3], keyValues.get(i).getValue()); + } + Row row = fillData(input, keyValue); + resultFuture.complete(Collections.singleton(row)); + if (openCache()) { + putCache(key, CacheObj.buildCacheObj(ECacheContentType.MultiLine, keyValue)); + } + } else { + dealMissKey(input, resultFuture); + if (openCache()) { + putCache(key, CacheMissVal.getMissKeyObj()); + } + } + } + }); + } } - @Override - public String buildCacheKey(Map refData) { - return redisSideReqRow.buildCacheKey(refData); + private String buildCacheKey(List keyData) { + String kv = String.join(":", keyData); + String tableName = redisSideTableInfo.getTableName(); + StringBuilder preKey = new StringBuilder(); + preKey.append(tableName).append(":").append(kv); + return preKey.toString(); } @Override diff --git a/redis5/redis5-side/redis-async-side/src/main/java/com/dtstack/flink/sql/side/redis/RedisAsyncSideInfo.java b/redis5/redis5-side/redis-async-side/src/main/java/com/dtstack/flink/sql/side/redis/RedisAsyncSideInfo.java index c23035ec7..9bdefe8c5 100644 --- a/redis5/redis5-side/redis-async-side/src/main/java/com/dtstack/flink/sql/side/redis/RedisAsyncSideInfo.java +++ b/redis5/redis5-side/redis-async-side/src/main/java/com/dtstack/flink/sql/side/redis/RedisAsyncSideInfo.java @@ -20,26 +20,24 @@ import com.dtstack.flink.sql.side.FieldInfo; import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.BaseSideInfo; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; +import com.dtstack.flink.sql.side.SideInfo; +import com.dtstack.flink.sql.side.SideTableInfo; import com.dtstack.flink.sql.util.ParseUtils; import org.apache.calcite.sql.SqlNode; import org.apache.flink.api.java.typeutils.RowTypeInfo; import com.google.common.collect.Lists; import java.util.List; -/** - * @author yanxi - */ -public class RedisAsyncSideInfo extends BaseSideInfo { + +public class RedisAsyncSideInfo extends SideInfo { private static final long serialVersionUID = -4851348392924455039L; - public RedisAsyncSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { + public RedisAsyncSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, SideTableInfo sideTableInfo) { super(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); } @Override - public void buildEqualInfo(JoinInfo joinInfo, AbstractSideTableInfo sideTableInfo) { + public void buildEqualInfo(JoinInfo joinInfo, SideTableInfo sideTableInfo) { String sideTableName = joinInfo.getSideTableName(); SqlNode conditionNode = joinInfo.getCondition(); diff --git a/redis5/redis5-side/redis-async-side/src/test/java/com/dtstack/flink/sql/side/redis/RedisAsyncReqRowTest.java b/redis5/redis5-side/redis-async-side/src/test/java/com/dtstack/flink/sql/side/redis/RedisAsyncReqRowTest.java deleted file mode 100644 index d89958328..000000000 --- a/redis5/redis5-side/redis-async-side/src/test/java/com/dtstack/flink/sql/side/redis/RedisAsyncReqRowTest.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.redis; - -import com.dtstack.flink.sql.side.*; -import com.dtstack.flink.sql.side.redis.table.RedisSideTableInfo; -import com.google.common.collect.Maps; -import io.lettuce.core.RedisAsyncCommandsImpl; -import io.lettuce.core.RedisClient; -import io.lettuce.core.RedisURI; -import io.lettuce.core.api.StatefulRedisConnection; -import io.lettuce.core.api.async.RedisHashAsyncCommands; -import io.lettuce.core.api.async.RedisKeyAsyncCommands; -import io.lettuce.core.cluster.RedisClusterClient; -import io.lettuce.core.cluster.api.StatefulRedisClusterConnection; -import io.lettuce.core.codec.StringCodec; -import org.apache.commons.compress.utils.Lists; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.configuration.Configuration; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import org.powermock.reflect.Whitebox; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.function.Consumer; - -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.powermock.api.support.membermodification.MemberMatcher.constructor; -import static org.powermock.api.support.membermodification.MemberModifier.suppress; - -/** - * @author: chuixue - * @create: 2020-07-22 09:12 - * @description: - **/ -@RunWith(PowerMockRunner.class) -@PrepareForTest({BaseAsyncReqRow.class - , RedisAsyncSideInfo.class - , RedisClient.class - , RedisAsyncReqRow.class - , RedisHashAsyncCommands.class - , RedisSideTableInfo.class - , RedisClusterClient.class - , StatefulRedisClusterConnection.class}) -public class RedisAsyncReqRowTest { - private RedisAsyncReqRow redisAsyncReqRow; - private RowTypeInfo rowTypeInfo; - private JoinInfo joinInfo; - private List outFieldInfoList = new ArrayList<>(); - private BaseSideInfo sideInfo; - private RedisSideTableInfo redisSideTableInfo; - private RedisClient redisClient; - private StatefulRedisConnection connection; - private StatefulRedisClusterConnection clusterConnection; - private RedisKeyAsyncCommands async = new RedisAsyncCommandsImpl<>(null, new StringCodec()); - private RedisClusterClient clusterClient; - - @Captor - private ArgumentCaptor>> cb; - - @Before - public void setUp() { - rowTypeInfo = PowerMockito.mock(RowTypeInfo.class); - joinInfo = PowerMockito.mock(JoinInfo.class); - sideInfo = PowerMockito.mock(BaseSideInfo.class); - redisSideTableInfo = PowerMockito.mock(RedisSideTableInfo.class); - redisClient = mock(RedisClient.class); - connection = mock(StatefulRedisConnection.class); - clusterConnection = mock(StatefulRedisClusterConnection.class); - clusterClient = mock(RedisClusterClient.class); - - List primaryKeys = Lists.newArrayList(); - primaryKeys.add("rowkey"); - - suppress(constructor(RedisAsyncSideInfo.class)); - suppress(constructor(BaseAsyncReqRow.class)); - - redisAsyncReqRow = new RedisAsyncReqRow(rowTypeInfo, joinInfo, outFieldInfoList, redisSideTableInfo); - Whitebox.setInternalState(redisAsyncReqRow, "sideInfo", sideInfo); - Whitebox.setInternalState(redisAsyncReqRow, "redisSideTableInfo", redisSideTableInfo); - Whitebox.setInternalState(redisAsyncReqRow, "connection", connection); - Whitebox.setInternalState(redisAsyncReqRow, "redisClient", redisClient); - Whitebox.setInternalState(redisAsyncReqRow, "clusterConnection", clusterConnection); - Whitebox.setInternalState(redisAsyncReqRow, "clusterClient", clusterClient); - Whitebox.setInternalState(redisAsyncReqRow, "async", async); - } - - @Test - public void testOpen() throws Exception { - PowerMockito.mockStatic(RedisClient.class); - - when(RedisClient.create(RedisURI.create("redis://localhost:6379,localhost:6379"))).thenReturn(redisClient); - when(redisClient.connect()).thenReturn(connection); - suppress(BaseAsyncReqRow.class.getMethod("open", Configuration.class)); - when(sideInfo.getSideTableInfo()).thenReturn(redisSideTableInfo); - when(redisSideTableInfo.getUrl()).thenReturn("localhost:6379,localhost:6379"); - when(redisSideTableInfo.getPassword()).thenReturn("pass"); - when(redisSideTableInfo.getMasterName()).thenReturn("master"); - - when(redisSideTableInfo.getRedisType()).thenReturn(1); - redisAsyncReqRow.open(new Configuration()); - - PowerMockito.mockStatic(RedisClusterClient.class); - when(RedisClusterClient.create(anyString())).thenReturn(clusterClient); - when(clusterClient.connect()).thenReturn(clusterConnection); - redisAsyncReqRow.open(new Configuration()); - } - - @Test - public void testBuildCacheKey() throws Exception { - List primaryKeys = Lists.newArrayList(); - primaryKeys.add("rowkey"); - Map inputParams = Maps.newHashMap(); - inputParams.put("rowkey", 1); - - when(redisSideTableInfo.getTableName()).thenReturn("sideTable"); - when(redisSideTableInfo.getPrimaryKeys()).thenReturn(primaryKeys); - - Assert.assertEquals("sideTable_1", redisAsyncReqRow.buildCacheKey(inputParams)); - } - - @Test - public void testClose() throws Exception { - suppress(BaseAsyncReqRow.class.getMethod("close")); - redisAsyncReqRow.close(); - } -} diff --git a/redis5/redis5-side/redis-async-side/src/test/java/com/dtstack/flink/sql/side/redis/RedisAsyncSideInfoTest.java b/redis5/redis5-side/redis-async-side/src/test/java/com/dtstack/flink/sql/side/redis/RedisAsyncSideInfoTest.java deleted file mode 100644 index fef3d347f..000000000 --- a/redis5/redis5-side/redis-async-side/src/test/java/com/dtstack/flink/sql/side/redis/RedisAsyncSideInfoTest.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.redis; - -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.BaseSideInfo; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.redis.table.RedisSideTableInfo; -import com.dtstack.flink.sql.util.ParseUtils; -import org.apache.calcite.sql.SqlNode; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -import java.util.ArrayList; -import java.util.List; - -import static org.powermock.api.support.membermodification.MemberMatcher.constructor; -import static org.powermock.api.support.membermodification.MemberMatcher.method; -import static org.powermock.api.support.membermodification.MemberModifier.suppress; - -/** - * @author: chuixue - * @create: 2020-07-22 17:13 - * @description: - **/ -@RunWith(PowerMockRunner.class) -@PrepareForTest({ - ParseUtils.class - , RedisAsyncSideInfo.class -}) -public class RedisAsyncSideInfoTest { - private RowTypeInfo rowTypeInfo; - private JoinInfo joinInfo; - private List outFieldInfoList = new ArrayList<>(); - private AbstractSideTableInfo sideTableInfo; - private RedisAsyncSideInfo redisAsyncSideInfo; - - @Before - public void setUp() { - rowTypeInfo = PowerMockito.mock(RowTypeInfo.class); - joinInfo = PowerMockito.mock(JoinInfo.class); - sideTableInfo = PowerMockito.mock(RedisSideTableInfo.class); - suppress(constructor(BaseSideInfo.class)); - redisAsyncSideInfo = new RedisAsyncSideInfo(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); - } - - @Test - public void testBuildEqualInfo() { - SqlNode conditionNode = PowerMockito.mock(SqlNode.class); - PowerMockito.when(joinInfo.getSideTableName()).thenReturn("dd"); - PowerMockito.when(joinInfo.getCondition()).thenReturn(conditionNode); - suppress(method(ParseUtils.class, "parseAnd", SqlNode.class, List.class)); - redisAsyncSideInfo.buildEqualInfo(joinInfo, sideTableInfo); - } -} diff --git a/redis5/redis5-side/redis-side-core/pom.xml b/redis5/redis5-side/redis-side-core/pom.xml index e2b1b88be..7fb45a291 100644 --- a/redis5/redis5-side/redis-side-core/pom.xml +++ b/redis5/redis5-side/redis-side-core/pom.xml @@ -12,7 +12,14 @@ sql.side.redis.core - + + + com.dtstack.flink + sql.core + 1.0-SNAPSHOT + provided + + jar diff --git a/redis5/redis5-side/redis-side-core/src/main/java/com/dtstack/flink/sql/side/redis/enums/RedisType.java b/redis5/redis5-side/redis-side-core/src/main/java/com/dtstack/flink/sql/side/redis/enums/RedisType.java deleted file mode 100644 index 048c32b08..000000000 --- a/redis5/redis5-side/redis-side-core/src/main/java/com/dtstack/flink/sql/side/redis/enums/RedisType.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.dtstack.flink.sql.side.redis.enums; - -public enum RedisType { - /** - * 单机 - */ - STANDALONE(1), - /** - * 哨兵 - */ - SENTINEL(2), - /** - * 集群 - */ - CLUSTER(3); - int type; - RedisType(int type){ - this.type = type; - } - - public int getType(){ - return type; - } - - public static RedisType parse(int redisType){ - for(RedisType type : RedisType.values()){ - if(type.getType() == redisType){ - return type; - } - } - throw new RuntimeException("unsupport redis type["+ redisType + "]"); - } -} diff --git a/redis5/redis5-side/redis-side-core/src/main/java/com/dtstack/flink/sql/side/redis/table/RedisSideParser.java b/redis5/redis5-side/redis-side-core/src/main/java/com/dtstack/flink/sql/side/redis/table/RedisSideParser.java index 26d2342db..f8a83b868 100644 --- a/redis5/redis5-side/redis-side-core/src/main/java/com/dtstack/flink/sql/side/redis/table/RedisSideParser.java +++ b/redis5/redis5-side/redis-side-core/src/main/java/com/dtstack/flink/sql/side/redis/table/RedisSideParser.java @@ -18,19 +18,16 @@ package com.dtstack.flink.sql.side.redis.table; -import com.dtstack.flink.sql.table.AbstractSideTableParser; -import com.dtstack.flink.sql.table.AbstractTableInfo; +import com.dtstack.flink.sql.table.AbsSideTableParser; +import com.dtstack.flink.sql.table.TableInfo; import com.dtstack.flink.sql.util.MathUtil; import java.util.Map; -/** - * @author yanxi - */ -public class RedisSideParser extends AbstractSideTableParser { +public class RedisSideParser extends AbsSideTableParser { @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { + public TableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { RedisSideTableInfo redisSideTableInfo = new RedisSideTableInfo(); redisSideTableInfo.setName(tableName); @@ -51,11 +48,6 @@ public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map(.*)):(?\\d+)*"); + private SideInfo sideInfo; - private BaseSideInfo sideInfo; - - private RedisSideTableInfo sideTableInfo; - - public RedisSideReqRow(BaseSideInfo sideInfo, RedisSideTableInfo sideTableInfo) { + public RedisSideReqRow(SideInfo sideInfo){ this.sideInfo = sideInfo; - this.sideTableInfo = sideTableInfo; } @Override - public BaseRow fillData(BaseRow input, Object sideInput) { - GenericRow genericRow = (GenericRow) input; + public Row fillData(Row input, Object sideInput) { Map sideInputMap = (Map) sideInput; - GenericRow row = new GenericRow(sideInfo.getOutFieldInfoList().size()); - row.setHeader(input.getHeader()); + Row row = new Row(sideInfo.getOutFieldInfoList().size()); for(Map.Entry entry : sideInfo.getInFieldIndex().entrySet()){ - Object obj = genericRow.getField(entry.getValue()); + Object obj = input.getField(entry.getValue()); boolean isTimeIndicatorTypeInfo = TimeIndicatorTypeInfo.class.isAssignableFrom(sideInfo.getRowTypeInfo().getTypeAt(entry.getValue()).getClass()); - if(obj instanceof LocalDateTime && isTimeIndicatorTypeInfo){ - obj = Timestamp.valueOf((LocalDateTime)obj); + if(obj instanceof Timestamp && isTimeIndicatorTypeInfo){ + obj = ((Timestamp)obj).getTime(); } row.setField(entry.getKey(), obj); } @@ -84,20 +72,7 @@ public BaseRow fillData(BaseRow input, Object sideInput) { return row; } - public String buildCacheKey(Map refData) { - TableUtils.addConstant(refData, sideTableInfo); - StringBuilder keyBuilder = new StringBuilder(sideTableInfo.getTableName()); - List primaryKeys = sideTableInfo.getPrimaryKeys(); - for(String primaryKey : primaryKeys){ - if(!refData.containsKey(primaryKey)){ - return null; - } - keyBuilder.append("_").append(refData.get(primaryKey)); - } - return keyBuilder.toString(); - } - - public void setRowField(GenericRow row, Integer index, BaseSideInfo sideInfo, String value) { + public void setRowField(Row row, Integer index, SideInfo sideInfo, String value) { Integer keyIndex = sideInfo.getSideFieldIndex().get(index); String classType = sideInfo.getSideTableInfo().getFieldClassList().get(keyIndex).getName(); switch (classType){ diff --git a/redis5/redis5-side/redis-side-core/src/main/java/com/dtstack/flink/sql/side/redis/table/RedisSideTableInfo.java b/redis5/redis5-side/redis-side-core/src/main/java/com/dtstack/flink/sql/side/redis/table/RedisSideTableInfo.java index 5224134c8..88cfcb8a2 100644 --- a/redis5/redis5-side/redis-side-core/src/main/java/com/dtstack/flink/sql/side/redis/table/RedisSideTableInfo.java +++ b/redis5/redis5-side/redis-side-core/src/main/java/com/dtstack/flink/sql/side/redis/table/RedisSideTableInfo.java @@ -18,12 +18,10 @@ package com.dtstack.flink.sql.side.redis.table; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; +import com.dtstack.flink.sql.side.SideTableInfo; import com.google.common.base.Preconditions; -/** - * @author yanxi - */ -public class RedisSideTableInfo extends AbstractSideTableInfo { + +public class RedisSideTableInfo extends SideTableInfo { private static final long serialVersionUID = -1L; diff --git a/redis5/redis5-side/redis-side-core/src/test/java/com/dtstack/flink/sql/side/redis/enums/RedisTypeTest.java b/redis5/redis5-side/redis-side-core/src/test/java/com/dtstack/flink/sql/side/redis/enums/RedisTypeTest.java deleted file mode 100644 index bba24256e..000000000 --- a/redis5/redis5-side/redis-side-core/src/test/java/com/dtstack/flink/sql/side/redis/enums/RedisTypeTest.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.redis.enums; - -import org.junit.Test; - -/** - * @author: chuixue - * @create: 2020-07-20 14:27 - * @description: - **/ -public class RedisTypeTest { - - @Test - public void testParse() { - for (RedisType value : RedisType.values()) { - RedisType.parse(value.getType()); - } - } -} diff --git a/redis5/redis5-side/redis-side-core/src/test/java/com/dtstack/flink/sql/side/redis/table/RedisSideParserTest.java b/redis5/redis5-side/redis-side-core/src/test/java/com/dtstack/flink/sql/side/redis/table/RedisSideParserTest.java deleted file mode 100644 index 08ed7f0ee..000000000 --- a/redis5/redis5-side/redis-side-core/src/test/java/com/dtstack/flink/sql/side/redis/table/RedisSideParserTest.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.redis.table; - -import com.google.common.collect.Maps; -import org.junit.Test; - -import java.util.Map; - -import static org.junit.Assert.assertEquals; - -/** - * @author: chuixue - * @create: 2020-07-20 11:52 - * @description: - **/ -public class RedisSideParserTest { - - @Test - public void testGetTableInfo() { - Map props = Maps.newHashMap(); - props.put("primaryKeys", "mid"); - props.put("redistype", "1"); - props.put("type", "redis"); - props.put("tablename", "sinkTable"); - props.put("url", "localhost:6379"); - RedisSideParser parser = new RedisSideParser(); - parser.getTableInfo("Mykafka", " mid int , mbb varchar, sid varchar, sbb varchar , PRIMARY KEY (mid)", props); - - assertEquals(parser, parser); - } -} diff --git a/redis5/redis5-side/redis-side-core/src/test/java/com/dtstack/flink/sql/side/redis/table/RedisSideReqRowTest.java b/redis5/redis5-side/redis-side-core/src/test/java/com/dtstack/flink/sql/side/redis/table/RedisSideReqRowTest.java deleted file mode 100644 index bc8a4ce6d..000000000 --- a/redis5/redis5-side/redis-side-core/src/test/java/com/dtstack/flink/sql/side/redis/table/RedisSideReqRowTest.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.redis.table; - -import com.dtstack.flink.sql.side.BaseSideInfo; -import com.dtstack.flink.sql.side.FieldInfo; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.table.dataformat.GenericRow; -import org.apache.flink.types.Row; -import org.junit.Test; -import org.powermock.api.mockito.PowerMockito; - -import java.sql.Date; -import java.sql.Timestamp; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -/** - * @author: chuixue - * @create: 2020-07-20 11:54 - * @description: - **/ -public class RedisSideReqRowTest { - @Test - public void teatFillData() { - BaseSideInfo sideInfo = PowerMockito.mock(BaseSideInfo.class); - RedisSideReqRow redisSideReqRow = new RedisSideReqRow(sideInfo, null); - List outFieldInfoList = Lists.newArrayList(); - FieldInfo fieldInfo = new FieldInfo(); - fieldInfo.setTable("m"); - fieldInfo.setFieldName("id"); - fieldInfo.setTypeInformation(TypeInformation.of(Integer.class)); - outFieldInfoList.add(fieldInfo); - outFieldInfoList.add(fieldInfo); - outFieldInfoList.add(fieldInfo); - outFieldInfoList.add(fieldInfo); - outFieldInfoList.add(fieldInfo); - outFieldInfoList.add(fieldInfo); - outFieldInfoList.add(fieldInfo); - Map inFieldIndex = Maps.newHashMap(); - inFieldIndex.put(0, 0); - inFieldIndex.put(1, 1); - inFieldIndex.put(2, 2); - RowTypeInfo rowTypeInfo = new RowTypeInfo(new TypeInformation[]{TypeInformation.of(Integer.class), TypeInformation.of(String.class), TypeInformation.of(Timestamp.class)}, new String[]{"id", "bb", "PROCTIME"}); - Map sideFieldIndex = Maps.newHashMap(); - sideFieldIndex.put(3, 0); - sideFieldIndex.put(4, 1); - sideFieldIndex.put(5, 2); - sideFieldIndex.put(6, 3); - Map sideFieldNameIndex = Maps.newHashMap(); - sideFieldNameIndex.put(3, "rowkey"); - sideFieldNameIndex.put(4, "channel"); - sideFieldNameIndex.put(5, "f"); - sideFieldNameIndex.put(6, "l"); - - GenericRow row = new GenericRow(3); - row.setField(0, 1); - row.setField(1, "bbbbbb"); - row.setField(2, "2020-07-14 01:27:43.969"); - - Map sideInput = new LinkedHashMap<>(); - sideInput.put("rowkey", "1"); - sideInput.put("channel", new Date(1594661263000L) + ""); - sideInput.put("f", 10.0f + ""); - sideInput.put("l", 10L + ""); - - RedisSideTableInfo redisSideTableInfo = PowerMockito.mock(RedisSideTableInfo.class); - List fieldClassList = Lists.newArrayList(); - fieldClassList.add(Integer.class); - fieldClassList.add(Date.class); - fieldClassList.add(Float.class); - fieldClassList.add(Long.class); - - PowerMockito.when(sideInfo.getOutFieldInfoList()).thenReturn(outFieldInfoList); - PowerMockito.when(sideInfo.getInFieldIndex()).thenReturn(inFieldIndex); - PowerMockito.when(sideInfo.getRowTypeInfo()).thenReturn(rowTypeInfo); - PowerMockito.when(sideInfo.getSideFieldIndex()).thenReturn(sideFieldIndex); - PowerMockito.when(sideInfo.getSideFieldNameIndex()).thenReturn(sideFieldNameIndex); - PowerMockito.when(sideInfo.getSideTableInfo()).thenReturn(redisSideTableInfo); - PowerMockito.when(redisSideTableInfo.getFieldClassList()).thenReturn(fieldClassList); - redisSideReqRow.fillData(row, sideInput); - } -} diff --git a/redis5/redis5-sink/pom.xml b/redis5/redis5-sink/pom.xml index bdc9240e0..be6a445ed 100644 --- a/redis5/redis5-sink/pom.xml +++ b/redis5/redis5-sink/pom.xml @@ -16,6 +16,20 @@ redis-sink http://maven.apache.org + + + com.dtstack.flink + sql.core + 1.0-SNAPSHOT + provided + + + redis.clients + jedis + 2.9.0 + + + @@ -62,14 +76,14 @@ - + - + diff --git a/redis5/redis5-sink/src/main/java/com/dtstack/flink/sql/sink/redis/RedisOutputFormat.java b/redis5/redis5-sink/src/main/java/com/dtstack/flink/sql/sink/redis/RedisOutputFormat.java index 22779156b..bb3963edb 100644 --- a/redis5/redis5-sink/src/main/java/com/dtstack/flink/sql/sink/redis/RedisOutputFormat.java +++ b/redis5/redis5-sink/src/main/java/com/dtstack/flink/sql/sink/redis/RedisOutputFormat.java @@ -18,10 +18,7 @@ package com.dtstack.flink.sql.sink.redis; -import com.dtstack.flink.sql.outputformat.AbstractDtRichOutputFormat; -import com.dtstack.flink.sql.sink.redis.enums.RedisType; -import com.google.common.collect.Maps; -import org.apache.commons.lang3.StringUtils; +import com.dtstack.flink.sql.sink.MetricOutputFormat; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.apache.flink.api.common.typeinfo.TypeInformation; import org.apache.flink.api.java.tuple.Tuple2; @@ -29,42 +26,17 @@ import org.apache.flink.types.Row; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import redis.clients.jedis.HostAndPort; -import redis.clients.jedis.JedisCluster; -import redis.clients.jedis.JedisCommands; -import redis.clients.jedis.JedisPool; -import redis.clients.jedis.JedisSentinelPool; - +import redis.clients.jedis.*; import java.io.Closeable; import java.io.IOException; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * @author yanxi - */ -public class RedisOutputFormat extends AbstractDtRichOutputFormat> { - private static final Logger LOG = LoggerFactory.getLogger(RedisOutputFormat.class); - - private static final Pattern HOST_PORT_PATTERN = Pattern.compile("(?(.*)):(?\\d+)*"); +import java.util.*; - protected String[] fieldNames; - - protected TypeInformation[] fieldTypes; - - protected List primaryKeys; - - protected int timeout = 10000; +public class RedisOutputFormat extends MetricOutputFormat { + private static final Logger LOG = LoggerFactory.getLogger(RedisOutputFormat.class); private String url; - private String database = "0"; + private String database; private String tableName; @@ -80,7 +52,13 @@ public class RedisOutputFormat extends AbstractDtRichOutputFormat[] fieldTypes; + + protected List primaryKeys; + + protected int timeout; private JedisPool pool; @@ -88,13 +66,12 @@ public class RedisOutputFormat extends AbstractDtRichOutputFormat ipPorts = new HashSet<>(Arrays.asList(nodes)); - jedisSentinelPool = new JedisSentinelPool( - masterName, - ipPorts, - poolConfig, - timeout, - password, - Integer.parseInt(database)); + poolConfig = setPoolConfig(maxTotal, maxIdle, minIdle); + String[] nodes = url.split(","); + String[] firstIpPort = nodes[0].split(":"); + String firstIp = firstIpPort[0]; + String firstPort = firstIpPort[1]; + Set addresses = new HashSet<>(); + Set ipPorts = new HashSet<>(); + for (String ipPort : nodes) { + ipPorts.add(ipPort); + String[] ipPortPair = ipPort.split(":"); + addresses.add(new HostAndPort(ipPortPair[0].trim(), Integer.valueOf(ipPortPair[1].trim()))); + } + if (timeout == 0){ + timeout = 10000; + } + if (database == null) + { + database = "0"; + } - jedis = jedisSentinelPool.getResource(); + switch (redisType){ + //单机 + case 1: + pool = new JedisPool(poolConfig, firstIp, Integer.parseInt(firstPort), timeout, password, Integer.parseInt(database)); + jedis = pool.getResource(); break; - case CLUSTER: - Set addresses = new HashSet<>(); - // 对ipv6 支持 - for (String node : nodes) { - Matcher matcher = HOST_PORT_PATTERN.matcher(node); - if (matcher.find()) { - String host = matcher.group("host").trim(); - String portStr = matcher.group("port").trim(); - if (StringUtils.isNotBlank(host) && StringUtils.isNotBlank(portStr)) { - // 转化为int格式的端口 - int port = Integer.parseInt(portStr); - addresses.add(new HostAndPort(host, port)); - } - } - } - jedis = new JedisCluster( - addresses, - timeout, - timeout, - 10, - password, - poolConfig); + //哨兵 + case 2: + jedisSentinelPool = new JedisSentinelPool(masterName, ipPorts, poolConfig, timeout, password, Integer.parseInt(database)); + jedis = jedisSentinelPool.getResource(); break; - default: - throw new IllegalArgumentException("unsupported redis type[ " + redisType + "]"); + //集群 + case 3: + jedis = new JedisCluster(addresses, timeout, timeout,10, password, poolConfig); } } @Override - public void writeRecord(Tuple2 record) throws IOException { - Boolean retract = record.getField(0); + public void writeRecord(Tuple2 record) throws IOException { + Tuple2 tupleTrans = record; + Boolean retract = tupleTrans.getField(0); if (!retract) { return; } - Row row = record.getField(1); + Row row = tupleTrans.getField(1); if (row.getArity() != fieldNames.length) { return; } - Map refData = Maps.newHashMap(); - for (int i = 0; i < fieldNames.length; i++) { - refData.put(fieldNames[i], row.getField(i)); + + HashMap map = new HashMap<>(); + + for (String primaryKey : primaryKeys){ + for (int i=0; i kvList = new LinkedList<>(); + for (String primaryKey : primaryKeys){ + StringBuilder primaryKV = new StringBuilder(); + int index = map.get(primaryKey).intValue(); + primaryKV.append(primaryKey).append(":").append(row.getField(index)); + kvList.add(primaryKV.toString()); } - outRecords.inc(); - } + String perKey = String.join(":", kvList); - /** - * 1. build key from map. - * 2. save key and value. - * 3. set expired time for key when keyExpiredTime has been set. - * @param refData - */ - private synchronized void save(Map refData) { - String key = buildCacheKey(refData); - try { - refData.forEach((field, value) -> jedis.hset(key, field, String.valueOf(value))); - } finally { - if (keyExpiredTime != 0) { - jedis.expire(key, keyExpiredTime); + + for (int i = 0; i < fieldNames.length; i++) { + StringBuilder key = new StringBuilder(); + key.append(tableName).append(":").append(perKey).append(":").append(fieldNames[i]); + + String value = "null"; + Object field = row.getField(i); + if (field != null) { + value = field.toString(); } + jedis.set(key.toString(), value); } + + if (outRecords.getCount()%rowLenth == 0){ + LOG.info(record.toString()); + } + outRecords.inc(); } @Override @@ -235,108 +194,96 @@ public void close() throws IOException { if (pool != null) { pool.close(); } - if (jedis != null) { - if (jedis instanceof Closeable) { + if (jedis != null){ + if (jedis instanceof Closeable){ ((Closeable) jedis).close(); } } } - public String buildCacheKey(Map refData) { - StringBuilder keyBuilder = new StringBuilder(tableName); - for (String primaryKey : primaryKeys) { - if (!refData.containsKey(primaryKey)) { - return null; - } - keyBuilder.append("_").append(refData.get(primaryKey)); - } - return keyBuilder.toString(); + public static RedisOutputFormatBuilder buildRedisOutputFormat(){ + return new RedisOutputFormatBuilder(); } - public static class RedisOutputFormatBuilder { + public static class RedisOutputFormatBuilder{ private final RedisOutputFormat redisOutputFormat; - protected RedisOutputFormatBuilder() { + protected RedisOutputFormatBuilder(){ this.redisOutputFormat = new RedisOutputFormat(); } - public RedisOutputFormatBuilder setUrl(String url) { + public RedisOutputFormatBuilder setUrl(String url){ redisOutputFormat.url = url; return this; } - public RedisOutputFormatBuilder setDatabase(String database) { + public RedisOutputFormatBuilder setDatabase(String database){ redisOutputFormat.database = database; return this; } - public RedisOutputFormatBuilder setTableName(String tableName) { + public RedisOutputFormatBuilder setTableName(String tableName){ redisOutputFormat.tableName = tableName; return this; } - public RedisOutputFormatBuilder setPassword(String password) { + public RedisOutputFormatBuilder setPassword(String password){ redisOutputFormat.password = password; return this; } - public RedisOutputFormatBuilder setFieldNames(String[] fieldNames) { + public RedisOutputFormatBuilder setFieldNames(String[] fieldNames){ redisOutputFormat.fieldNames = fieldNames; return this; } - public RedisOutputFormatBuilder setFieldTypes(TypeInformation[] fieldTypes) { + public RedisOutputFormatBuilder setFieldTypes(TypeInformation[] fieldTypes){ redisOutputFormat.fieldTypes = fieldTypes; return this; } - public RedisOutputFormatBuilder setPrimaryKeys(List primaryKeys) { + public RedisOutputFormatBuilder setPrimaryKeys(List primaryKeys){ redisOutputFormat.primaryKeys = primaryKeys; return this; } - public RedisOutputFormatBuilder setTimeout(int timeout) { + public RedisOutputFormatBuilder setTimeout(int timeout){ redisOutputFormat.timeout = timeout; return this; } - public RedisOutputFormatBuilder setRedisType(int redisType) { + public RedisOutputFormatBuilder setRedisType(int redisType){ redisOutputFormat.redisType = redisType; return this; } - public RedisOutputFormatBuilder setMaxTotal(String maxTotal) { + public RedisOutputFormatBuilder setMaxTotal(String maxTotal){ redisOutputFormat.maxTotal = maxTotal; return this; } - public RedisOutputFormatBuilder setMaxIdle(String maxIdle) { + public RedisOutputFormatBuilder setMaxIdle(String maxIdle){ redisOutputFormat.maxIdle = maxIdle; return this; } - public RedisOutputFormatBuilder setMinIdle(String minIdle) { + public RedisOutputFormatBuilder setMinIdle(String minIdle){ redisOutputFormat.minIdle = minIdle; return this; } - public RedisOutputFormatBuilder setMasterName(String masterName) { + public RedisOutputFormatBuilder setMasterName(String masterName){ redisOutputFormat.masterName = masterName; return this; } - public RedisOutputFormatBuilder setKeyExpiredTime(int keyExpiredTime){ - redisOutputFormat.keyExpiredTime = keyExpiredTime; - return this; - } - - public RedisOutputFormat finish() { - if (redisOutputFormat.url == null) { + public RedisOutputFormat finish(){ + if (redisOutputFormat.url == null){ throw new IllegalArgumentException("No URL supplied."); } - if (redisOutputFormat.tableName == null) { + if (redisOutputFormat.tableName == null){ throw new IllegalArgumentException("No tablename supplied."); } diff --git a/redis5/redis5-sink/src/main/java/com/dtstack/flink/sql/sink/redis/RedisSink.java b/redis5/redis5-sink/src/main/java/com/dtstack/flink/sql/sink/redis/RedisSink.java index 24caab9e1..d2e28c01f 100644 --- a/redis5/redis5-sink/src/main/java/com/dtstack/flink/sql/sink/redis/RedisSink.java +++ b/redis5/redis5-sink/src/main/java/com/dtstack/flink/sql/sink/redis/RedisSink.java @@ -20,13 +20,12 @@ import com.dtstack.flink.sql.sink.IStreamSinkGener; import com.dtstack.flink.sql.sink.redis.table.RedisTableInfo; -import com.dtstack.flink.sql.table.AbstractTargetTableInfo; +import com.dtstack.flink.sql.table.TargetTableInfo; import org.apache.flink.api.common.typeinfo.TypeInformation; import org.apache.flink.api.java.tuple.Tuple2; import org.apache.flink.api.java.typeutils.RowTypeInfo; import org.apache.flink.api.java.typeutils.TupleTypeInfo; import org.apache.flink.streaming.api.datastream.DataStream; -import org.apache.flink.streaming.api.datastream.DataStreamSink; import org.apache.flink.streaming.api.functions.sink.OutputFormatSinkFunction; import org.apache.flink.streaming.api.functions.sink.RichSinkFunction; import org.apache.flink.table.sinks.RetractStreamTableSink; @@ -34,11 +33,7 @@ import org.apache.flink.types.Row; import java.util.List; -import java.util.Objects; -/** - * @author yanxi - */ public class RedisSink implements RetractStreamTableSink, IStreamSinkGener { protected String[] fieldNames; @@ -67,18 +62,12 @@ public class RedisSink implements RetractStreamTableSink, IStreamSinkGener< protected String masterName; - protected Integer parallelism = 1; - - protected String registerTableName; - - protected int keyExpiredTime; - - public RedisSink() { + public RedisSink(){ } @Override - public RedisSink genStreamSink(AbstractTargetTableInfo targetTableInfo) { + public RedisSink genStreamSink(TargetTableInfo targetTableInfo) { RedisTableInfo redisTableInfo = (RedisTableInfo) targetTableInfo; this.url = redisTableInfo.getUrl(); this.database = redisTableInfo.getDatabase(); @@ -91,10 +80,6 @@ public RedisSink genStreamSink(AbstractTargetTableInfo targetTableInfo) { this.minIdle = redisTableInfo.getMinIdle(); this.masterName = redisTableInfo.getMasterName(); this.timeout = redisTableInfo.getTimeout(); - this.parallelism = Objects.isNull(redisTableInfo.getParallelism()) ? - parallelism : redisTableInfo.getParallelism(); - this.registerTableName = redisTableInfo.getName(); - this.keyExpiredTime = redisTableInfo.getKeyExpiredTime(); return this; } @@ -105,13 +90,8 @@ public TypeInformation getRecordType() { @Override public void emitDataStream(DataStream> dataStream) { - consumeDataStream(dataStream); - } - - @Override - public DataStreamSink> consumeDataStream(DataStream> dataStream) { RedisOutputFormat.RedisOutputFormatBuilder builder = RedisOutputFormat.buildRedisOutputFormat(); - RedisOutputFormat redisOutputFormat = builder.setUrl(this.url) + builder.setUrl(this.url) .setDatabase(this.database) .setTableName(this.tableName) .setPassword(this.password) @@ -123,14 +103,10 @@ public DataStreamSink> consumeDataStream(DataStream props) { + public TableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { RedisTableInfo redisTableInfo = new RedisTableInfo(); redisTableInfo.setName(tableName); parseFieldsInfo(fieldsInfo, redisTableInfo); @@ -49,11 +46,15 @@ public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map primaryKeysList = null; + if (!StringUtils.isEmpty(primaryKeysStr)) { + String[] primaryKeysArray = primaryKeysStr.split(","); + primaryKeysList = new ArrayList(Arrays.asList(primaryKeysArray)); + } else { + primaryKeysList = new ArrayList<>(); } - - redisTableInfo.setParallelism(MathUtil.getIntegerVal(props.get(RedisTableInfo.PARALLELISM_KEY.toLowerCase()))); + redisTableInfo.setPrimaryKeys(primaryKeysList); return redisTableInfo; } diff --git a/redis5/redis5-sink/src/main/java/com/dtstack/flink/sql/sink/redis/table/RedisTableInfo.java b/redis5/redis5-sink/src/main/java/com/dtstack/flink/sql/sink/redis/table/RedisTableInfo.java index 6d6e4f390..82def4115 100644 --- a/redis5/redis5-sink/src/main/java/com/dtstack/flink/sql/sink/redis/table/RedisTableInfo.java +++ b/redis5/redis5-sink/src/main/java/com/dtstack/flink/sql/sink/redis/table/RedisTableInfo.java @@ -18,12 +18,10 @@ package com.dtstack.flink.sql.sink.redis.table; -import com.dtstack.flink.sql.table.AbstractTargetTableInfo; +import com.dtstack.flink.sql.table.TargetTableInfo; import com.google.common.base.Preconditions; -/** - * @author yanxi - */ -public class RedisTableInfo extends AbstractTargetTableInfo { + +public class RedisTableInfo extends TargetTableInfo { private static final String CURR_TYPE = "redis"; @@ -47,8 +45,6 @@ public class RedisTableInfo extends AbstractTargetTableInfo { public static final String MASTER_NAME = "masterName"; - public static final String KEY_EXPIRED_TIME = "keyExpiredTime"; - public RedisTableInfo(){ setType(CURR_TYPE); } @@ -73,8 +69,6 @@ public RedisTableInfo(){ private String masterName; - private int keyExpiredTime; - public String getUrl() { return url; } @@ -155,14 +149,6 @@ public void setMasterName(String masterName) { this.masterName = masterName; } - public int getKeyExpiredTime() { - return keyExpiredTime; - } - - public void setKeyExpiredTime(int keyExpiredTime) { - this.keyExpiredTime = keyExpiredTime; - } - @Override public boolean check() { Preconditions.checkNotNull(url, "redis field of URL is required"); diff --git a/redis5/redis5-sink/src/test/java/com/dtstack/flink/sql/sink/redis/RedisOutputFormatTest.java b/redis5/redis5-sink/src/test/java/com/dtstack/flink/sql/sink/redis/RedisOutputFormatTest.java deleted file mode 100644 index ed6ec382b..000000000 --- a/redis5/redis5-sink/src/test/java/com/dtstack/flink/sql/sink/redis/RedisOutputFormatTest.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.redis; - -import com.dtstack.flink.sql.outputformat.AbstractDtRichOutputFormat; -import com.google.common.collect.Lists; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.metrics.Counter; -import org.apache.flink.types.Row; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.InjectMocks; -import org.mockito.MockitoAnnotations; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.api.support.membermodification.MemberModifier; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import org.powermock.reflect.Whitebox; -import redis.clients.jedis.Jedis; -import redis.clients.jedis.JedisPool; - -import java.io.IOException; -import java.util.List; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.powermock.api.support.membermodification.MemberModifier.suppress; - -/** - * @author: chuixue - * @create: 2020-07-20 10:33 - * @description: - **/ -@RunWith(PowerMockRunner.class) -@PrepareForTest({RedisOutputFormat.class}) -public class RedisOutputFormatTest { - @InjectMocks - private RedisOutputFormat redisOutputFormat; - private Jedis jedis; - private Counter outRecords; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - jedis = mock(Jedis.class); - outRecords = mock(Counter.class); - Whitebox.setInternalState(redisOutputFormat, "outRecords", outRecords); - MemberModifier.field(RedisOutputFormat.class, "maxTotal").set(redisOutputFormat, "10000"); - MemberModifier.field(RedisOutputFormat.class, "maxIdle").set(redisOutputFormat, "1000"); - MemberModifier.field(RedisOutputFormat.class, "minIdle").set(redisOutputFormat, "10"); - MemberModifier.field(RedisOutputFormat.class, "url").set(redisOutputFormat, "localhost:6379"); - MemberModifier.field(RedisOutputFormat.class, "redisType").set(redisOutputFormat, 1); - MemberModifier.field(RedisOutputFormat.class, "jedis").set(redisOutputFormat, jedis); - - List pys = Lists.newArrayList(); - pys.add("mid"); - MemberModifier.field(RedisOutputFormat.class, "fieldNames").set(redisOutputFormat, new String[]{"mid", "mbb", "sid", "sbb"}); - MemberModifier.field(RedisOutputFormat.class, "primaryKeys").set(redisOutputFormat, pys); - MemberModifier.field(RedisOutputFormat.class, "tableName").set(redisOutputFormat, "sinkTable"); - MemberModifier.field(RedisOutputFormat.class, "database").set(redisOutputFormat, "0"); - } - - @Test - public void testOpen() throws Exception { - JedisPool jedisPool = mock(JedisPool.class); - - PowerMockito.whenNew(JedisPool.class).withAnyArguments().thenReturn(jedisPool); - when(jedisPool.getResource()).thenReturn(jedis); - suppress(AbstractDtRichOutputFormat.class.getMethod("initMetric")); - redisOutputFormat.open(1, 1); - } - - @Test - public void testWriteRecord() throws IOException { - Row row = new Row(4); - row.setField(0, "1"); - row.setField(1, "bbbbbb"); - row.setField(2, null); - row.setField(3, null); - Tuple2 records = new Tuple2(true, row); - - redisOutputFormat.writeRecord(records); - } -} diff --git a/redis5/redis5-sink/src/test/java/com/dtstack/flink/sql/sink/redis/RedisSinkTest.java b/redis5/redis5-sink/src/test/java/com/dtstack/flink/sql/sink/redis/RedisSinkTest.java deleted file mode 100644 index df2b5ba1e..000000000 --- a/redis5/redis5-sink/src/test/java/com/dtstack/flink/sql/sink/redis/RedisSinkTest.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.redis; - -import com.dtstack.flink.sql.sink.redis.table.RedisTableInfo; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.streaming.api.datastream.DataStream; -import org.apache.flink.streaming.api.datastream.DataStreamSink; -import org.apache.flink.types.Row; -import org.junit.Before; -import org.junit.Test; -import org.powermock.api.mockito.PowerMockito; - -import java.util.ArrayList; -import java.util.List; - -import static org.junit.Assert.assertEquals; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.Mockito.when; - -/** - * @author: chuixue - * @create: 2020-07-20 10:01 - * @description: - **/ -public class RedisSinkTest { - private RedisSink redisSink; - private RedisTableInfo targetTableInfo; - - @Before - public void setUp() { - targetTableInfo = new RedisTableInfo(); - List pks = new ArrayList<>(); - pks.add("mid"); - targetTableInfo.setUrl("localhost:6379"); - targetTableInfo.setDatabase("db0"); - targetTableInfo.setPassword("root"); - targetTableInfo.setTablename("sideTable"); - targetTableInfo.setPrimaryKeys(pks); - targetTableInfo.setRedisType("1"); - targetTableInfo.setMaxTotal("1000"); - targetTableInfo.setMaxIdle("10"); - targetTableInfo.setMinIdle("1"); - targetTableInfo.setMasterName("redis"); - targetTableInfo.setTimeout(10000); - redisSink = new RedisSink(); - redisSink.genStreamSink(targetTableInfo); - assertEquals(redisSink, redisSink); - } - - @Test - public void testEmitDataStream() { - DataStream> dataStream = PowerMockito.mock(DataStream.class); - - DataStreamSink dataStreamSink = PowerMockito.mock(DataStreamSink.class); - when(dataStream.addSink(any())).thenReturn(dataStreamSink); - when(dataStreamSink.setParallelism(anyInt())).thenReturn(dataStreamSink); - - redisSink.emitDataStream(dataStream); - } -} diff --git a/redis5/redis5-sink/src/test/java/com/dtstack/flink/sql/sink/redis/table/RedisSinkParserTest.java b/redis5/redis5-sink/src/test/java/com/dtstack/flink/sql/sink/redis/table/RedisSinkParserTest.java deleted file mode 100644 index 7fbb71b51..000000000 --- a/redis5/redis5-sink/src/test/java/com/dtstack/flink/sql/sink/redis/table/RedisSinkParserTest.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.redis.table; - -import com.google.common.collect.Maps; -import org.junit.Test; - -import java.util.Map; - -import static org.junit.Assert.*; - -/** - * @author: chuixue - * @create: 2020-07-20 10:24 - * @description: - **/ -public class RedisSinkParserTest { - - @Test - public void testGetTableInfo() { - Map props = Maps.newHashMap(); - props.put("primaryKeys", "mid"); - props.put("redistype", "1"); - props.put("type", "redis"); - props.put("tablename", "sinkTable"); - props.put("url", "localhost:6379"); - RedisSinkParser parser = new RedisSinkParser(); - parser.getTableInfo("Mykafka", " mid int , mbb varchar, sid varchar, sbb varchar ", props); - - assertEquals(parser, parser); - } -} diff --git a/serversocket/pom.xml b/serversocket/pom.xml index 93ae422e9..dd76df619 100644 --- a/serversocket/pom.xml +++ b/serversocket/pom.xml @@ -18,10 +18,17 @@ pom + 3.8.1 1.0-SNAPSHOT + + junit + junit + ${junit.version} + test + com.dtstack.flink diff --git a/serversocket/serversocket-source/pom.xml b/serversocket/serversocket-source/pom.xml index 7e22b5078..9a1f274c0 100644 --- a/serversocket/serversocket-source/pom.xml +++ b/serversocket/serversocket-source/pom.xml @@ -63,14 +63,14 @@ - + - + diff --git a/serversocket/serversocket-source/src/main/java/com/dtstack/flink/sql/source/serversocket/CustomerSocketTextStreamFunction.java b/serversocket/serversocket-source/src/main/java/com/dtstack/flink/sql/source/serversocket/CustomerSocketTextStreamFunction.java index ca2450c40..b76e94159 100644 --- a/serversocket/serversocket-source/src/main/java/com/dtstack/flink/sql/source/serversocket/CustomerSocketTextStreamFunction.java +++ b/serversocket/serversocket-source/src/main/java/com/dtstack/flink/sql/source/serversocket/CustomerSocketTextStreamFunction.java @@ -17,12 +17,11 @@ */ package com.dtstack.flink.sql.source.serversocket; -import com.dtstack.flink.sql.dirtyManager.manager.DirtyDataManager; -import com.dtstack.flink.sql.format.DeserializationMetricWrapper; -import com.dtstack.flink.sql.format.dtnest.DtNestRowDeserializationSchema; import com.dtstack.flink.sql.source.serversocket.table.ServersocketSourceTableInfo; -import com.dtstack.flink.sql.table.AbstractTableInfo; import org.apache.flink.api.common.typeinfo.TypeInformation; +import org.apache.flink.api.java.typeutils.RowTypeInfo; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.flink.streaming.api.functions.source.SourceFunction; import org.apache.flink.types.Row; import org.apache.flink.util.IOUtils; @@ -30,11 +29,11 @@ import org.slf4j.LoggerFactory; import java.io.BufferedReader; +import java.io.IOException; import java.io.InputStreamReader; import java.net.InetSocketAddress; import java.net.Socket; -import java.util.List; -import java.util.Map; +import java.util.Iterator; /** @@ -47,10 +46,6 @@ public class CustomerSocketTextStreamFunction implements SourceFunction { private static final Logger LOG = LoggerFactory.getLogger(CustomerSocketTextStreamFunction.class); - protected DtNestRowDeserializationSchema deserializationSchema; - - protected DeserializationMetricWrapper deserializationMetricWrapper; - /** * Default delay between successive connection attempts. */ @@ -59,23 +54,39 @@ public class CustomerSocketTextStreamFunction implements SourceFunction { /** * Default connection timeout when connecting to the server socket (infinite). */ - private static final int CONNECTION_TIMEOUT_TIME = 30000; + private static final int CONNECTION_TIMEOUT_TIME = 0; + + private final ObjectMapper objectMapper = new ObjectMapper(); + + /** + * Type information describing the result type. + */ + private final TypeInformation typeInfo; + + /** + * Field names to parse. Indices match fieldTypes indices. + */ + private final String[] fieldNames; + + /** + * Types to parse fields as. Indices match fieldNames indices. + */ + private final TypeInformation[] fieldTypes; private volatile boolean isRunning = true; private transient Socket currentSocket; - private String CHARSET_NAME = "UTF-8"; - ServersocketSourceTableInfo tableInfo; + public CustomerSocketTextStreamFunction(ServersocketSourceTableInfo tableInfo, TypeInformation typeInfo) { + this.typeInfo = typeInfo; + this.fieldNames = ((RowTypeInfo) typeInfo).getFieldNames(); + + this.fieldTypes = ((RowTypeInfo) typeInfo).getFieldTypes(); - public CustomerSocketTextStreamFunction(ServersocketSourceTableInfo tableInfo, TypeInformation typeInfo, - Map rowAndFieldMapping, List fieldExtraInfos) { this.tableInfo = tableInfo; - this.deserializationSchema = new DtNestRowDeserializationSchema(typeInfo, rowAndFieldMapping, fieldExtraInfos, CHARSET_NAME); - this.deserializationMetricWrapper = new DeserializationMetricWrapper(typeInfo, deserializationSchema, DirtyDataManager.newInstance(tableInfo.getDirtyProperties())); } @Override @@ -84,37 +95,33 @@ public void run(SourceContext ctx) throws Exception { long attempt = 0; while (isRunning) { - try (Socket socket = new Socket()) { + try { + Socket socket = new Socket(); currentSocket = socket; - LOG.info("Connecting to server socket " + tableInfo.getHostname() + ':' + tableInfo.getPort()); socket.connect(new InetSocketAddress(tableInfo.getHostname(), tableInfo.getPort()), CONNECTION_TIMEOUT_TIME); - try (BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()))) { - char[] cbuf = new char[8192]; - int bytesRead; - while (isRunning && (bytesRead = reader.read(cbuf)) != -1) { - buffer.append(cbuf, 0, bytesRead); - int delimPos; - String delimiter = tableInfo.getDelimiter(); - while (buffer.length() >= delimiter.length() && (delimPos = buffer.indexOf(delimiter)) != -1) { - String record = buffer.substring(0, delimPos); - // truncate trailing carriage return - if ("\n".equals(delimiter) && "\r".endsWith(record)) { - record = record.substring(0, record.length() - 1); - } - try { - Row row = deserializationMetricWrapper.deserialize(record.getBytes()); - ctx.collect(row); - } catch (Exception e) { - LOG.error("parseData error ", e); - } finally { - buffer.delete(0, delimPos + delimiter.length()); - } + BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); + char[] cbuf = new char[8192]; + int bytesRead; + while (isRunning && (bytesRead = reader.read(cbuf)) != -1) { + buffer.append(cbuf, 0, bytesRead); + int delimPos; + String delimiter = tableInfo.getDelimiter(); + while (buffer.length() >= delimiter.length() && (delimPos = buffer.indexOf(delimiter)) != -1) { + String record = buffer.substring(0, delimPos); + // truncate trailing carriage return + if (delimiter.equals("\n") && record.endsWith("\r")) { + record = record.substring(0, record.length() - 1); } + ctx.collect(convertToRow(record)); + buffer.delete(0, delimPos + delimiter.length()); } } + } catch (Exception e) { + LOG.info("Connection server failed, Please check configuration !!!!!!!!!!!!!!!!"); } + // if we dropped out of this loop due to an EOF, sleep and retry if (isRunning) { attempt++; @@ -130,15 +137,27 @@ record = record.substring(0, record.length() - 1); // collect trailing data if (buffer.length() > 0) { - try { - Row row = deserializationMetricWrapper.deserialize(buffer.toString().getBytes()); - ctx.collect(row); - } catch (Exception e) { - LOG.error("parseData error ", e); + ctx.collect(convertToRow(buffer.toString())); + } + } + + public Row convertToRow(String record) throws IOException { + JsonNode root = objectMapper.readTree(record); + Row row = new Row(fieldNames.length); + for (int i = 0; i < fieldNames.length; i++) { + JsonNode node = getIgnoreCase(root, fieldNames[i]); + if (node == null) { + row.setField(i, null); + } else { + // Read the value as specified type + Object value = objectMapper.treeToValue(node, fieldTypes[i].getTypeClass()); + row.setField(i, value); } } + return row; } + @Override public void cancel() { isRunning = false; @@ -151,4 +170,14 @@ public void cancel() { } } + public JsonNode getIgnoreCase(JsonNode jsonNode, String key) { + Iterator iter = jsonNode.fieldNames(); + while (iter.hasNext()) { + String key1 = iter.next(); + if (key1.equalsIgnoreCase(key)) { + return jsonNode.get(key1); + } + } + return null; + } } diff --git a/serversocket/serversocket-source/src/main/java/com/dtstack/flink/sql/source/serversocket/ServersocketSource.java b/serversocket/serversocket-source/src/main/java/com/dtstack/flink/sql/source/serversocket/ServersocketSource.java index b4dda5f3b..3a67d2c98 100644 --- a/serversocket/serversocket-source/src/main/java/com/dtstack/flink/sql/source/serversocket/ServersocketSource.java +++ b/serversocket/serversocket-source/src/main/java/com/dtstack/flink/sql/source/serversocket/ServersocketSource.java @@ -19,14 +19,16 @@ import com.dtstack.flink.sql.source.IStreamSourceGener; import com.dtstack.flink.sql.source.serversocket.table.ServersocketSourceTableInfo; -import com.dtstack.flink.sql.table.AbstractSourceTableInfo; +import com.dtstack.flink.sql.table.SourceTableInfo; import org.apache.commons.lang3.StringUtils; import org.apache.flink.api.common.typeinfo.TypeInformation; import org.apache.flink.api.java.typeutils.RowTypeInfo; import org.apache.flink.streaming.api.datastream.DataStreamSource; import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; +import org.apache.flink.streaming.api.functions.source.SocketTextStreamFunction; import org.apache.flink.table.api.Table; import org.apache.flink.table.api.java.StreamTableEnvironment; +import org.apache.flink.types.Row; /** * Reason: @@ -37,19 +39,21 @@ */ public class ServersocketSource implements IStreamSourceGener

{ @Override - public Table genStreamSource(AbstractSourceTableInfo sourceTableInfo, StreamExecutionEnvironment env, StreamTableEnvironment tableEnv) { + public Table genStreamSource(SourceTableInfo sourceTableInfo, StreamExecutionEnvironment env, StreamTableEnvironment tableEnv) { ServersocketSourceTableInfo serversocketSourceTableInfo = (ServersocketSourceTableInfo) sourceTableInfo; + String tableName = serversocketSourceTableInfo.getName(); TypeInformation[] types = new TypeInformation[serversocketSourceTableInfo.getFields().length]; for (int i = 0; i < serversocketSourceTableInfo.getFieldClasses().length; i++) { types[i] = TypeInformation.of(serversocketSourceTableInfo.getFieldClasses()[i]); } + TypeInformation typeInformation = new RowTypeInfo(types, serversocketSourceTableInfo.getFields()); + String fields = StringUtils.join(serversocketSourceTableInfo.getFields(), ","); - CustomerSocketTextStreamFunction customerSocketTextStreamFunction = new CustomerSocketTextStreamFunction(serversocketSourceTableInfo, typeInformation, - serversocketSourceTableInfo.getPhysicalFields(), serversocketSourceTableInfo.getFieldExtraInfoList()); + CustomerSocketTextStreamFunction customerSocketTextStreamFunction = new CustomerSocketTextStreamFunction(serversocketSourceTableInfo, typeInformation); DataStreamSource serversocketSource = env.addSource(customerSocketTextStreamFunction, tableName, typeInformation); diff --git a/serversocket/serversocket-source/src/main/java/com/dtstack/flink/sql/source/serversocket/table/ServersocketSourceParser.java b/serversocket/serversocket-source/src/main/java/com/dtstack/flink/sql/source/serversocket/table/ServersocketSourceParser.java index f2d861b17..b52e38e59 100644 --- a/serversocket/serversocket-source/src/main/java/com/dtstack/flink/sql/source/serversocket/table/ServersocketSourceParser.java +++ b/serversocket/serversocket-source/src/main/java/com/dtstack/flink/sql/source/serversocket/table/ServersocketSourceParser.java @@ -17,8 +17,8 @@ */ package com.dtstack.flink.sql.source.serversocket.table; -import com.dtstack.flink.sql.table.AbstractSourceParser; -import com.dtstack.flink.sql.table.AbstractTableInfo; +import com.dtstack.flink.sql.table.AbsSourceParser; +import com.dtstack.flink.sql.table.TableInfo; import com.dtstack.flink.sql.util.MathUtil; import java.util.Map; @@ -30,9 +30,9 @@ * * @author maqi */ -public class ServersocketSourceParser extends AbstractSourceParser { +public class ServersocketSourceParser extends AbsSourceParser { @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { + public TableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { ServersocketSourceTableInfo serversocketSourceTableInfo = new ServersocketSourceTableInfo(); serversocketSourceTableInfo.setName(tableName); parseFieldsInfo(fieldsInfo, serversocketSourceTableInfo); diff --git a/serversocket/serversocket-source/src/main/java/com/dtstack/flink/sql/source/serversocket/table/ServersocketSourceTableInfo.java b/serversocket/serversocket-source/src/main/java/com/dtstack/flink/sql/source/serversocket/table/ServersocketSourceTableInfo.java index 3123b477f..796728eb3 100644 --- a/serversocket/serversocket-source/src/main/java/com/dtstack/flink/sql/source/serversocket/table/ServersocketSourceTableInfo.java +++ b/serversocket/serversocket-source/src/main/java/com/dtstack/flink/sql/source/serversocket/table/ServersocketSourceTableInfo.java @@ -17,7 +17,7 @@ */ package com.dtstack.flink.sql.source.serversocket.table; -import com.dtstack.flink.sql.table.AbstractSourceTableInfo; +import com.dtstack.flink.sql.table.SourceTableInfo; import com.google.common.base.Preconditions; /** @@ -27,8 +27,8 @@ * * @author maqi */ -public class ServersocketSourceTableInfo extends AbstractSourceTableInfo { - +public class ServersocketSourceTableInfo extends SourceTableInfo { + //version private static final String CURR_TYPE = "serversocket"; public static final String HOSTNAME_KEY = "host"; diff --git a/serversocket/serversocket-source/src/test/java/com/dtstack/flink/sql/source/serversocket/CustomerSocketTextStreamFunctionTest.java b/serversocket/serversocket-source/src/test/java/com/dtstack/flink/sql/source/serversocket/CustomerSocketTextStreamFunctionTest.java deleted file mode 100644 index d49ea9f18..000000000 --- a/serversocket/serversocket-source/src/test/java/com/dtstack/flink/sql/source/serversocket/CustomerSocketTextStreamFunctionTest.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.source.serversocket; - -import com.dtstack.flink.sql.source.serversocket.table.ServersocketSourceTableInfo; -import com.dtstack.flink.sql.table.AbstractTableInfo; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.streaming.api.functions.source.SourceFunction; -import org.apache.flink.types.Row; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import org.powermock.reflect.Whitebox; - -import java.io.BufferedReader; -import java.io.InputStream; -import java.net.Socket; -import java.net.SocketAddress; -import java.util.List; -import java.util.Map; - -import static org.mockito.Mockito.mock; -import static org.powermock.api.mockito.PowerMockito.when; -import static org.powermock.api.mockito.PowerMockito.whenNew; -import static org.powermock.api.support.membermodification.MemberModifier.suppress; - - -/** - * @author: chuixue - * @create: 2020-08-03 10:14 - * @description: - **/ -//@RunWith(PowerMockRunner.class) -//@PrepareForTest({BufferedReader.class, -// CustomerSocketTextStreamFunction.class}) -public class CustomerSocketTextStreamFunctionTest { - - private ServersocketSourceTableInfo tableInfo = mock(ServersocketSourceTableInfo.class); - private CustomerSocketTextStreamFunction customerSocketTextStreamFunction; - -// @Before - public void setUp() { - TypeInformation typeInfo = new RowTypeInfo(new TypeInformation[]{TypeInformation.of(Integer.class), TypeInformation.of(String.class)}, new String[]{"id", "name"}); - Map rowAndFieldMapping = Maps.newHashMap(); - List fieldExtraInfos = Lists.newArrayList(); - -// customerSocketTextStreamFunction -// = new CustomerSocketTextStreamFunction(tableInfo, typeInfo, rowAndFieldMapping, fieldExtraInfos); - } - -// @Test - public void testRun() throws Exception { - BufferedReader reader = mock(BufferedReader.class); - char[] cbuf = new char[8192]; - Socket socket = mock(Socket.class); - InputStream inputStream = mock(InputStream.class); - - whenNew(Socket.class).withNoArguments().thenReturn(socket); - suppress(Socket.class.getMethod("connect", SocketAddress.class, int.class)); - when(socket.getInputStream()).thenReturn(inputStream); - - whenNew(BufferedReader.class).withAnyArguments().thenReturn(reader); - when(tableInfo.getHostname()).thenReturn("localhost"); - when(tableInfo.getPort()).thenReturn(9090); - when(tableInfo.getDelimiter()).thenReturn("|"); - when(reader.read(cbuf)).thenReturn(-1); - - SourceFunction.SourceContext ctx = mock(SourceFunction.SourceContext.class); - customerSocketTextStreamFunction.run(ctx); - } - -// @Test - public void testCancel() { - Socket currentSocket = mock(Socket.class); - Whitebox.setInternalState(customerSocketTextStreamFunction, "currentSocket", currentSocket); - customerSocketTextStreamFunction.cancel(); - } -} diff --git a/serversocket/serversocket-source/src/test/java/com/dtstack/flink/sql/source/serversocket/ServersocketSourceTest.java b/serversocket/serversocket-source/src/test/java/com/dtstack/flink/sql/source/serversocket/ServersocketSourceTest.java deleted file mode 100644 index 25158d8a2..000000000 --- a/serversocket/serversocket-source/src/test/java/com/dtstack/flink/sql/source/serversocket/ServersocketSourceTest.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.source.serversocket; - -import com.dtstack.flink.sql.source.serversocket.table.ServersocketSourceTableInfo; -import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; -import org.apache.flink.table.api.java.StreamTableEnvironment; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.modules.junit4.PowerMockRunner; - -import static org.mockito.Mockito.mock; -import static org.powermock.api.mockito.PowerMockito.when; - -/** - * @author: chuixue - * @create: 2020-08-03 09:54 - * @description: - **/ -@RunWith(PowerMockRunner.class) -public class ServersocketSourceTest { - - @Test - public void testGenStreamSource() { - ServersocketSourceTableInfo serversocketSourceTableInfo = mock(ServersocketSourceTableInfo.class); - StreamExecutionEnvironment env = mock(StreamExecutionEnvironment.class); - StreamTableEnvironment tableEnv = mock(StreamTableEnvironment.class); - ServersocketSource serversocketSource = new ServersocketSource(); - - when(serversocketSourceTableInfo.getName()).thenReturn("test"); - when(serversocketSourceTableInfo.getFields()).thenReturn(new String[]{"id", "name"}); - when(serversocketSourceTableInfo.getFieldClasses()).thenReturn(new Class[]{Integer.class, String.class}); - -// serversocketSource.genStreamSource(serversocketSourceTableInfo, env, tableEnv); - } -} diff --git a/serversocket/serversocket-source/src/test/java/com/dtstack/flink/sql/source/serversocket/table/ServersocketSourceParserTest.java b/serversocket/serversocket-source/src/test/java/com/dtstack/flink/sql/source/serversocket/table/ServersocketSourceParserTest.java deleted file mode 100644 index fc2500a09..000000000 --- a/serversocket/serversocket-source/src/test/java/com/dtstack/flink/sql/source/serversocket/table/ServersocketSourceParserTest.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.source.serversocket.table; - -import com.google.common.collect.Maps; -import org.junit.Test; - -import java.util.Map; - -/** - * @author: chuixue - * @create: 2020-08-03 09:54 - * @description: - **/ -public class ServersocketSourceParserTest { - - @Test - public void testGetTableInfo() { - ServersocketSourceParser serversocketSourceParser = new ServersocketSourceParser(); - Map props = Maps.newHashMap(); - props.put("host", "localhost"); - props.put("port", "80"); - props.put("delimiter", "|"); - props.put("maxnumretries", 3); - - serversocketSourceParser.getTableInfo("Mykafka", " rowkey int,\n" + - " channel varchar ,\n" + - " name varchar ", props); - - } -} diff --git a/solr/pom.xml b/solr/pom.xml deleted file mode 100644 index 972c6562e..000000000 --- a/solr/pom.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - flink.sql - com.dtstack.flink - 1.0-SNAPSHOT - - 4.0.0 - - sql.solr - pom - - solr-sink - - - - 1.0-SNAPSHOT - - - - - com.dtstack.flink - sql.core - ${sql.core.version} - provided - - - org.apache.solr - solr-solrj - 7.4.0 - - - org.slf4j - slf4j-api - - - - - \ No newline at end of file diff --git a/solr/solr-sink/pom.xml b/solr/solr-sink/pom.xml deleted file mode 100644 index 1566f0b8b..000000000 --- a/solr/solr-sink/pom.xml +++ /dev/null @@ -1,85 +0,0 @@ - - - - sql.solr - com.dtstack.flink - 1.0-SNAPSHOT - ../pom.xml - - 4.0.0 - - solr-sink - - - - commons-codec - commons-codec - 1.15 - - - - - - - org.apache.maven.plugins - maven-shade-plugin - 1.4 - - - package - - shade - - - false - - - - - - - - *:* - - META-INF/*.SF - META-INF/*.DSA - META-INF/*.RSA - - - - - - - - - - maven-antrun-plugin - 1.2 - - - copy-resources - - package - - run - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/solr/solr-sink/src/main/java/com/dtstack/flink/sql/sink/solr/SolrOutputFormat.java b/solr/solr-sink/src/main/java/com/dtstack/flink/sql/sink/solr/SolrOutputFormat.java deleted file mode 100644 index 79c7cfdb6..000000000 --- a/solr/solr-sink/src/main/java/com/dtstack/flink/sql/sink/solr/SolrOutputFormat.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.solr; - -import com.dtstack.flink.sql.factory.DTThreadFactory; -import com.dtstack.flink.sql.outputformat.AbstractDtRichOutputFormat; -import com.dtstack.flink.sql.sink.solr.client.CloudSolrClientProvider; -import com.dtstack.flink.sql.sink.solr.options.KerberosOptions; -import com.dtstack.flink.sql.sink.solr.options.SolrClientOptions; -import com.dtstack.flink.sql.sink.solr.options.SolrWriteOptions; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.configuration.Configuration; -import org.apache.flink.types.Row; -import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.common.SolrInputDocument; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import sun.security.krb5.KrbException; - -import javax.security.auth.login.LoginException; -import java.io.IOException; -import java.security.PrivilegedActionException; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * @author wuren - * @program flinkStreamSQL - * @create 2021/05/17 - */ -public class SolrOutputFormat extends AbstractDtRichOutputFormat> { - - private static final Logger LOG = LoggerFactory.getLogger(SolrOutputFormat.class); - - // private transient SolrClient solrClient; - private final SolrClientOptions solrClientOptions; - private final SolrWriteOptions solrWriteOptions; - private final KerberosOptions kerberosOptions; - private transient AtomicInteger rowCount; - protected String[] fieldNames; - private transient ScheduledExecutorService scheduler; - private transient ScheduledFuture scheduledFuture; - CloudSolrClientProvider provider; - - public SolrOutputFormat( - SolrClientOptions solrClientOptions, - SolrWriteOptions solrWriteOptions, - KerberosOptions kerberosOptions, - String[] fieldNames) { - this.solrClientOptions = solrClientOptions; - this.solrWriteOptions = solrWriteOptions; - this.kerberosOptions = kerberosOptions; - this.fieldNames = fieldNames; - } - - @Override - public void configure(Configuration parameters) {} - - @Override - public void open(int taskNumber, int numTasks) throws IOException { - provider = new CloudSolrClientProvider(solrClientOptions, kerberosOptions); - try { - provider.getClient(); - } catch (KrbException | LoginException e) { - LOG.error("", e); - } - initMetric(); - initIntervalFlush(); - rowCount = new AtomicInteger(0); - } - - @Override - public void writeRecord(Tuple2 record) throws IOException { - Row row = record.getField(1); - SolrInputDocument solrDocument = new SolrInputDocument(); - int columnIndex = 0; - for (String name : fieldNames) { - solrDocument.setField(name, row.getField(columnIndex)); - columnIndex++; - } - try { - if (outRecords.getCount() % ROW_PRINT_FREQUENCY == 0) { - LOG.info("Receive data : {}", row); - } - provider.add(solrDocument); - outRecords.inc(); - } catch (SolrServerException | PrivilegedActionException e) { - LOG.error("", e); - } - if (rowCount.incrementAndGet() >= solrWriteOptions.getBufferFlushMaxRows()) { - flush(); - } - } - - @Override - public void close() throws IOException { - flush(); - try { - provider.close(); - } catch (PrivilegedActionException e) { - LOG.error("", e); - } - } - - private void initIntervalFlush() { - if (solrWriteOptions.getBufferFlushIntervalMillis() != 0 - && solrWriteOptions.getBufferFlushMaxRows() != 1) { - this.scheduler = - new ScheduledThreadPoolExecutor(1, new DTThreadFactory("solr-batch-flusher")); - this.scheduledFuture = - this.scheduler.scheduleWithFixedDelay( - () -> { - flush(); - }, - solrWriteOptions.getBufferFlushIntervalMillis(), - solrWriteOptions.getBufferFlushIntervalMillis(), - TimeUnit.MILLISECONDS); - } - } - - private synchronized void flush() { - try { - provider.commit(); - rowCount.set(0); - } catch (SolrServerException | IOException | PrivilegedActionException e) { - LOG.error("", e); - } - } -} diff --git a/solr/solr-sink/src/main/java/com/dtstack/flink/sql/sink/solr/SolrSink.java b/solr/solr-sink/src/main/java/com/dtstack/flink/sql/sink/solr/SolrSink.java deleted file mode 100644 index b1f849252..000000000 --- a/solr/solr-sink/src/main/java/com/dtstack/flink/sql/sink/solr/SolrSink.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.solr; - -import com.dtstack.flink.sql.sink.IStreamSinkGener; -import com.dtstack.flink.sql.sink.solr.options.KerberosOptions; -import com.dtstack.flink.sql.sink.solr.options.SolrClientOptions; -import com.dtstack.flink.sql.sink.solr.options.SolrWriteOptions; -import com.dtstack.flink.sql.sink.solr.table.SolrTableInfo; -import com.dtstack.flink.sql.table.AbstractTargetTableInfo; -import org.apache.flink.api.common.typeinfo.TypeInformation; -import org.apache.flink.api.java.tuple.Tuple2; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.api.java.typeutils.TupleTypeInfo; -import org.apache.flink.streaming.api.datastream.DataStream; -import org.apache.flink.streaming.api.datastream.DataStreamSink; -import org.apache.flink.streaming.api.functions.sink.OutputFormatSinkFunction; -import org.apache.flink.streaming.api.functions.sink.RichSinkFunction; -import org.apache.flink.table.sinks.RetractStreamTableSink; -import org.apache.flink.table.sinks.TableSink; -import org.apache.flink.types.Row; - -import java.io.Serializable; - -/** - * @author wuren - * @program flinkStreamSQL - * @create 2021/05/17 - */ -public class SolrSink - implements RetractStreamTableSink, Serializable, IStreamSinkGener { - - private SolrClientOptions solrClientOptions; - private SolrWriteOptions solrWriteOptions; - private KerberosOptions kerberosOptions; - - protected String[] fieldNames; - TypeInformation[] fieldTypes; - - @Override - public SolrSink genStreamSink(AbstractTargetTableInfo targetTableInfo) { - SolrTableInfo solrTableInfo = (SolrTableInfo) targetTableInfo; - solrClientOptions = solrTableInfo.getSolrClientOptions(); - solrWriteOptions = solrTableInfo.getSolrWriteOptions(); - kerberosOptions = solrTableInfo.getKerberosOptions(); - return this; - } - - @Override - public void emitDataStream(DataStream> dataStream) { - consumeDataStream(dataStream); - } - - @Override - public DataStreamSink> consumeDataStream( - DataStream> dataStream) { - SolrOutputFormat solrOutputFormat = - new SolrOutputFormat( - solrClientOptions, solrWriteOptions, kerberosOptions, fieldNames); - String tableName = solrClientOptions.getCollection(); - int parallelism = solrWriteOptions.getParallelism(); - RichSinkFunction richSinkFunction = new OutputFormatSinkFunction(solrOutputFormat); - DataStreamSink dataStreamSink = dataStream.addSink(richSinkFunction); - dataStreamSink.name(tableName); - if (parallelism > 0) { - dataStreamSink.setParallelism(parallelism); - } - return dataStreamSink; - } - - @Override - public TableSink> configure( - String[] fieldNames, TypeInformation[] fieldTypes) { - this.fieldNames = fieldNames; - this.fieldTypes = fieldTypes; - return this; - } - - @Override - public TupleTypeInfo> getOutputType() { - return new TupleTypeInfo(org.apache.flink.table.api.Types.BOOLEAN(), getRecordType()); - } - - @Override - public TypeInformation getRecordType() { - return new RowTypeInfo(fieldTypes, fieldNames); - } - - @Override - public String[] getFieldNames() { - return fieldNames; - } - - @Override - public TypeInformation[] getFieldTypes() { - return fieldTypes; - } -} diff --git a/solr/solr-sink/src/main/java/com/dtstack/flink/sql/sink/solr/client/CloudSolrClientProvider.java b/solr/solr-sink/src/main/java/com/dtstack/flink/sql/sink/solr/client/CloudSolrClientProvider.java deleted file mode 100644 index 1e6551809..000000000 --- a/solr/solr-sink/src/main/java/com/dtstack/flink/sql/sink/solr/client/CloudSolrClientProvider.java +++ /dev/null @@ -1,192 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.solr.client; - -import com.dtstack.flink.sql.sink.solr.options.KerberosOptions; -import com.dtstack.flink.sql.sink.solr.options.SolrClientOptions; -import com.dtstack.flink.sql.util.DtFileUtils; -import org.apache.flink.runtime.security.DynamicConfiguration; -import org.apache.flink.runtime.security.KerberosUtils; -import org.apache.hadoop.security.authentication.util.KerberosName; -import org.apache.solr.client.solrj.SolrClient; -import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.impl.CloudSolrClient; -import org.apache.solr.client.solrj.impl.HttpClientUtil; -import org.apache.solr.client.solrj.impl.Krb5HttpClientBuilder; -import org.apache.solr.client.solrj.impl.SolrHttpClientBuilder; -import org.apache.solr.common.SolrInputDocument; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import sun.security.krb5.KrbException; - -import javax.security.auth.Subject; -import javax.security.auth.login.AppConfigurationEntry; -import javax.security.auth.login.LoginContext; -import javax.security.auth.login.LoginException; -import java.io.IOException; -import java.io.Serializable; -import java.lang.invoke.MethodHandles; -import java.security.PrivilegedAction; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; -import java.util.Optional; - -import static com.dtstack.flink.sql.sink.solr.client.FlinkxKrb5HttpClientBuilder.SOLR_KERBEROS_JAAS_APPNAME; - -/** - * 目前只实现CloudSolrClient一种,以后有其他需求可以实现其他Provider。 例如HttpSolrClient,ConcurrentUpdateSolrClient。 - * Inspired by flink connector jdbc. - * - * @author wuren - * @program flinkStreamSQL - * @create 2021/05/18 - */ -public class CloudSolrClientProvider implements Serializable { - - private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - - private static final String JAVA_SECURITY_KRB5_CONF = "java.security.krb5.conf"; - - private static final String JAAS_APP_NAME = "SolrJClient"; - private final SolrClientOptions solrClientOptions; - private final KerberosOptions kerberosOptions; - private CloudSolrClient cloudSolrClient; - private Subject subject; - - public CloudSolrClientProvider( - SolrClientOptions solrClientOptions, KerberosOptions kerberosOptions) { - this.solrClientOptions = solrClientOptions; - this.kerberosOptions = kerberosOptions; - } - - public SolrClient getClient() throws KrbException, LoginException { - if (kerberosOptions.isEnableKrb()) { - String principal = kerberosOptions.getPrincipal(); - String krb5conf = kerberosOptions.getKrb5conf(); - String keytab = kerberosOptions.getKeytab(); - - System.setProperty(SOLR_KERBEROS_JAAS_APPNAME, JAAS_APP_NAME); - setKrb5Conf(krb5conf); - subject = genSubject(principal, keytab); - setKrb5HttpClient(principal, keytab); - - LOG.info("Kerberos login principal: {}, keytab: {}", principal, keytab); - Subject.doAs( - subject, - (PrivilegedAction) - () -> { - connect(); - return null; - }); - } else { - connect(); - } - return cloudSolrClient; - } - - private void connect() { - cloudSolrClient = - new CloudSolrClient.Builder( - solrClientOptions.getZkHosts(), - Optional.of(solrClientOptions.getZkChroot())) - .build(); - String collectionName = solrClientOptions.getCollection(); - cloudSolrClient.setDefaultCollection(collectionName); - cloudSolrClient.connect(); - } - - private void refreshConfig() throws KrbException { - sun.security.krb5.Config.refresh(); - KerberosName.resetDefaultRealm(); - } - - public void add(SolrInputDocument solrDocument) - throws IOException, SolrServerException, PrivilegedActionException { - if (kerberosOptions.isEnableKrb()) { - Subject.doAs( - subject, - new PrivilegedExceptionAction() { - @Override - public Object run() throws IOException, SolrServerException { - cloudSolrClient.add(solrDocument); - return null; - } - }); - } else { - cloudSolrClient.add(solrDocument); - } - } - - public void commit() throws IOException, SolrServerException, PrivilegedActionException { - if (kerberosOptions.isEnableKrb()) { - Subject.doAs( - subject, - new PrivilegedExceptionAction() { - @Override - public Object run() throws IOException, SolrServerException { - cloudSolrClient.commit(); - return null; - } - }); - } else { - cloudSolrClient.commit(); - } - } - - public void close() throws IOException, PrivilegedActionException { - if (kerberosOptions.isEnableKrb()) { - Subject.doAs( - subject, - new PrivilegedExceptionAction() { - @Override - public Object run() throws IOException { - cloudSolrClient.close(); - return null; - } - }); - } else { - cloudSolrClient.close(); - } - } - - private void setKrb5Conf(String krb5conf) throws KrbException { - DtFileUtils.checkExists(krb5conf); - System.setProperty(JAVA_SECURITY_KRB5_CONF, krb5conf); - LOG.info("{} is set to {}", JAVA_SECURITY_KRB5_CONF, krb5conf); - refreshConfig(); - } - - private Subject genSubject(String principal, String keytab) throws LoginException { - // construct a dynamic JAAS configuration - DynamicConfiguration currentConfig = new DynamicConfiguration(null); - // wire up the configured JAAS login contexts to use the krb5 entries - AppConfigurationEntry krb5Entry = KerberosUtils.keytabEntry(keytab, principal); - currentConfig.addAppConfigurationEntry(JAAS_APP_NAME, krb5Entry); - LoginContext context = new LoginContext(JAAS_APP_NAME, null, null, currentConfig); - - context.login(); - return context.getSubject(); - } - - private void setKrb5HttpClient(String principal, String keytab) { - Krb5HttpClientBuilder krbBuild = new FlinkxKrb5HttpClientBuilder(principal, keytab); - SolrHttpClientBuilder kb = krbBuild.getBuilder(); - HttpClientUtil.setHttpClientBuilder(kb); - } -} diff --git a/solr/solr-sink/src/main/java/com/dtstack/flink/sql/sink/solr/client/FlinkxKrb5HttpClientBuilder.java b/solr/solr-sink/src/main/java/com/dtstack/flink/sql/sink/solr/client/FlinkxKrb5HttpClientBuilder.java deleted file mode 100644 index 2b838dd8e..000000000 --- a/solr/solr-sink/src/main/java/com/dtstack/flink/sql/sink/solr/client/FlinkxKrb5HttpClientBuilder.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.solr.client; - -import com.dtstack.flink.sql.util.KrbUtils; -import org.apache.http.HttpEntity; -import org.apache.http.HttpEntityEnclosingRequest; -import org.apache.http.HttpRequestInterceptor; -import org.apache.http.auth.AuthSchemeProvider; -import org.apache.http.auth.AuthScope; -import org.apache.http.auth.Credentials; -import org.apache.http.client.CredentialsProvider; -import org.apache.http.client.config.AuthSchemes; -import org.apache.http.config.Lookup; -import org.apache.http.config.RegistryBuilder; -import org.apache.http.cookie.CookieSpecProvider; -import org.apache.http.entity.BufferedHttpEntity; -import org.apache.http.impl.auth.SPNegoSchemeFactory; -import org.apache.http.impl.client.BasicCredentialsProvider; -import org.apache.solr.client.solrj.impl.HttpClientUtil; -import org.apache.solr.client.solrj.impl.Krb5HttpClientBuilder; -import org.apache.solr.client.solrj.impl.SolrHttpClientBuilder; -import org.apache.solr.client.solrj.impl.SolrPortAwareCookieSpecFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.lang.invoke.MethodHandles; -import java.security.Principal; -import java.util.Locale; - -/** - * 修改 Krb5HttpClientBuilder使之不依赖 java.security.auth.login.config 环境变量 - * - * @author wuren - * @program flinkStreamSQL - * @create 2021/05/18 - */ -public class FlinkxKrb5HttpClientBuilder extends Krb5HttpClientBuilder { - - public static final String SOLR_KERBEROS_JAAS_APPNAME = "solr.kerberos.jaas.appname"; - private static final Logger logger = - LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - private final String keytab; - private final String principal; - // Set a buffered entity based request interceptor - private final HttpRequestInterceptor bufferedEntityInterceptor = - (request, context) -> { - if (request instanceof HttpEntityEnclosingRequest) { - HttpEntityEnclosingRequest enclosingRequest = - ((HttpEntityEnclosingRequest) request); - HttpEntity requestEntity = enclosingRequest.getEntity(); - enclosingRequest.setEntity(new BufferedHttpEntity(requestEntity)); - } - }; - - public FlinkxKrb5HttpClientBuilder(String principal, String keytab) { - this.principal = principal; - this.keytab = keytab; - } - - @Override - public SolrHttpClientBuilder getBuilder(SolrHttpClientBuilder builder) { - if (System.getProperty(SOLR_KERBEROS_JAAS_APPNAME) != null) { - String configValue = System.getProperty(SOLR_KERBEROS_JAAS_APPNAME); - // if (System.getProperty(LOGIN_CONFIG_PROP) != null) { - // String configValue = System.getProperty(LOGIN_CONFIG_PROP); - - if (configValue != null) { - logger.info("Setting up SPNego auth with config: " + configValue); - final String useSubjectCredsProp = "javax.security.auth.useSubjectCredsOnly"; - String useSubjectCredsVal = System.getProperty(useSubjectCredsProp); - - // "javax.security.auth.useSubjectCredsOnly" should be false so that the underlying - // authentication mechanism can load the credentials from the JAAS configuration. - if (useSubjectCredsVal == null) { - System.setProperty(useSubjectCredsProp, "false"); - } else if (!useSubjectCredsVal.toLowerCase(Locale.ROOT).equals("false")) { - // Don't overwrite the prop value if it's already been written to something - // else, - // but log because it is likely the Credentials won't be loaded correctly. - logger.warn( - "System Property: " - + useSubjectCredsProp - + " set to: " - + useSubjectCredsVal - + " not false. SPNego authentication may not be successful."); - } - KrbUtils.appendJaasConf(configValue, keytab, principal); - - // javax.security.auth.login.Configuration.setConfiguration(jaasConfig); - // Enable only SPNEGO authentication scheme. - - builder.setAuthSchemeRegistryProvider( - () -> { - Lookup authProviders = - RegistryBuilder.create() - .register( - AuthSchemes.SPNEGO, - new SPNegoSchemeFactory(true, false)) - .build(); - return authProviders; - }); - // Get the credentials from the JAAS configuration rather than here - Credentials useJaasCreds = - new Credentials() { - public String getPassword() { - return null; - } - - public Principal getUserPrincipal() { - return null; - } - }; - - HttpClientUtil.setCookiePolicy(SolrPortAwareCookieSpecFactory.POLICY_NAME); - - builder.setCookieSpecRegistryProvider( - () -> { - SolrPortAwareCookieSpecFactory cookieFactory = - new SolrPortAwareCookieSpecFactory(); - - Lookup cookieRegistry = - RegistryBuilder.create() - .register( - SolrPortAwareCookieSpecFactory.POLICY_NAME, - cookieFactory) - .build(); - - return cookieRegistry; - }); - - builder.setDefaultCredentialsProvider( - () -> { - CredentialsProvider credentialsProvider = - new BasicCredentialsProvider(); - credentialsProvider.setCredentials(AuthScope.ANY, useJaasCreds); - return credentialsProvider; - }); - HttpClientUtil.addRequestInterceptor(bufferedEntityInterceptor); - } - } else { - logger.warn( - "{} is configured without specifying system property '{}'", - getClass().getName(), - LOGIN_CONFIG_PROP); - } - - return builder; - } -} diff --git a/solr/solr-sink/src/main/java/com/dtstack/flink/sql/sink/solr/options/KerberosOptions.java b/solr/solr-sink/src/main/java/com/dtstack/flink/sql/sink/solr/options/KerberosOptions.java deleted file mode 100644 index 19a25769a..000000000 --- a/solr/solr-sink/src/main/java/com/dtstack/flink/sql/sink/solr/options/KerberosOptions.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.solr.options; - -import com.dtstack.flink.sql.krb.KerberosTable; - -import java.io.Serializable; - -/** - * @author wuren - * @program flinkStreamSQL - * @create 2021/05/17 - */ -public class KerberosOptions implements KerberosTable, Serializable { - - boolean enableKrb; - private String principal; - private String keytab; - private String krb5conf; - - public KerberosOptions(String principal, String keytab, String krb5conf) { - this.principal = principal; - this.keytab = keytab; - this.krb5conf = krb5conf; - } - - @Override - public String getPrincipal() { - return principal; - } - - @Override - public void setPrincipal(String principal) { - this.principal = principal; - } - - @Override - public String getKeytab() { - return keytab; - } - - @Override - public void setKeytab(String keytab) { - this.keytab = keytab; - } - - @Override - public String getKrb5conf() { - return krb5conf; - } - - @Override - public void setKrb5conf(String krb5conf) { - this.krb5conf = krb5conf; - } - - @Override - public boolean isEnableKrb() { - return enableKrb; - } - - @Override - public void setEnableKrb(boolean enableKrb) { - this.enableKrb = enableKrb; - } -} diff --git a/solr/solr-sink/src/main/java/com/dtstack/flink/sql/sink/solr/options/SolrClientOptions.java b/solr/solr-sink/src/main/java/com/dtstack/flink/sql/sink/solr/options/SolrClientOptions.java deleted file mode 100644 index 23f2ca441..000000000 --- a/solr/solr-sink/src/main/java/com/dtstack/flink/sql/sink/solr/options/SolrClientOptions.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.solr.options; - -import java.io.Serializable; -import java.util.List; - -/** - * @author wuren - * @program flinkStreamSQL - * @create 2021/05/17 - */ -public class SolrClientOptions implements Serializable { - - private List zkHosts; - private String zkChroot; - private String collection; - - public SolrClientOptions(List zkHosts, String zkChroot, String collection) { - this.zkHosts = zkHosts; - this.zkChroot = zkChroot; - this.collection = collection; - } - - public List getZkHosts() { - return zkHosts; - } - - public void setZkHosts(List zkHosts) { - this.zkHosts = zkHosts; - } - - public String getZkChroot() { - return zkChroot; - } - - public void setZkChroot(String zkChroot) { - this.zkChroot = zkChroot; - } - - public String getCollection() { - return collection; - } - - public void setCollection(String collection) { - this.collection = collection; - } -} diff --git a/solr/solr-sink/src/main/java/com/dtstack/flink/sql/sink/solr/options/SolrWriteOptions.java b/solr/solr-sink/src/main/java/com/dtstack/flink/sql/sink/solr/options/SolrWriteOptions.java deleted file mode 100644 index d0cf2c52b..000000000 --- a/solr/solr-sink/src/main/java/com/dtstack/flink/sql/sink/solr/options/SolrWriteOptions.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.solr.options; - -import java.io.Serializable; -import java.util.Optional; - -/** - * @author wuren - * @program flinkStreamSQL - * @create 2021/05/17 - */ -public class SolrWriteOptions implements Serializable { - - private static final long DEFAULT_BUFFER_FLUSH_INTERVAL_MILLIS = 1000; - private static final int DEFAULT_BUFFER_FLUSH_MAX_ROWS = 1000; - private static final int DEFAULT_PARALLELISMS = -1; - private final long bufferFlushIntervalMillis; - private final int bufferFlushMaxRows; - private final Integer parallelism; - - public SolrWriteOptions( - Optional bufferFlushIntervalMillis, - Optional bufferFlushMaxRows, - Optional parallelism) { - this.bufferFlushIntervalMillis = - bufferFlushIntervalMillis.orElse(DEFAULT_BUFFER_FLUSH_INTERVAL_MILLIS); - this.bufferFlushMaxRows = bufferFlushMaxRows.orElse(DEFAULT_BUFFER_FLUSH_MAX_ROWS); - this.parallelism = parallelism.orElse(DEFAULT_PARALLELISMS); - } - - public int getParallelism() { - return parallelism; - } - - public long getBufferFlushIntervalMillis() { - return bufferFlushIntervalMillis; - } - - public int getBufferFlushMaxRows() { - return bufferFlushMaxRows; - } -} diff --git a/solr/solr-sink/src/main/java/com/dtstack/flink/sql/sink/solr/table/SolrSinkParser.java b/solr/solr-sink/src/main/java/com/dtstack/flink/sql/sink/solr/table/SolrSinkParser.java deleted file mode 100644 index a13eaf561..000000000 --- a/solr/solr-sink/src/main/java/com/dtstack/flink/sql/sink/solr/table/SolrSinkParser.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.solr.table; - -import com.dtstack.flink.sql.constant.PluginParamConsts; -import com.dtstack.flink.sql.sink.solr.options.KerberosOptions; -import com.dtstack.flink.sql.sink.solr.options.SolrClientOptions; -import com.dtstack.flink.sql.sink.solr.options.SolrWriteOptions; -import com.dtstack.flink.sql.table.AbstractTableInfo; -import com.dtstack.flink.sql.table.AbstractTableParser; -import com.dtstack.flink.sql.util.MathUtil; -import org.apache.commons.lang3.StringUtils; - -import java.sql.Timestamp; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.Optional; - -import static com.dtstack.flink.sql.table.AbstractTableInfo.PARALLELISM_KEY; - -/** - * @author wuren - * @program flinkStreamSQL - * @create 2021/05/17 - */ -public class SolrSinkParser extends AbstractTableParser { - - public static final String ZK_HOSTS = "zk-hosts"; - public static final String ZK_CHROOT = "zk-chroot"; - public static final String COLLECTION = "collection"; - - public static final String SINK_BUFFER_FLUSH_MAX_ROWS = "sink.buffer-flush.max-rows"; - public static final String SINK_BUFFER_FLUSH_INTERVAL = "sink.buffer-flush.interval"; - - @Override - public AbstractTableInfo getTableInfo( - String tableName, String fieldsInfo, Map props) throws Exception { - SolrTableInfo solrTableInfo = new SolrTableInfo(); - solrTableInfo.setName(tableName); - parseFieldsInfo(fieldsInfo, solrTableInfo); - - String zkHostsStr = MathUtil.getString(props.get(ZK_HOSTS)); - List zkHosts = Arrays.asList(StringUtils.split(zkHostsStr, ',')); - SolrClientOptions solrClientOptions = - new SolrClientOptions( - zkHosts, - MathUtil.getString(props.get(ZK_CHROOT)), - MathUtil.getString(props.get(COLLECTION))); - solrTableInfo.setSolrClientOptions(solrClientOptions); - - SolrWriteOptions solrWriteOptions = - new SolrWriteOptions( - Optional.ofNullable( - MathUtil.getLongVal(props.get(SINK_BUFFER_FLUSH_INTERVAL))), - Optional.ofNullable( - MathUtil.getIntegerVal(props.get(SINK_BUFFER_FLUSH_MAX_ROWS))), - Optional.ofNullable( - MathUtil.getIntegerVal(props.get(PARALLELISM_KEY.toLowerCase())))); - solrTableInfo.setSolrWriteOptions(solrWriteOptions); - - KerberosOptions kerberosOptions = - new KerberosOptions( - MathUtil.getString(props.get(PluginParamConsts.PRINCIPAL)), - MathUtil.getString(props.get(PluginParamConsts.KEYTAB)), - MathUtil.getString(props.get(PluginParamConsts.KRB5_CONF))); - kerberosOptions.judgeKrbEnable(); - solrTableInfo.setKerberosOptions(kerberosOptions); - - return solrTableInfo; - } - - @Override - public Class dbTypeConvertToJavaType(String fieldType) { - switch (fieldType.toLowerCase()) { - case "bool": - case "boolean": - return Boolean.class; - case "int": - case "integer": - return Integer.class; - case "long": - case "bigint": - return Long.class; - case "varchar": - case "string": - case "text": - return String.class; - case "float": - return Float.class; - case "double": - return Double.class; - case "date": - case "timestamp": - return Timestamp.class; - default: - throw new RuntimeException("不支持 " + fieldType + " 类型"); - } - } -} diff --git a/solr/solr-sink/src/main/java/com/dtstack/flink/sql/sink/solr/table/SolrTableInfo.java b/solr/solr-sink/src/main/java/com/dtstack/flink/sql/sink/solr/table/SolrTableInfo.java deleted file mode 100644 index a3c61942a..000000000 --- a/solr/solr-sink/src/main/java/com/dtstack/flink/sql/sink/solr/table/SolrTableInfo.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.solr.table; - -import com.dtstack.flink.sql.sink.solr.options.KerberosOptions; -import com.dtstack.flink.sql.sink.solr.options.SolrClientOptions; -import com.dtstack.flink.sql.sink.solr.options.SolrWriteOptions; -import com.dtstack.flink.sql.table.AbstractTargetTableInfo; -import com.google.common.base.Preconditions; - -import java.util.List; - -/** - * @author wuren - * @program flinkStreamSQL - * @create 2021/05/17 - */ -public class SolrTableInfo extends AbstractTargetTableInfo { - - private static final String TYPE = "solr"; - - private SolrClientOptions solrClientOptions; - private SolrWriteOptions solrWriteOptions; - private KerberosOptions kerberosOptions; - - public SolrClientOptions getSolrClientOptions() { - return solrClientOptions; - } - - public void setSolrClientOptions(SolrClientOptions solrClientOptions) { - this.solrClientOptions = solrClientOptions; - } - - public SolrWriteOptions getSolrWriteOptions() { - return solrWriteOptions; - } - - public void setSolrWriteOptions(SolrWriteOptions solrWriteOptions) { - this.solrWriteOptions = solrWriteOptions; - } - - public KerberosOptions getKerberosOptions() { - return kerberosOptions; - } - - public void setKerberosOptions(KerberosOptions kerberosOptions) { - this.kerberosOptions = kerberosOptions; - } - - @Override - public boolean check() { - List zkHosts = solrClientOptions.getZkHosts(); - Preconditions.checkNotNull(zkHosts, "zk-hosts is required"); - Preconditions.checkState(!zkHosts.isEmpty(), "zk-hosts is required"); - String collection = solrClientOptions.getCollection(); - Preconditions.checkNotNull(collection, "collection is required"); - Preconditions.checkState(!collection.isEmpty(), "collection is required"); - return true; - } - - @Override - public String getType() { - return TYPE; - } -} diff --git a/solr/solr-sink/src/test/java/com/dtstack/flink/sql/sink/solr/table/SolrTableInfoTest.java b/solr/solr-sink/src/test/java/com/dtstack/flink/sql/sink/solr/table/SolrTableInfoTest.java deleted file mode 100644 index b7313dfa1..000000000 --- a/solr/solr-sink/src/test/java/com/dtstack/flink/sql/sink/solr/table/SolrTableInfoTest.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.dtstack.flink.sql.sink.solr.table; - -import com.dtstack.flink.sql.sink.solr.options.SolrClientOptions; -import org.junit.Test; - -import java.util.ArrayList; -import java.util.List; - -public class SolrTableInfoTest { - - @Test - public void check() { - SolrTableInfo solrTableInfo = new SolrTableInfo(); - List zkHosts = new ArrayList<>(); - SolrClientOptions solrClientOptions = new SolrClientOptions(zkHosts, null, ""); - solrTableInfo.setSolrClientOptions(solrClientOptions); - try { - solrTableInfo.check(); - } catch (NullPointerException | IllegalStateException e) { - } - zkHosts.add("host:2181"); - solrClientOptions.setZkHosts(zkHosts); - try { - solrTableInfo.check(); - } catch (NullPointerException | IllegalStateException e) { - } - solrClientOptions.setCollection("abc"); - solrTableInfo.check(); - } -} diff --git a/sqlserver/pom.xml b/sqlserver/pom.xml index 08372d73a..de00840e8 100644 --- a/sqlserver/pom.xml +++ b/sqlserver/pom.xml @@ -17,7 +17,6 @@ 1.3.1 1.0-SNAPSHOT - 9.2.1.jre8 @@ -33,13 +32,11 @@ provided - - com.microsoft.sqlserver - mssql-jdbc - ${mssql.jdbc.version} + net.sourceforge.jtds + jtds + ${jtds.version} - \ No newline at end of file diff --git a/sqlserver/sqlserver-side/pom.xml b/sqlserver/sqlserver-side/pom.xml index 214a4144a..3848021e6 100644 --- a/sqlserver/sqlserver-side/pom.xml +++ b/sqlserver/sqlserver-side/pom.xml @@ -32,16 +32,6 @@ sql.side.rdb ${rdb.side.version} - - - - - com.dtstack.flink - sql.side.rdb - ${rdb.side.version} - test-jar - test - diff --git a/sqlserver/sqlserver-side/sqlserver-all-side/pom.xml b/sqlserver/sqlserver-side/sqlserver-all-side/pom.xml index 15ff1039e..136a2af3d 100644 --- a/sqlserver/sqlserver-side/sqlserver-all-side/pom.xml +++ b/sqlserver/sqlserver-side/sqlserver-all-side/pom.xml @@ -73,14 +73,14 @@ - + - + diff --git a/sqlserver/sqlserver-side/sqlserver-all-side/src/main/java/com/dtstack/flink/sql/side/sqlserver/SqlserverAllReqRow.java b/sqlserver/sqlserver-side/sqlserver-all-side/src/main/java/com/dtstack/flink/sql/side/sqlserver/SqlserverAllReqRow.java index 3b4364a2b..961539fde 100644 --- a/sqlserver/sqlserver-side/sqlserver-all-side/src/main/java/com/dtstack/flink/sql/side/sqlserver/SqlserverAllReqRow.java +++ b/sqlserver/sqlserver-side/sqlserver-all-side/src/main/java/com/dtstack/flink/sql/side/sqlserver/SqlserverAllReqRow.java @@ -1,4 +1,4 @@ -/* +/** * 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 @@ -20,47 +20,44 @@ import com.dtstack.flink.sql.side.FieldInfo; import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.rdb.all.AbstractRdbAllReqRow; +import com.dtstack.flink.sql.side.SideTableInfo; +import com.dtstack.flink.sql.side.rdb.all.RdbAllReqRow; import com.dtstack.flink.sql.util.DtStringUtil; import org.apache.flink.api.java.typeutils.RowTypeInfo; import com.google.common.collect.Maps; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.sql.Connection; import java.sql.DriverManager; import java.util.List; import java.util.Map; - /** - * side operator with cache for all(period reload) - * Date: 2019/11/26 - * Company: www.dtstack.com - * @author maqi + * side operator with cache for all(period reload) */ -public class SqlserverAllReqRow extends AbstractRdbAllReqRow { +public class SqlserverAllReqRow extends RdbAllReqRow { private static final Logger LOG = LoggerFactory.getLogger(SqlserverAllReqRow.class); - private static final String SQLSERVER_DRIVER = "com.microsoft.sqlserver.jdbc.SQLServerDriver"; + private static final String SQLSERVER_DRIVER = "net.sourceforge.jtds.jdbc.Driver"; - public SqlserverAllReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { + public SqlserverAllReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, SideTableInfo sideTableInfo) { super(new SqlserverAllSideInfo(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo)); } @Override - public Connection getConn(String dbUrl, String userName, String password) { + public Connection getConn(String dbURL, String userName, String password) { try { Class.forName(SQLSERVER_DRIVER); //add param useCursorFetch=true Map addParams = Maps.newHashMap(); - String targetDbUrl = DtStringUtil.addJdbcParam(dbUrl, addParams, true); + //addParams.put("useCursorFetch", "true"); + String targetDbUrl = DtStringUtil.addJdbcParam(dbURL, addParams, true); return DriverManager.getConnection(targetDbUrl, userName, password); } catch (Exception e) { LOG.error("", e); throw new RuntimeException("", e); } } + } diff --git a/sqlserver/sqlserver-side/sqlserver-all-side/src/main/java/com/dtstack/flink/sql/side/sqlserver/SqlserverAllSideInfo.java b/sqlserver/sqlserver-side/sqlserver-all-side/src/main/java/com/dtstack/flink/sql/side/sqlserver/SqlserverAllSideInfo.java index 43fc5daea..2b9913e7e 100644 --- a/sqlserver/sqlserver-side/sqlserver-all-side/src/main/java/com/dtstack/flink/sql/side/sqlserver/SqlserverAllSideInfo.java +++ b/sqlserver/sqlserver-side/sqlserver-all-side/src/main/java/com/dtstack/flink/sql/side/sqlserver/SqlserverAllSideInfo.java @@ -1,4 +1,4 @@ -/* +/** * 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 @@ -18,33 +18,16 @@ package com.dtstack.flink.sql.side.sqlserver; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; import com.dtstack.flink.sql.side.FieldInfo; import com.dtstack.flink.sql.side.JoinInfo; +import com.dtstack.flink.sql.side.SideTableInfo; import com.dtstack.flink.sql.side.rdb.all.RdbAllSideInfo; -import com.dtstack.flink.sql.side.rdb.table.RdbSideTableInfo; -import com.dtstack.flink.sql.util.DtStringUtil; import org.apache.flink.api.java.typeutils.RowTypeInfo; - import java.util.List; -/** - * Date: 2019/11/26 - * Company: www.dtstack.com - * @author maqi - */ + public class SqlserverAllSideInfo extends RdbAllSideInfo { - public SqlserverAllSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { + public SqlserverAllSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, SideTableInfo sideTableInfo) { super(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); } - - @Override - public String quoteIdentifier(String identifier) { - return "\"" + identifier + "\""; - } - - @Override - public String getTableName(RdbSideTableInfo rdbSideTableInfo) { - return DtStringUtil.getTableFullPath(rdbSideTableInfo.getSchema(), rdbSideTableInfo.getTableName()); - } } diff --git a/sqlserver/sqlserver-side/sqlserver-all-side/src/test/java/com/dtstack/flink/sql/side/sqlserver/SqlserverAllReqRowTest.java b/sqlserver/sqlserver-side/sqlserver-all-side/src/test/java/com/dtstack/flink/sql/side/sqlserver/SqlserverAllReqRowTest.java deleted file mode 100644 index 8d64bd568..000000000 --- a/sqlserver/sqlserver-side/sqlserver-all-side/src/test/java/com/dtstack/flink/sql/side/sqlserver/SqlserverAllReqRowTest.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.dtstack.flink.sql.side.sqlserver; - -import com.dtstack.flink.sql.side.rdb.all.RdbAllReqRowTestBase; - -public class SqlserverAllReqRowTest extends RdbAllReqRowTestBase { - - @Override - protected void init() { - clazz = SqlserverAllReqRow.class; - } - -} \ No newline at end of file diff --git a/sqlserver/sqlserver-side/sqlserver-async-side/pom.xml b/sqlserver/sqlserver-side/sqlserver-async-side/pom.xml index 4e9ff6631..fc2d000f3 100644 --- a/sqlserver/sqlserver-side/sqlserver-async-side/pom.xml +++ b/sqlserver/sqlserver-side/sqlserver-async-side/pom.xml @@ -73,14 +73,14 @@ - + - + diff --git a/sqlserver/sqlserver-side/sqlserver-async-side/src/main/java/com/dtstack/flink/sql/side/sqlserver/SqlserverAsyncReqRow.java b/sqlserver/sqlserver-side/sqlserver-async-side/src/main/java/com/dtstack/flink/sql/side/sqlserver/SqlserverAsyncReqRow.java index 7582b00b0..cb4240ca6 100644 --- a/sqlserver/sqlserver-side/sqlserver-async-side/src/main/java/com/dtstack/flink/sql/side/sqlserver/SqlserverAsyncReqRow.java +++ b/sqlserver/sqlserver-side/sqlserver-async-side/src/main/java/com/dtstack/flink/sql/side/sqlserver/SqlserverAsyncReqRow.java @@ -19,12 +19,13 @@ package com.dtstack.flink.sql.side.sqlserver; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; +import com.dtstack.flink.sql.side.*; import com.dtstack.flink.sql.side.rdb.async.RdbAsyncReqRow; import com.dtstack.flink.sql.side.rdb.table.RdbSideTableInfo; +import io.vertx.core.Vertx; +import io.vertx.core.VertxOptions; import io.vertx.core.json.JsonObject; +import io.vertx.ext.jdbc.JDBCClient; import org.apache.flink.api.java.typeutils.RowTypeInfo; import org.apache.flink.configuration.Configuration; import org.slf4j.Logger; @@ -32,33 +33,25 @@ import java.util.List; -/** - * Date: 2019/11/26 - * Company: www.dtstack.com - * @author maqi - */ + public class SqlserverAsyncReqRow extends RdbAsyncReqRow { private static final Logger LOG = LoggerFactory.getLogger(SqlserverAsyncReqRow.class); - private final static String SQLSERVER_DRIVER = "com.microsoft.sqlserver.jdbc.SQLServerDriver"; + private final static String SQLSERVER_DRIVER = "net.sourceforge.jtds.jdbc.Driver"; - public SqlserverAsyncReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { + public SqlserverAsyncReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, SideTableInfo sideTableInfo) { super(new SqlserverAsyncSideInfo(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo)); } @Override public void open(Configuration parameters) throws Exception { super.open(parameters); - } - - @Override - public JsonObject buildJdbcConfig() { JsonObject sqlserverClientConfig = new JsonObject(); RdbSideTableInfo rdbSideTableInfo = (RdbSideTableInfo) sideInfo.getSideTableInfo(); sqlserverClientConfig.put("url", rdbSideTableInfo.getUrl()) .put("driver_class", SQLSERVER_DRIVER) - .put("max_pool_size", rdbSideTableInfo.getAsyncPoolSize()) + .put("max_pool_size", DEFAULT_MAX_DB_CONN_POOL_SIZE) .put("user", rdbSideTableInfo.getUserName()) .put("password", rdbSideTableInfo.getPassword()) .put("provider_class", DT_PROVIDER_CLASS) @@ -66,6 +59,14 @@ public JsonObject buildJdbcConfig() { .put("idle_connection_test_period", DEFAULT_IDLE_CONNECTION_TEST_PEROID) .put("test_connection_on_checkin", DEFAULT_TEST_CONNECTION_ON_CHECKIN); - return sqlserverClientConfig; + + System.setProperty("vertx.disableFileCPResolving", "true"); + + VertxOptions vo = new VertxOptions(); + vo.setEventLoopPoolSize(DEFAULT_VERTX_EVENT_LOOP_POOL_SIZE); + vo.setWorkerPoolSize(DEFAULT_VERTX_WORKER_POOL_SIZE); + vo.setFileResolverCachingEnabled(false); + Vertx vertx = Vertx.vertx(vo); + setRdbSQLClient(JDBCClient.createNonShared(vertx, sqlserverClientConfig)); } } diff --git a/sqlserver/sqlserver-side/sqlserver-async-side/src/main/java/com/dtstack/flink/sql/side/sqlserver/SqlserverAsyncSideInfo.java b/sqlserver/sqlserver-side/sqlserver-async-side/src/main/java/com/dtstack/flink/sql/side/sqlserver/SqlserverAsyncSideInfo.java index 889e90c60..347ca9bf4 100644 --- a/sqlserver/sqlserver-side/sqlserver-async-side/src/main/java/com/dtstack/flink/sql/side/sqlserver/SqlserverAsyncSideInfo.java +++ b/sqlserver/sqlserver-side/sqlserver-async-side/src/main/java/com/dtstack/flink/sql/side/sqlserver/SqlserverAsyncSideInfo.java @@ -20,33 +20,16 @@ import com.dtstack.flink.sql.side.FieldInfo; import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.AbstractSideTableInfo; +import com.dtstack.flink.sql.side.SideTableInfo; import com.dtstack.flink.sql.side.rdb.async.RdbAsyncSideInfo; -import com.dtstack.flink.sql.side.rdb.table.RdbSideTableInfo; -import com.dtstack.flink.sql.util.DtStringUtil; import org.apache.flink.api.java.typeutils.RowTypeInfo; - import java.util.List; -/** - * Date: 2019/11/26 - * Company: www.dtstack.com - * @author maqi - */ + public class SqlserverAsyncSideInfo extends RdbAsyncSideInfo { - public SqlserverAsyncSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { + public SqlserverAsyncSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, SideTableInfo sideTableInfo) { super(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); } - - @Override - public String getTableName(RdbSideTableInfo rdbSideTableInfo) { - return DtStringUtil.getTableFullPath(rdbSideTableInfo.getSchema(), rdbSideTableInfo.getTableName()); - } - - @Override - public String quoteIdentifier(String identifier) { - return "\"" + identifier + "\""; - } } diff --git a/sqlserver/sqlserver-side/sqlserver-async-side/src/test/java/com/dtstack/flink/sql/side/sqlserver/SqlserverAsyncReqRowTest.java b/sqlserver/sqlserver-side/sqlserver-async-side/src/test/java/com/dtstack/flink/sql/side/sqlserver/SqlserverAsyncReqRowTest.java deleted file mode 100644 index 93e110a94..000000000 --- a/sqlserver/sqlserver-side/sqlserver-async-side/src/test/java/com/dtstack/flink/sql/side/sqlserver/SqlserverAsyncReqRowTest.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.dtstack.flink.sql.side.sqlserver; - -import com.dtstack.flink.sql.side.rdb.async.RdbAsyncReqRowTestBase; - -public class SqlserverAsyncReqRowTest extends RdbAsyncReqRowTestBase { - - @Override - protected void init() { - clazz = SqlserverAsyncReqRow.class; - } - -} \ No newline at end of file diff --git a/sqlserver/sqlserver-side/sqlserver-side-core/src/main/java/com/dtstack/flink/sql/side/sqlserver/table/SqlserverSideParser.java b/sqlserver/sqlserver-side/sqlserver-side-core/src/main/java/com/dtstack/flink/sql/side/sqlserver/table/SqlserverSideParser.java index ca34d6599..3631dcd8a 100644 --- a/sqlserver/sqlserver-side/sqlserver-side-core/src/main/java/com/dtstack/flink/sql/side/sqlserver/table/SqlserverSideParser.java +++ b/sqlserver/sqlserver-side/sqlserver-side-core/src/main/java/com/dtstack/flink/sql/side/sqlserver/table/SqlserverSideParser.java @@ -17,23 +17,17 @@ */ package com.dtstack.flink.sql.side.sqlserver.table; -import com.dtstack.flink.sql.core.rdb.JdbcCheckKeys; import com.dtstack.flink.sql.side.rdb.table.RdbSideParser; -import com.dtstack.flink.sql.table.AbstractTableInfo; +import com.dtstack.flink.sql.table.TableInfo; import java.util.Map; -/** - * Date: 2019/11/26 - * Company: www.dtstack.com - * @author maqi - */ + public class SqlserverSideParser extends RdbSideParser { private static final String CURR_TYPE = "sqlserver"; @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { - props.put(JdbcCheckKeys.DRIVER_NAME, "com.microsoft.sqlserver.jdbc.SQLServerDriver"); - AbstractTableInfo sqlServerTableInfo = super.getTableInfo(tableName, fieldsInfo, props); + public TableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { + TableInfo sqlServerTableInfo = super.getTableInfo(tableName, fieldsInfo, props); sqlServerTableInfo.setType(CURR_TYPE); return sqlServerTableInfo; } diff --git a/sqlserver/sqlserver-side/sqlserver-side-core/src/test/java/com/dtstack/flink/sql/side/sqlserver/table/SqlserverSideParserTest.java b/sqlserver/sqlserver-side/sqlserver-side-core/src/test/java/com/dtstack/flink/sql/side/sqlserver/table/SqlserverSideParserTest.java deleted file mode 100644 index 930e70874..000000000 --- a/sqlserver/sqlserver-side/sqlserver-side-core/src/test/java/com/dtstack/flink/sql/side/sqlserver/table/SqlserverSideParserTest.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.dtstack.flink.sql.side.sqlserver.table; - -import com.dtstack.flink.sql.table.AbstractTableInfo; -import org.junit.Assert; -import org.junit.Test; -import java.util.HashMap; -import java.util.Map; - -public class SqlserverSideParserTest { - -// @Test - public void getTableInfo() { - SqlserverSideParser sideParser = new SqlserverSideParser(); - - final String tableName = "table_foo"; - final String fieldsInfo = "id INT, name VARCHAR, PRIMARY KEY (id)"; - - Map props = new HashMap(); - props.put("url", "jdbc:mysql://foo:3306/db_foo"); - props.put("tablename", "table_foo"); - props.put("username", "foo"); - props.put("password", "foo"); - - AbstractTableInfo tableInfo= sideParser.getTableInfo(tableName, fieldsInfo, props); - - final String NORMAL_TYPE = "sqlserver"; - final String table_type = tableInfo.getType(); - Assert.assertTrue(NORMAL_TYPE.equals(table_type)); - } - -} \ No newline at end of file diff --git a/sqlserver/sqlserver-sink/pom.xml b/sqlserver/sqlserver-sink/pom.xml index be4aed37f..2066877ff 100644 --- a/sqlserver/sqlserver-sink/pom.xml +++ b/sqlserver/sqlserver-sink/pom.xml @@ -74,14 +74,14 @@ - + - + diff --git a/sqlserver/sqlserver-sink/src/main/java/com/dtstack/flink/sql/sink/sqlserver/SqlserverDialect.java b/sqlserver/sqlserver-sink/src/main/java/com/dtstack/flink/sql/sink/sqlserver/SqlserverDialect.java deleted file mode 100644 index 56fa9e84d..000000000 --- a/sqlserver/sqlserver-sink/src/main/java/com/dtstack/flink/sql/sink/sqlserver/SqlserverDialect.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.sqlserver; - -import com.dtstack.flink.sql.sink.rdb.dialect.JDBCDialect; -import com.dtstack.flink.sql.util.DtStringUtil; -import org.apache.commons.lang3.StringUtils; - -import java.util.Arrays; -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; - -/** - * Date: 2020/1/15 - * Company: www.dtstack.com - * - * @author maqi - */ -public class SqlserverDialect implements JDBCDialect { - - @Override - public boolean canHandle(String url) { - return url.startsWith("jdbc:sqlserver:"); - } - - @Override - public Optional defaultDriverName() { - return Optional.of("com.microsoft.sqlserver.jdbc.SQLServerDriver"); - } - - @Override - public Optional getUpsertStatement(String schema, String tableName, String[] fieldNames, String[] uniqueKeyFields, boolean allReplace) { - tableName = DtStringUtil.getTableFullPath(schema, tableName); - StringBuilder sb = new StringBuilder(); - sb.append("MERGE INTO ") - .append(tableName) - .append(" T1 USING (") - .append(buildDualQueryStatement(fieldNames)) - .append(") T2 ON (") - .append(buildConnectionConditions(uniqueKeyFields)) - .append(") "); - - String updateSql = buildUpdateConnection(fieldNames, uniqueKeyFields, allReplace); - - if (StringUtils.isNotEmpty(updateSql)) { - sb.append(" WHEN MATCHED THEN UPDATE SET ") - .append(updateSql); - } - - sb.append(" WHEN NOT MATCHED THEN " + "INSERT (") - .append( - Arrays - .stream(fieldNames) - .map(this::quoteIdentifier) - .collect(Collectors.joining(","))) - .append(") VALUES (") - .append( - Arrays - .stream(fieldNames) - .map(col -> "T2." + quoteIdentifier(col)) - .collect(Collectors.joining(","))) - .append(");"); - return Optional.of(sb.toString()); - } - - /** - * build T1."A"=T2."A" or T1."A"=nvl(T2."A",T1."A") - * - * @param fieldNames - * @param uniqueKeyFields - * @param allReplace - * @return - */ - private String buildUpdateConnection(String[] fieldNames, String[] uniqueKeyFields, boolean allReplace) { - List uniqueKeyList = Arrays.asList(uniqueKeyFields); - return - Arrays - .stream(fieldNames) - .filter(col -> !uniqueKeyList.contains(col)) - .map(col -> allReplace ? - quoteIdentifier("T1") + "." + quoteIdentifier(col) + " = " + quoteIdentifier("T2") + "." + quoteIdentifier(col) : - quoteIdentifier("T1") + "." + quoteIdentifier(col) + " =ISNULL(" + quoteIdentifier("T2") + "." + quoteIdentifier(col) - + "," + quoteIdentifier("T1") + "." + quoteIdentifier(col) + ")").collect(Collectors.joining(",")); - } - - - private String buildConnectionConditions(String[] uniqueKeyFields) { - return - Arrays - .stream(uniqueKeyFields) - .map(col -> "T1." + quoteIdentifier(col) + "=T2." + quoteIdentifier(col)) - .collect(Collectors.joining(",")); - } - - /** - * build select sql , such as (SELECT ? "A",? "B" FROM DUAL) - * - * @param column destination column - * @return - */ - public String buildDualQueryStatement(String[] column) { - StringBuilder sb = new StringBuilder("SELECT "); - String collect = - Arrays - .stream(column) - .map(col -> " ? " + quoteIdentifier(col)) - .collect(Collectors.joining(", ")); - sb.append(collect); - return sb.toString(); - } -} diff --git a/sqlserver/sqlserver-sink/src/main/java/com/dtstack/flink/sql/sink/sqlserver/SqlserverSink.java b/sqlserver/sqlserver-sink/src/main/java/com/dtstack/flink/sql/sink/sqlserver/SqlserverSink.java index 020787ef2..2341bca66 100644 --- a/sqlserver/sqlserver-sink/src/main/java/com/dtstack/flink/sql/sink/sqlserver/SqlserverSink.java +++ b/sqlserver/sqlserver-sink/src/main/java/com/dtstack/flink/sql/sink/sqlserver/SqlserverSink.java @@ -18,9 +18,13 @@ package com.dtstack.flink.sql.sink.sqlserver; import com.dtstack.flink.sql.sink.IStreamSinkGener; -import com.dtstack.flink.sql.sink.rdb.JDBCOptions; -import com.dtstack.flink.sql.sink.rdb.AbstractRdbSink; -import com.dtstack.flink.sql.sink.rdb.format.JDBCUpsertOutputFormat; +import com.dtstack.flink.sql.sink.rdb.RdbSink; +import com.dtstack.flink.sql.sink.rdb.format.ExtendOutputFormat; +import com.dtstack.flink.sql.sink.rdb.format.RetractJDBCOutputFormat; +import com.dtstack.flink.sql.util.DtStringUtil; +import org.apache.commons.lang3.StringUtils; + +import java.util.*; /** * Reason: @@ -29,32 +33,160 @@ * * @author maqi */ -public class SqlserverSink extends AbstractRdbSink implements IStreamSinkGener { +public class SqlserverSink extends RdbSink implements IStreamSinkGener { + private static final String SQLSERVER_DRIVER = "net.sourceforge.jtds.jdbc.Driver"; + + @Override + public String getDriverName() { + return SQLSERVER_DRIVER; + } + + @Override + public RetractJDBCOutputFormat getOutputFormat() { + return new ExtendOutputFormat(); + } + + @Override + public void buildSql(String scheam, String tableName, List fields) { + buildInsertSql(tableName, fields); + } + + private void buildInsertSql(String tableName, List fields) { + String sqlTmp = "insert into " + tableName + " (${fields}) values (${placeholder})"; + String fieldsStr = StringUtils.join(fields, ","); + String placeholder = ""; - public SqlserverSink() { - super(new SqlserverDialect()); + for (String fieldName : fields) { + placeholder += ",?"; + } + placeholder = placeholder.replaceFirst(",", ""); + sqlTmp = sqlTmp.replace("${fields}", fieldsStr).replace("${placeholder}", placeholder); + this.sql = sqlTmp; } @Override - public JDBCUpsertOutputFormat getOutputFormat() { - JDBCOptions jdbcOptions = JDBCOptions.builder() - .setDbUrl(dbUrl) - .setDialect(jdbcDialect) - .setUsername(userName) - .setPassword(password) - .setTableName(tableName) - .setSchema(schema) - .build(); - - return JDBCUpsertOutputFormat.builder() - .setOptions(jdbcOptions) - .setFieldNames(fieldNames) - .setFlushMaxSize(batchNum) - .setFlushIntervalMills(batchWaitInterval) - .setFieldTypes(sqlTypes) - .setKeyFields(primaryKeys) - .setAllReplace(allReplace) - .setErrorLimit(errorLimit) - .setUpdateMode(updateMode).build(); + public String buildUpdateSql(String scheam, String tableName, List fieldNames, Map> realIndexes, List fullField) { + StringBuilder sb = new StringBuilder(); + + sb.append("MERGE INTO " + tableName + " T1 USING " + + "(" + makeValues(fieldNames) + ") T2 ON (" + + updateKeySql(realIndexes) + ") "); + + + String updateSql = getUpdateSql(fieldNames, fullField, "T1", "T2", keyColList(realIndexes)); + + if (StringUtils.isNotEmpty(updateSql)) { + sb.append(" WHEN MATCHED THEN UPDATE SET "); + sb.append(updateSql); + } + + sb.append(" WHEN NOT MATCHED THEN " + + "INSERT (" + quoteColumns(fieldNames) + ") VALUES (" + + quoteColumns(fieldNames, "T2") + ")"); + + return sb.toString(); + } + + + public String quoteColumns(List column) { + return quoteColumns(column, null); + } + + public String quoteColumns(List column, String table) { + String prefix = StringUtils.isBlank(table) ? "" : quoteTable(table) + "."; + List list = new ArrayList<>(); + for (String col : column) { + list.add(prefix + quoteColumn(col)); + } + return StringUtils.join(list, ","); } + + protected List keyColList(Map> updateKey) { + List keyCols = new ArrayList<>(); + for (Map.Entry> entry : updateKey.entrySet()) { + List list = entry.getValue(); + for (String col : list) { + if (!containsIgnoreCase(keyCols,col)) { + keyCols.add(col); + } + } + } + return keyCols; + } + + public String getUpdateSql(List column, List fullColumn, String leftTable, String rightTable, List keyCols) { + String prefixLeft = StringUtils.isBlank(leftTable) ? "" : quoteTable(leftTable) + "."; + String prefixRight = StringUtils.isBlank(rightTable) ? "" : quoteTable(rightTable) + "."; + List list = new ArrayList<>(); + for (String col : fullColumn) { + if (keyCols == null || keyCols.size() == 0) { + continue; + } + if (fullColumn == null || containsIgnoreCase(column,col)) { + list.add(prefixLeft + col + "=" + prefixRight + col); + } else { + list.add(prefixLeft + col + "=null"); + } + } + return StringUtils.join(list, ","); + } + + public String quoteTable(String table) { + String[] parts = table.split("\\."); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < parts.length; ++i) { + if (i != 0) { + sb.append("."); + } + sb.append(getStartQuote() + parts[i] + getEndQuote()); + } + return sb.toString(); + } + + + public String updateKeySql(Map> updateKey) { + List exprList = new ArrayList<>(); + for (Map.Entry> entry : updateKey.entrySet()) { + List colList = new ArrayList<>(); + for (String col : entry.getValue()) { + colList.add("T1." + quoteColumn(col) + "=T2." + quoteColumn(col)); + } + exprList.add(StringUtils.join(colList, " AND ")); + } + return StringUtils.join(exprList, " OR "); + } + + + public String makeValues(List column) { + StringBuilder sb = new StringBuilder("SELECT "); + for (int i = 0; i < column.size(); ++i) { + if (i != 0) { + sb.append(","); + } + sb.append("? " + quoteColumn(column.get(i))); + } + return sb.toString(); + } + + public boolean containsIgnoreCase(List l, String s) { + Iterator it = l.iterator(); + while (it.hasNext()) { + if (it.next().equalsIgnoreCase(s)) + return true; + } + return false; + } + public String quoteColumn(String column) { + return getStartQuote() + column + getEndQuote(); + } + + public String getStartQuote() { + return "\""; + } + + public String getEndQuote() { + return "\""; + } + + } diff --git a/sqlserver/sqlserver-sink/src/main/java/com/dtstack/flink/sql/sink/sqlserver/table/SqlserverSinkParser.java b/sqlserver/sqlserver-sink/src/main/java/com/dtstack/flink/sql/sink/sqlserver/table/SqlserverSinkParser.java index 90be66d66..a695d6c3b 100644 --- a/sqlserver/sqlserver-sink/src/main/java/com/dtstack/flink/sql/sink/sqlserver/table/SqlserverSinkParser.java +++ b/sqlserver/sqlserver-sink/src/main/java/com/dtstack/flink/sql/sink/sqlserver/table/SqlserverSinkParser.java @@ -1,4 +1,4 @@ -/* +/** * 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 @@ -17,9 +17,8 @@ */ package com.dtstack.flink.sql.sink.sqlserver.table; -import com.dtstack.flink.sql.core.rdb.JdbcCheckKeys; import com.dtstack.flink.sql.sink.rdb.table.RdbSinkParser; -import com.dtstack.flink.sql.table.AbstractTableInfo; +import com.dtstack.flink.sql.table.TableInfo; import java.util.Map; @@ -34,9 +33,8 @@ public class SqlserverSinkParser extends RdbSinkParser { private static final String CURR_TYPE = "sqlserver"; @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { - props.put(JdbcCheckKeys.DRIVER_NAME, "com.microsoft.sqlserver.jdbc.SQLServerDriver"); - AbstractTableInfo sqlserverTableInfo = super.getTableInfo(tableName, fieldsInfo, props); + public TableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { + TableInfo sqlserverTableInfo = super.getTableInfo(tableName, fieldsInfo, props); sqlserverTableInfo.setType(CURR_TYPE); return sqlserverTableInfo; } diff --git a/sqlserver/sqlserver-sink/src/test/java/com/dtstack/flink/sql/sink/sqlserver/SqlserverDialectTest.java b/sqlserver/sqlserver-sink/src/test/java/com/dtstack/flink/sql/sink/sqlserver/SqlserverDialectTest.java deleted file mode 100644 index 295d76175..000000000 --- a/sqlserver/sqlserver-sink/src/test/java/com/dtstack/flink/sql/sink/sqlserver/SqlserverDialectTest.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.dtstack.flink.sql.sink.sqlserver; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -public class SqlserverDialectTest { - - SqlserverDialect dialect; - - @Before - public void setUp() throws Exception { - dialect = new SqlserverDialect(); - } - - @Test - public void testEasyUtils() { - final String s = "jdbc:jtds://localhost:3306/foo_db"; - boolean r = dialect.canHandle(s); - Assert.assertTrue(r); - - String driver = dialect.defaultDriverName().get(); - Assert.assertTrue(driver.equals("net.sourceforge.jtds.jdbc.Driver")); - } - - @Test - public void testDialect() { - final String tableName = "table_foo"; - final String[] fieldNames = new String[] { - "id", - "name" - }; - final String[] uniqueKeyFields = new String[] { - "id", - }; - final String NORMAL_STMT = - "MERGE INTO \"table_foo\" T1 USING " + - "(SELECT ? \"id\", ? \"name\") T2 ON (T1.\"id\"=T2.\"id\") " + - "WHEN MATCHED THEN UPDATE SET \"T1\".\"name\" =ISNULL(\"T2\".\"name\",\"T1\".\"name\") " + - "WHEN NOT MATCHED THEN INSERT (\"id\",\"name\") VALUES (T2.\"id\",T2.\"name\");"; - - - String upsertStmt = dialect - .getUpsertStatement("", tableName, fieldNames, uniqueKeyFields, false) - .get(); - - Assert.assertTrue(NORMAL_STMT.equals(upsertStmt)); - - } - -} \ No newline at end of file diff --git a/sqlserver/sqlserver-sink/src/test/java/com/dtstack/flink/sql/sink/sqlserver/SqlserverSinkTest.java b/sqlserver/sqlserver-sink/src/test/java/com/dtstack/flink/sql/sink/sqlserver/SqlserverSinkTest.java deleted file mode 100644 index 2077bfc61..000000000 --- a/sqlserver/sqlserver-sink/src/test/java/com/dtstack/flink/sql/sink/sqlserver/SqlserverSinkTest.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.dtstack.flink.sql.sink.sqlserver; - -import com.dtstack.flink.sql.sink.rdb.dialect.JDBCDialect; -import com.dtstack.flink.sql.sink.rdb.format.JDBCUpsertOutputFormat; -import org.junit.Before; -import org.junit.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.powermock.api.support.membermodification.MemberModifier; -import java.util.Optional; -import static org.mockito.Mockito.when; - -public class SqlserverSinkTest { - - @Mock - JDBCDialect jdbcDialect; - - @InjectMocks - SqlserverSink sink = new SqlserverSink();; - @Before - public void setUp () { - MockitoAnnotations.initMocks(this); - } - - @Test - public void testGetOutputFormat() throws IllegalAccessException { - when(jdbcDialect.defaultDriverName()).thenReturn(Optional.of("dd")); - - MemberModifier.field(SqlserverSink.class, "dbUrl").set(sink, "foo"); - MemberModifier.field(SqlserverSink.class, "jdbcDialect").set(sink, jdbcDialect); - MemberModifier.field(SqlserverSink.class, "userName").set(sink, "foo"); - MemberModifier.field(SqlserverSink.class, "password").set(sink, "foo"); - MemberModifier.field(SqlserverSink.class, "tableName").set(sink, "foo"); - MemberModifier.field(SqlserverSink.class, "fieldNames").set(sink, new String[]{"foo", "bar"}); - - JDBCUpsertOutputFormat format = sink.getOutputFormat(); - } - -} \ No newline at end of file diff --git a/sqlserver/sqlserver-sink/src/test/java/com/dtstack/flink/sql/sink/sqlserver/table/SqlserverSinkParserTest.java b/sqlserver/sqlserver-sink/src/test/java/com/dtstack/flink/sql/sink/sqlserver/table/SqlserverSinkParserTest.java deleted file mode 100644 index ead714563..000000000 --- a/sqlserver/sqlserver-sink/src/test/java/com/dtstack/flink/sql/sink/sqlserver/table/SqlserverSinkParserTest.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.dtstack.flink.sql.sink.sqlserver.table; - -import com.dtstack.flink.sql.table.AbstractTableInfo; -import org.junit.Assert; -import org.junit.Test; -import java.util.HashMap; -import java.util.Map; - -public class SqlserverSinkParserTest { - -// @Test - public void getTableInfo() { - SqlserverSinkParser sinkParser = new SqlserverSinkParser(); - - final String tableName = "table_foo"; - final String fieldsInfo = "id INT, name VARCHAR"; - - Map props = new HashMap(); - props.put("url", "jdbc:mysql://foo:3306/db_foo"); - props.put("tablename", "table_foo"); - props.put("username", "foo"); - props.put("password", "foo"); - - AbstractTableInfo tableInfo= sinkParser.getTableInfo(tableName, fieldsInfo, props); - - final String NORMAL_TYPE = "sqlserver"; - final String table_type = tableInfo.getType(); - Assert.assertTrue(NORMAL_TYPE.equals(table_type)); - } - -} \ No newline at end of file diff --git a/tidb/pom.xml b/tidb/pom.xml deleted file mode 100644 index a84fadf3b..000000000 --- a/tidb/pom.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - flink.sql - com.dtstack.flink - 1.0-SNAPSHOT - ../pom.xml - - 4.0.0 - - sql.tidb - pom - - tidb-side - tidb-sink - - - - 5.1.46 - 1.0-SNAPSHOT - - - - - - com.dtstack.flink - sql.core - ${sql.core.version} - provided - - - - mysql - mysql-connector-java - ${tidb.connector.version} - - - - diff --git a/tidb/tidb-side/pom.xml b/tidb/tidb-side/pom.xml deleted file mode 100644 index 3f05dd093..000000000 --- a/tidb/tidb-side/pom.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - sql.tidb - com.dtstack.flink - 1.0-SNAPSHOT - ../pom.xml - - 4.0.0 - - sql.side.tidb - 1.0-SNAPSHOT - - tidb-all-side - tidb-side-core - tidb-async-side - - tidb-side - pom - - - 1.0-SNAPSHOT - - - - - com.dtstack.flink - sql.side.rdb - ${rdb.side.version} - - - - - - com.dtstack.flink - sql.side.rdb - ${rdb.side.version} - test-jar - test - - - - - - diff --git a/tidb/tidb-side/tidb-all-side/pom.xml b/tidb/tidb-side/tidb-all-side/pom.xml deleted file mode 100644 index 788f47c61..000000000 --- a/tidb/tidb-side/tidb-all-side/pom.xml +++ /dev/null @@ -1,91 +0,0 @@ - - - - sql.side.tidb - com.dtstack.flink - 1.0-SNAPSHOT - - 4.0.0 - - sql.side.all.tidb - tidb-all-side - jar - - - 1.0-SNAPSHOT - - - - - com.dtstack.flink - sql.side.tidb.core - ${sql.side.tidb.core.version} - - - - - - - - org.apache.maven.plugins - maven-shade-plugin - 1.4 - - - package - - shade - - - false - - - - - - - - *:* - - META-INF/*.SF - META-INF/*.DSA - META-INF/*.RSA - - - - - - - - - - maven-antrun-plugin - 1.2 - - - copy-resources - - package - - run - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/tidb/tidb-side/tidb-all-side/src/main/java/com/dtstack/flink/sql/side/tidb/TidbAllReqRow.java b/tidb/tidb-side/tidb-all-side/src/main/java/com/dtstack/flink/sql/side/tidb/TidbAllReqRow.java deleted file mode 100644 index c1529cd63..000000000 --- a/tidb/tidb-side/tidb-all-side/src/main/java/com/dtstack/flink/sql/side/tidb/TidbAllReqRow.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.tidb; - -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.rdb.all.AbstractRdbAllReqRow; -import com.dtstack.flink.sql.util.DtStringUtil; -import com.google.common.collect.Maps; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.SQLException; -import java.util.List; -import java.util.Map; - -/** - * @author tiezhu - * Date 2020/6/1 - * company www.dtstack.com - */ -public class TidbAllReqRow extends AbstractRdbAllReqRow { - - private static final Logger LOG = LoggerFactory.getLogger(TidbAllReqRow.class); - - private static final String TIDB_DRIVER = "com.mysql.jdbc.Driver"; - - public TidbAllReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { - super(new TidbAllSideInfo(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo)); - } - - @Override - public Connection getConn(String dbUrl, String userName, String password) { - try { - Class.forName(TIDB_DRIVER); - Map addParams = Maps.newHashMap(); - addParams.put("userCursorFetch", "true"); - String targetDbUrl = DtStringUtil.addJdbcParam(dbUrl, addParams, true); - return DriverManager.getConnection(targetDbUrl, userName, password); - } catch (ClassNotFoundException | SQLException e) { - LOG.error("TiDB get connect error!", e); - throw new RuntimeException("TiDB get connect error! ", e); - - } - } - - @Override - public int getFetchSize() { - return Integer.MIN_VALUE; - } -} diff --git a/tidb/tidb-side/tidb-all-side/src/main/java/com/dtstack/flink/sql/side/tidb/TidbAllSideInfo.java b/tidb/tidb-side/tidb-all-side/src/main/java/com/dtstack/flink/sql/side/tidb/TidbAllSideInfo.java deleted file mode 100644 index 2a7a39076..000000000 --- a/tidb/tidb-side/tidb-all-side/src/main/java/com/dtstack/flink/sql/side/tidb/TidbAllSideInfo.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.tidb; - -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.rdb.all.RdbAllSideInfo; -import org.apache.flink.api.java.typeutils.RowTypeInfo; - -import java.util.List; - -/** - * @author tiezhu - * Date 2020/6/1 - * company www.dtstack.com - */ -public class TidbAllSideInfo extends RdbAllSideInfo { - public TidbAllSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { - super(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); - } - - @Override - public String quoteIdentifier(String identifier) { - return "`" + identifier + "`"; - } -} diff --git a/tidb/tidb-side/tidb-all-side/src/test/java/com/dtstack/flink/sql/side/tidb/TidbAllReqRowTest.java b/tidb/tidb-side/tidb-all-side/src/test/java/com/dtstack/flink/sql/side/tidb/TidbAllReqRowTest.java deleted file mode 100644 index 5452a290c..000000000 --- a/tidb/tidb-side/tidb-all-side/src/test/java/com/dtstack/flink/sql/side/tidb/TidbAllReqRowTest.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.dtstack.flink.sql.side.tidb; - -import com.dtstack.flink.sql.side.rdb.all.RdbAllReqRowTestBase; - -public class TidbAllReqRowTest extends RdbAllReqRowTestBase { - - @Override - protected void init() { - clazz = TidbAllReqRow.class; - } - -} \ No newline at end of file diff --git a/tidb/tidb-side/tidb-async-side/pom.xml b/tidb/tidb-side/tidb-async-side/pom.xml deleted file mode 100644 index 06385639d..000000000 --- a/tidb/tidb-side/tidb-async-side/pom.xml +++ /dev/null @@ -1,92 +0,0 @@ - - - - sql.side.tidb - com.dtstack.flink - 1.0-SNAPSHOT - ../pom.xml - - 4.0.0 - - sql.side.async.tidb - 1.0-SNAPSHOT - tidb-async-side - jar - - - 1.0-SNAPSHOT - - - - - com.dtstack.flink - sql.side.tidb.core - ${sql.side.tidb.core.version} - - - - - - - org.apache.maven.plugins - maven-shade-plugin - 1.4 - - - package - - shade - - - false - - - - - - - - *:* - - META-INF/*.SF - META-INF/*.DSA - META-INF/*.RSA - - - - - - - - - - maven-antrun-plugin - 1.2 - - - copy-resources - - package - - run - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/tidb/tidb-side/tidb-async-side/src/main/java/com/dtstack/flink/sql/side/tidb/TidbAsyncReqRow.java b/tidb/tidb-side/tidb-async-side/src/main/java/com/dtstack/flink/sql/side/tidb/TidbAsyncReqRow.java deleted file mode 100644 index fe9420758..000000000 --- a/tidb/tidb-side/tidb-async-side/src/main/java/com/dtstack/flink/sql/side/tidb/TidbAsyncReqRow.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.tidb; - -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.rdb.async.RdbAsyncReqRow; -import com.dtstack.flink.sql.side.rdb.table.RdbSideTableInfo; -import io.vertx.core.json.JsonObject; -import org.apache.flink.api.java.typeutils.RowTypeInfo; -import org.apache.flink.configuration.Configuration; - -import java.util.List; - -/** - * @author tiezhu - * Date 2020/6/1 - * company www.dtstack.com - */ -public class TidbAsyncReqRow extends RdbAsyncReqRow { - - private final static String TIDB_DRIVER = "com.mysql.jdbc.Driver"; - - public TidbAsyncReqRow(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { - super(new TidbAsyncSideInfo(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo)); - } - - @Override - public void open(Configuration parameters) throws Exception { - super.open(parameters); - } - - @Override - public JsonObject buildJdbcConfig() { - JsonObject tidbClientConfig = new JsonObject(); - RdbSideTableInfo sideTableInfo = (RdbSideTableInfo) sideInfo.getSideTableInfo(); - tidbClientConfig.put("url", sideTableInfo.getUrl()) - .put("driver_class", TIDB_DRIVER) - .put("max_pool_size", sideTableInfo.getAsyncPoolSize()) - .put("user", sideTableInfo.getUserName()) - .put("password", sideTableInfo.getPassword()) - .put("provider_class", DT_PROVIDER_CLASS) - .put("preferred_test_query", PREFERRED_TEST_QUERY_SQL) - .put("test_connection_on_checkin", DEFAULT_TEST_CONNECTION_ON_CHECKIN) - .put("idle_connection_test_period", DEFAULT_IDLE_CONNECTION_TEST_PEROID); - - return tidbClientConfig; - } -} diff --git a/tidb/tidb-side/tidb-async-side/src/main/java/com/dtstack/flink/sql/side/tidb/TidbAsyncSideInfo.java b/tidb/tidb-side/tidb-async-side/src/main/java/com/dtstack/flink/sql/side/tidb/TidbAsyncSideInfo.java deleted file mode 100644 index f672f0b83..000000000 --- a/tidb/tidb-side/tidb-async-side/src/main/java/com/dtstack/flink/sql/side/tidb/TidbAsyncSideInfo.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.tidb; - -import com.dtstack.flink.sql.side.AbstractSideTableInfo; -import com.dtstack.flink.sql.side.FieldInfo; -import com.dtstack.flink.sql.side.JoinInfo; -import com.dtstack.flink.sql.side.rdb.async.RdbAsyncSideInfo; -import org.apache.flink.api.java.typeutils.RowTypeInfo; - -import java.util.List; - -/** - * @author tiezhu - * Date 2020/6/1 - * company www.dtstack.com - */ -public class TidbAsyncSideInfo extends RdbAsyncSideInfo { - - public TidbAsyncSideInfo(RowTypeInfo rowTypeInfo, JoinInfo joinInfo, List outFieldInfoList, AbstractSideTableInfo sideTableInfo) { - super(rowTypeInfo, joinInfo, outFieldInfoList, sideTableInfo); - } - - @Override - public String quoteIdentifier(String identifier) { - return "`" + identifier + "`"; - } -} diff --git a/tidb/tidb-side/tidb-async-side/src/test/java/com/dtstack/flink/sql/side/tidb/TidbAsyncReqRowTest.java b/tidb/tidb-side/tidb-async-side/src/test/java/com/dtstack/flink/sql/side/tidb/TidbAsyncReqRowTest.java deleted file mode 100644 index 2c1e441c3..000000000 --- a/tidb/tidb-side/tidb-async-side/src/test/java/com/dtstack/flink/sql/side/tidb/TidbAsyncReqRowTest.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.dtstack.flink.sql.side.tidb; - -import com.dtstack.flink.sql.side.rdb.async.RdbAsyncReqRowTestBase; - -public class TidbAsyncReqRowTest extends RdbAsyncReqRowTestBase { - - @Override - protected void init() { - clazz = TidbAsyncReqRow.class; - } - -} \ No newline at end of file diff --git a/tidb/tidb-side/tidb-side-core/pom.xml b/tidb/tidb-side/tidb-side-core/pom.xml deleted file mode 100644 index 201dc9198..000000000 --- a/tidb/tidb-side/tidb-side-core/pom.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - sql.side.tidb - com.dtstack.flink - 1.0-SNAPSHOT - - 4.0.0 - - sql.side.tidb.core - jar - tidb-side-core - 1.0-SNAPSHOT - \ No newline at end of file diff --git a/tidb/tidb-side/tidb-side-core/src/main/java/com/dtstack/flink/sql/side/tidb/table/TidbSideParser.java b/tidb/tidb-side/tidb-side-core/src/main/java/com/dtstack/flink/sql/side/tidb/table/TidbSideParser.java deleted file mode 100644 index 4d5088738..000000000 --- a/tidb/tidb-side/tidb-side-core/src/main/java/com/dtstack/flink/sql/side/tidb/table/TidbSideParser.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.side.tidb.table; - -import com.dtstack.flink.sql.core.rdb.JdbcCheckKeys; -import com.dtstack.flink.sql.side.rdb.table.RdbSideParser; -import com.dtstack.flink.sql.table.AbstractTableInfo; - -import java.util.Map; - -/** - * @author tiezhu - * Date 2020/6/1 - * company www.dtstack.com - */ -public class TidbSideParser extends RdbSideParser { - - private static final String CURRENT_TYPE = "tidb"; - - @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { - props.put(JdbcCheckKeys.DRIVER_NAME, "com.mysql.jdbc.Driver"); - AbstractTableInfo tableInfo = super.getTableInfo(tableName, fieldsInfo, props); - tableInfo.setType(CURRENT_TYPE); - return tableInfo; - } -} diff --git a/tidb/tidb-side/tidb-side-core/src/test/java/com/dtstack/flink/sql/side/tidb/table/TidbSideParserTest.java b/tidb/tidb-side/tidb-side-core/src/test/java/com/dtstack/flink/sql/side/tidb/table/TidbSideParserTest.java deleted file mode 100644 index 2850903d3..000000000 --- a/tidb/tidb-side/tidb-side-core/src/test/java/com/dtstack/flink/sql/side/tidb/table/TidbSideParserTest.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.dtstack.flink.sql.side.tidb.table; - -import com.dtstack.flink.sql.table.AbstractTableInfo; -import org.junit.Assert; -import org.junit.Test; - -import java.util.HashMap; -import java.util.Map; - -public class TidbSideParserTest { - -// @Test - public void getTableInfo() { - TidbSideParser sideParser = new TidbSideParser(); - - final String tableName = "table_foo"; - final String fieldsInfo = "id INT, name VARCHAR, PRIMARY KEY (id)"; - - Map props = new HashMap(); - props.put("url", "jdbc:mysql://foo:3306/db_foo"); - props.put("tablename", "table_foo"); - props.put("username", "foo"); - props.put("password", "foo"); - - AbstractTableInfo tableInfo= sideParser.getTableInfo(tableName, fieldsInfo, props); - - final String NORMAL_TYPE = "tidb"; - final String table_type = tableInfo.getType(); - Assert.assertTrue(NORMAL_TYPE.equals(table_type)); - } - -} \ No newline at end of file diff --git a/tidb/tidb-sink/pom.xml b/tidb/tidb-sink/pom.xml deleted file mode 100644 index d2bdd68ed..000000000 --- a/tidb/tidb-sink/pom.xml +++ /dev/null @@ -1,93 +0,0 @@ - - - - sql.tidb - com.dtstack.flink - 1.0-SNAPSHOT - ../pom.xml - - 4.0.0 - - sql.sink.tidb - tidb-sink - jar - 1.0-SNAPSHOT - - - 1.0-SNAPSHOT - - - - - com.dtstack.flink - sql.sink.rdb - ${sql.sink.rdb.version} - - - - - - - org.apache.maven.plugins - maven-shade-plugin - 1.4 - - - package - - shade - - - false - - - - - - - - *:* - - META-INF/*.SF - META-INF/*.DSA - META-INF/*.RSA - - - - - - - - - - maven-antrun-plugin - 1.2 - - - copy-resources - - package - - run - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/tidb/tidb-sink/src/main/java/com/dtstack/flink/sql/sink/tidb/TidbDialect.java b/tidb/tidb-sink/src/main/java/com/dtstack/flink/sql/sink/tidb/TidbDialect.java deleted file mode 100644 index 3a7770ede..000000000 --- a/tidb/tidb-sink/src/main/java/com/dtstack/flink/sql/sink/tidb/TidbDialect.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.tidb; - -import com.dtstack.flink.sql.sink.rdb.dialect.JDBCDialect; - -import java.util.Arrays; -import java.util.Optional; -import java.util.stream.Collectors; - -/** - * @author tiezhu - * Date 2020/6/1 - * company www.dtstack.com - */ -public class TidbDialect implements JDBCDialect { - private static final long serialVersionUID = 1L; - - @Override - public boolean canHandle(String url) { - return url.startsWith("jdbc:mysql:"); - } - - @Override - public Optional defaultDriverName() { - return Optional.of("com.mysql.jdbc.Driver"); - } - - @Override - public String quoteIdentifier(String identifier) { - return "`" + identifier + "`"; - } - - /** - * 根据ALLReplace参数,选择使用replace语句还是ON DUPLICATE KEY UPDATE 语句 - */ - @Override - public Optional getUpsertStatement(String schema, String tableName, String[] fieldNames, String[] uniqueKeyFields, boolean allReplace) { - return allReplace ? buildReplaceIntoStatement(tableName, fieldNames) : buildDuplicateUpsertStatement(tableName, fieldNames); - } - - public Optional buildDuplicateUpsertStatement(String tableName, String[] fieldNames) { - String updateClause = Arrays.stream(fieldNames).map(f -> quoteIdentifier(f) + "=IFNULL(VALUES(" + quoteIdentifier(f) + ")," + quoteIdentifier(f) + ")") - .collect(Collectors.joining(", ")); - return Optional.of(getInsertIntoStatement("", tableName, fieldNames, null) + - " ON DUPLICATE KEY UPDATE " + updateClause); - } - - public Optional buildReplaceIntoStatement(String tableName, String[] fieldNames) { - String columns = Arrays.stream(fieldNames) - .map(this::quoteIdentifier) - .collect(Collectors.joining(", ")); - String placeholders = Arrays.stream(fieldNames) - .map(f -> "?") - .collect(Collectors.joining(", ")); - return Optional.of("REPLACE INTO " + quoteIdentifier(tableName) + - "(" + columns + ")" + " VALUES (" + placeholders + ")"); - } -} diff --git a/tidb/tidb-sink/src/main/java/com/dtstack/flink/sql/sink/tidb/TidbSink.java b/tidb/tidb-sink/src/main/java/com/dtstack/flink/sql/sink/tidb/TidbSink.java deleted file mode 100644 index 8f1e79134..000000000 --- a/tidb/tidb-sink/src/main/java/com/dtstack/flink/sql/sink/tidb/TidbSink.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.tidb; - -import com.dtstack.flink.sql.sink.IStreamSinkGener; -import com.dtstack.flink.sql.sink.rdb.AbstractRdbSink; -import com.dtstack.flink.sql.sink.rdb.JDBCOptions; -import com.dtstack.flink.sql.sink.rdb.format.JDBCUpsertOutputFormat; - -/** - * @author tiezhu - * Date 2020/6/1 - * company www.dtstack.com - */ -public class TidbSink extends AbstractRdbSink implements IStreamSinkGener { - - public TidbSink() { - super(new TidbDialect()); - } - - @Override - public JDBCUpsertOutputFormat getOutputFormat() { - JDBCOptions jdbcOptions = JDBCOptions.builder() - .setDbUrl(dbUrl) - .setDialect(jdbcDialect) - .setUsername(userName) - .setPassword(password) - .setTableName(tableName) - .build(); - - return JDBCUpsertOutputFormat.builder() - .setOptions(jdbcOptions) - .setFieldNames(fieldNames) - .setFlushMaxSize(batchNum) - .setFlushIntervalMills(batchWaitInterval) - .setFieldTypes(sqlTypes) - .setKeyFields(primaryKeys) - .setAllReplace(allReplace) - .setUpdateMode(updateMode) - .setErrorLimit(errorLimit) - .build(); - } -} diff --git a/tidb/tidb-sink/src/main/java/com/dtstack/flink/sql/sink/tidb/table/TidbSinkParser.java b/tidb/tidb-sink/src/main/java/com/dtstack/flink/sql/sink/tidb/table/TidbSinkParser.java deleted file mode 100644 index 4f7001e85..000000000 --- a/tidb/tidb-sink/src/main/java/com/dtstack/flink/sql/sink/tidb/table/TidbSinkParser.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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 com.dtstack.flink.sql.sink.tidb.table; - -import com.dtstack.flink.sql.core.rdb.JdbcCheckKeys; -import com.dtstack.flink.sql.sink.rdb.table.RdbSinkParser; -import com.dtstack.flink.sql.table.AbstractTableInfo; - -import java.util.Map; - -/** - * @author tiezhu - * Date 2020/6/1 - * company www.dtstack.com - */ -public class TidbSinkParser extends RdbSinkParser { - - private static final String CURRENT_TYPE = "tidb"; - - @Override - public AbstractTableInfo getTableInfo(String tableName, String fieldsInfo, Map props) { - props.put(JdbcCheckKeys.DRIVER_NAME, "com.mysql.jdbc.Driver"); - AbstractTableInfo tableInfo = super.getTableInfo(tableName, fieldsInfo, props); - tableInfo.setType(CURRENT_TYPE); - return tableInfo; - } -} diff --git a/tidb/tidb-sink/src/test/java/com/dtstack/flink/sql/sink/tidb/TidbDialectTest.java b/tidb/tidb-sink/src/test/java/com/dtstack/flink/sql/sink/tidb/TidbDialectTest.java deleted file mode 100644 index 5096302ae..000000000 --- a/tidb/tidb-sink/src/test/java/com/dtstack/flink/sql/sink/tidb/TidbDialectTest.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.dtstack.flink.sql.sink.tidb; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -public class TidbDialectTest { - - TidbDialect dialect; - - @Before - public void setUp() { - dialect = new TidbDialect(); - } - - @Test - public void testEasyUtils() { - final String s = "jdbc:mysql://localhost:3306/foo_db"; - boolean r = dialect.canHandle(s); - Assert.assertTrue(r); - - String driver = dialect.defaultDriverName().get(); - Assert.assertTrue(driver.equals("com.mysql.jdbc.Driver")); - - final String foo = "foo"; - final String NORMAL_QUOTE = "`foo`"; - String strWithQuote = dialect.quoteIdentifier(foo); - - Assert.assertTrue(strWithQuote.equals(NORMAL_QUOTE)); - } - - @Test - public void testDialect() { - final String tableName = "table_foo"; - final String[] fieldNames = new String[] { - "id", - "name" - }; - final String NORMAL_REPELACE_STMT = - "REPLACE INTO `table_foo`(`id`, `name`) VALUES (?, ?)"; - final String NORMAL_UPSERT_STMT = - "INSERT INTO `table_foo`(`id`, `name`) VALUES (?, ?) " + - "ON DUPLICATE KEY UPDATE `id`=IFNULL(VALUES(`id`),`id`), " + - "`name`=IFNULL(VALUES(`name`),`name`)"; - - String replaceStmt = dialect.buildReplaceIntoStatement(tableName, fieldNames) - .get(); - String upsertStmt = dialect.buildDuplicateUpsertStatement(tableName, fieldNames) - .get(); - - Assert.assertTrue(NORMAL_REPELACE_STMT.equals(replaceStmt)); - Assert.assertTrue(NORMAL_UPSERT_STMT.equals(upsertStmt)); - - String upsertStmtWithReplace = dialect - .getUpsertStatement("", tableName, fieldNames, null, true) - .get(); - String upsertStmtWithoutReplace = dialect - .getUpsertStatement("", tableName, fieldNames, null, false) - .get(); - - Assert.assertTrue(replaceStmt.equals(upsertStmtWithReplace)); - Assert.assertTrue(upsertStmt.equals(upsertStmtWithoutReplace)); - } - -} \ No newline at end of file diff --git a/tidb/tidb-sink/src/test/java/com/dtstack/flink/sql/sink/tidb/TidbSinkTest.java b/tidb/tidb-sink/src/test/java/com/dtstack/flink/sql/sink/tidb/TidbSinkTest.java deleted file mode 100644 index 5d8334fac..000000000 --- a/tidb/tidb-sink/src/test/java/com/dtstack/flink/sql/sink/tidb/TidbSinkTest.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.dtstack.flink.sql.sink.tidb; - -import com.dtstack.flink.sql.sink.rdb.dialect.JDBCDialect; -import com.dtstack.flink.sql.sink.rdb.format.JDBCUpsertOutputFormat; -import org.junit.Before; -import org.junit.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.powermock.api.support.membermodification.MemberModifier; - -import java.util.Optional; - -import static org.mockito.Mockito.when; - -public class TidbSinkTest { - - @Mock - JDBCDialect jdbcDialect; - - @InjectMocks - TidbSink sink = new TidbSink();; - @Before - public void setUp () { - MockitoAnnotations.initMocks(this); - } - - @Test - public void testGetOutputFormat() throws IllegalAccessException { - when(jdbcDialect.defaultDriverName()).thenReturn(Optional.of("dd")); - - MemberModifier.field(TidbSink.class, "dbUrl").set(sink, "foo"); - MemberModifier.field(TidbSink.class, "jdbcDialect").set(sink, jdbcDialect); - MemberModifier.field(TidbSink.class, "userName").set(sink, "foo"); - MemberModifier.field(TidbSink.class, "password").set(sink, "foo"); - MemberModifier.field(TidbSink.class, "tableName").set(sink, "foo"); - MemberModifier.field(TidbSink.class, "fieldNames").set(sink, new String[]{"foo", "bar"}); - - JDBCUpsertOutputFormat format = sink.getOutputFormat(); - } - -} \ No newline at end of file diff --git a/tidb/tidb-sink/src/test/java/com/dtstack/flink/sql/sink/tidb/table/TidbSinkParserTest.java b/tidb/tidb-sink/src/test/java/com/dtstack/flink/sql/sink/tidb/table/TidbSinkParserTest.java deleted file mode 100644 index 7e56e3aba..000000000 --- a/tidb/tidb-sink/src/test/java/com/dtstack/flink/sql/sink/tidb/table/TidbSinkParserTest.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.dtstack.flink.sql.sink.tidb.table; - -import com.dtstack.flink.sql.table.AbstractTableInfo; -import org.junit.Assert; -import org.junit.Test; - -import java.util.HashMap; -import java.util.Map; - -public class TidbSinkParserTest { - -// @Test - public void getTableInfo() { - TidbSinkParser parser = new TidbSinkParser(); - - final String tableName = "table_foo"; - final String fieldsInfo = "id INT, name VARCHAR"; - - Map props = new HashMap(); - props.put("url", "jdbc:mysql://foo:3306/db_foo"); - props.put("tablename", "table_foo"); - props.put("username", "foo"); - props.put("password", "foo"); - - AbstractTableInfo tableInfo= parser.getTableInfo(tableName, fieldsInfo, props); - - final String NORMAL_TYPE = "tidb"; - final String table_type = tableInfo.getType(); - Assert.assertTrue(NORMAL_TYPE.equals(table_type)); - } - -} \ No newline at end of file