From bec678a8b9c2458e2be2b37fbd758c7b7ae64a3c Mon Sep 17 00:00:00 2001
From: xiangzihao <460888207@qq.com>
Date: Wed, 20 Nov 2024 09:20:41 +0800
Subject: [PATCH] [DSIP-78][Data Quality] Remove data quality module (#16794)
---
.github/CODEOWNERS | 1 -
.github/actions/labeler/labeler.yml | 1 -
config/plugins_config | 1 -
deploy/kubernetes/dolphinscheduler/README.md | 1 -
.../kubernetes/dolphinscheduler/values.yaml | 4 -
docs/configs/docsdev.js | 8 -
docs/docs/en/architecture/configuration.md | 1 -
docs/docs/en/guide/data-quality.md | 313 -----
docs/docs/en/guide/upgrade/incompatible.md | 3 +-
docs/docs/zh/architecture/configuration.md | 1 -
docs/docs/zh/guide/data-quality.md | 357 -----
docs/docs/zh/guide/upgrade/incompatible.md | 7 +-
docs/img/tasks/demo/custom_sql_check.png | Bin 20259 -> 0 bytes
docs/img/tasks/demo/enumeration_check.png | Bin 20145 -> 0 bytes
docs/img/tasks/demo/field_length_check.png | Bin 18951 -> 0 bytes
.../tasks/demo/multi_table_accuracy_check.png | Bin 21355 -> 0 bytes
.../demo/multi_table_comparison_check.png | Bin 20590 -> 0 bytes
docs/img/tasks/demo/null_check.png | Bin 21491 -> 0 bytes
docs/img/tasks/demo/regexp_check.png | Bin 20379 -> 0 bytes
docs/img/tasks/demo/result.png | Bin 63652 -> 0 bytes
docs/img/tasks/demo/rule_detail.png | Bin 74110 -> 0 bytes
docs/img/tasks/demo/rule_list.png | Bin 55713 -> 0 bytes
docs/img/tasks/demo/table_count_check.png | Bin 20701 -> 0 bytes
docs/img/tasks/demo/timeliness_check.png | Bin 21350 -> 0 bytes
docs/img/tasks/demo/uniqueness_check.png | Bin 20438 -> 0 bytes
.../docker/file-manage/common.properties | 9 +-
dolphinscheduler-api/pom.xml | 5 -
.../DynamicTaskTypeConfiguration.java | 6 +-
.../configuration/TaskTypeConfiguration.java | 3 -
.../api/controller/DataQualityController.java | 195 ---
.../api/dto/RuleDefinition.java | 63 -
.../dolphinscheduler/api/enums/Status.java | 6 -
.../api/service/DqExecuteResultService.java | 36 -
.../api/service/DqRuleService.java | 44 -
.../impl/DqExecuteResultServiceImpl.java | 101 --
.../api/service/impl/DqRuleServiceImpl.java | 314 -----
.../service/impl/TaskInstanceServiceImpl.java | 5 -
.../resources/dynamic-task-type-config.yaml | 2 -
.../main/resources/i18n/messages.properties | 8 -
.../resources/i18n/messages_en_US.properties | 8 -
.../resources/i18n/messages_zh_CN.properties | 8 -
.../src/main/resources/task-type-config.yaml | 2 -
.../controller/DataQualityControllerTest.java | 164 ---
.../api/service/DqRuleServiceTest.java | 249 ----
...kflowInstanceExecuteResultServiceTest.java | 108 --
dolphinscheduler-bom/pom.xml | 49 -
.../common/constants/Constants.java | 9 -
.../common/enums/AuthorizationType.java | 14 +-
.../src/main/resources/common.properties | 7 -
.../log/SensitiveDataConverterTest.java | 28 -
.../src/test/resources/common.properties | 7 -
.../src/test/resources/sql/mysql_dml.sql | 44 -
.../dao/entity/DqComparisonType.java | 74 -
.../dao/entity/DqExecuteResult.java | 108 --
.../entity/DqExecuteResultAlertContent.java | 258 ----
.../dolphinscheduler/dao/entity/DqRule.java | 74 -
.../dao/entity/DqRuleExecuteSql.java | 76 -
.../dao/entity/DqRuleInputEntry.java | 130 --
.../dao/entity/DqTaskStatisticsValue.java | 72 -
.../dao/mapper/DqComparisonTypeMapper.java | 29 -
.../dao/mapper/DqExecuteResultMapper.java | 62 -
.../dao/mapper/DqRuleExecuteSqlMapper.java | 39 -
.../dao/mapper/DqRuleInputEntryMapper.java | 39 -
.../dao/mapper/DqRuleMapper.java | 48 -
.../mapper/DqTaskStatisticsValueMapper.java | 29 -
.../dao/repository/DqExecuteResultDao.java | 25 -
.../impl/DqExecuteResultDaoImpl.java | 42 -
.../dao/utils/DqRuleUtils.java | 58 -
.../dao/mapper/DqComparisonTypeMapper.xml | 22 -
.../dao/mapper/DqExecuteResultMapper.xml | 111 --
.../dao/mapper/DqExecuteSqlMapper.xml | 27 -
.../dao/mapper/DqRuleInputEntryMapper.xml | 43 -
.../dao/mapper/DqRuleMapper.xml | 37 -
.../mapper/DqTaskStatisticsValueMapper.xml | 22 -
.../resources/sql/dolphinscheduler_h2.sql | 819 -----------
.../resources/sql/dolphinscheduler_mysql.sql | 821 -----------
.../sql/dolphinscheduler_postgresql.sql | 812 -----------
.../mysql/dolphinscheduler_dml.sql | 8 -
.../postgresql/dolphinscheduler_dml.sql | 8 -
.../mysql/dolphinscheduler_ddl.sql | 20 +
.../postgresql/dolphinscheduler_ddl.sql | 21 +
.../mapper/DqRuleInputEntryMapperTest.java | 61 -
dolphinscheduler-data-quality/pom.xml | 201 ---
.../data/quality/Constants.java | 67 -
.../data/quality/DataQualityApplication.java | 80 --
.../data/quality/config/BaseConfig.java | 66 -
.../data/quality/config/Config.java | 94 --
.../config/DataQualityConfiguration.java | 133 --
.../data/quality/config/EnvConfig.java | 34 -
.../data/quality/config/IConfig.java | 29 -
.../data/quality/config/ReaderConfig.java | 33 -
.../quality/config/TransformerConfig.java | 33 -
.../data/quality/config/ValidateResult.java | 46 -
.../data/quality/config/WriterConfig.java | 33 -
.../quality/context/DataQualityContext.java | 67 -
.../data/quality/enums/ReaderType.java | 41 -
.../data/quality/enums/TransformerType.java | 39 -
.../data/quality/enums/WriterType.java | 41 -
.../exception/ConfigRuntimeException.java | 40 -
.../exception/DataQualityException.java | 57 -
.../data/quality/execution/Execution.java | 36 -
.../execution/SparkBatchExecution.java | 134 --
.../execution/SparkRuntimeEnvironment.java | 75 -
.../data/quality/flow/Component.java | 56 -
.../data/quality/flow/batch/BatchReader.java | 37 -
.../quality/flow/batch/BatchTransformer.java | 38 -
.../data/quality/flow/batch/BatchWriter.java | 37 -
.../quality/flow/batch/reader/HiveReader.java | 69 -
.../quality/flow/batch/reader/JdbcReader.java | 101 --
.../flow/batch/reader/ReaderFactory.java | 78 --
.../batch/transformer/SqlTransformer.java | 62 -
.../batch/transformer/TransformerFactory.java | 74 -
.../quality/flow/batch/writer/JdbcWriter.java | 93 --
.../flow/batch/writer/WriterFactory.java | 83 --
.../batch/writer/file/BaseFileWriter.java | 132 --
.../batch/writer/file/HdfsFileWriter.java | 47 -
.../batch/writer/file/LocalFileWriter.java | 47 -
.../data/quality/utils/ConfigUtils.java | 56 -
.../data/quality/utils/JsonUtils.java | 73 -
.../data/quality/utils/ParserUtils.java | 58 -
.../src/main/resources/log4j.properties | 22 -
.../quality/SparkApplicationTestBase.java | 47 -
.../ConfigurationParserTest.java | 62 -
.../data/quality/flow/FlowTestBase.java | 45 -
.../quality/flow/reader/JdbcReaderTest.java | 99 --
.../flow/reader/ReaderFactoryTest.java | 70 -
.../quality/flow/writer/JdbcWriterTest.java | 101 --
.../flow/writer/WriterFactoryTest.java | 54 -
.../data/quality/utils/ConfigUtilsTest.java | 46 -
.../src/test/resources/logback.xml | 21 -
.../api/constants/DataSourceConstants.java | 7 -
.../datasource/api/utils/CommonUtils.java | 84 --
dolphinscheduler-dist/pom.xml | 5 -
.../e2e/pages/common/NavBarPage.java | 3 -
.../docker/file-manage/common.properties | 9 +-
.../runner/TaskExecutionContextFactory.java | 235 ----
.../service/alert/WorkflowAlertManager.java | 105 --
.../service/process/ProcessService.java | 12 -
.../service/process/ProcessServiceImpl.java | 49 -
.../service/process/ProcessServiceTest.java | 120 --
.../dolphinscheduler-task-all/pom.xml | 6 -
.../api/DataQualityTaskExecutionContext.java | 291 ----
.../plugin/task/api/TaskExecutionContext.java | 2 -
.../task/api/enums/dp/DqFailureStrategy.java | 65 -
.../plugin/task/api/enums/dp/DqTaskState.java | 70 -
.../dataquality/DataQualityParameters.java | 100 --
.../dataquality/spark/ProgramType.java | 31 -
.../dataquality/spark/SparkConstants.java | 73 -
.../dataquality/spark/SparkParameters.java | 228 ---
.../task/api/utils/DataQualityConstants.java | 104 --
.../plugin/task/api/utils/JdbcUrlParser.java | 133 --
.../api/enums/dp/DqFailureStrategyTest.java | 42 -
.../task/api/enums/dp/DqTaskStateTest.java | 45 -
.../task/api/utils/JdbcUrlParserTest.java | 54 -
.../src/test/resources/common.properties | 9 +-
.../dolphinscheduler-task-dataquality/pom.xml | 84 --
.../plugin/task/dq/DataQualityTask.java | 200 ---
.../task/dq/DataQualityTaskChannel.java | 39 -
.../dq/DataQualityTaskChannelFactory.java | 37 -
.../dq/exception/DataQualityException.java | 45 -
.../plugin/task/dq/rule/RuleManager.java | 137 --
.../task/dq/rule/entity/DqRuleExecuteSql.java | 62 -
.../task/dq/rule/entity/DqRuleInputEntry.java | 105 --
.../task/dq/rule/parameter/BaseConfig.java | 59 -
.../parameter/DataQualityConfiguration.java | 122 --
.../task/dq/rule/parameter/EnvConfig.java | 34 -
.../task/dq/rule/parser/IRuleParser.java | 33 -
.../task/dq/rule/parser/MappingColumn.java | 61 -
.../parser/MultiTableAccuracyRuleParser.java | 93 --
.../MultiTableComparisonRuleParser.java | 59 -
.../SingleTableCustomSqlRuleParser.java | 74 -
.../dq/rule/parser/SingleTableRuleParser.java | 82 --
.../plugin/task/dq/utils/Md5Utils.java | 47 -
.../plugin/task/dq/utils/RuleParserUtils.java | 592 --------
.../plugin/task/dq/utils/SparkArgsUtils.java | 137 --
.../task/dq/DataQualityParameterTest.java | 131 --
.../plugin/task/dq/DataQualityTaskTest.java | 1241 -----------------
.../plugin/task/dq/utils/Md5UtilsTest.java | 29 -
dolphinscheduler-task-plugin/pom.xml | 1 -
.../public/images/task-icons/data_quality.png | Bin 1086 -> 0 bytes
.../images/task-icons/data_quality_hover.png | Bin 1054 -> 0 bytes
.../src/layouts/content/use-dataList.ts | 21 -
.../src/locales/en_US/data-quality.ts | 114 --
.../src/locales/en_US/index.ts | 2 -
dolphinscheduler-ui/src/locales/en_US/menu.ts | 1 -
.../src/locales/en_US/project.ts | 1 -
.../src/locales/zh_CN/data-quality.ts | 113 --
.../src/locales/zh_CN/index.ts | 2 -
dolphinscheduler-ui/src/locales/zh_CN/menu.ts | 1 -
.../src/locales/zh_CN/project.ts | 1 -
.../src/router/modules/data-quality.ts | 55 -
dolphinscheduler-ui/src/router/routes.ts | 2 -
.../src/service/modules/data-quality/index.ts | 62 -
.../src/service/modules/data-quality/types.ts | 94 --
.../src/store/project/task-type.ts | 4 -
.../src/store/project/types.ts | 1 -
.../rule/components/rule-modal.tsx | 100 --
.../rule/components/table-action.tsx | 74 -
.../src/views/data-quality/rule/index.tsx | 157 ---
.../src/views/data-quality/rule/use-table.ts | 152 --
.../views/data-quality/task-result/index.tsx | 186 ---
.../data-quality/task-result/use-table.ts | 290 ----
.../task/components/node/fields/index.ts | 1 -
.../task/components/node/fields/use-rules.ts | 304 ----
.../task/components/node/format-data.ts | 43 -
.../task/components/node/tasks/index.ts | 2 -
.../components/node/tasks/use-data-quality.ts | 107 --
.../projects/task/constants/task-type.ts | 5 -
.../workflow/components/dag/dag-sidebar.tsx | 3 -
.../workflow/components/dag/dag.module.scss | 6 -
pom.xml | 7 -
211 files changed, 54 insertions(+), 16517 deletions(-)
delete mode 100644 docs/docs/en/guide/data-quality.md
delete mode 100644 docs/docs/zh/guide/data-quality.md
delete mode 100644 docs/img/tasks/demo/custom_sql_check.png
delete mode 100644 docs/img/tasks/demo/enumeration_check.png
delete mode 100644 docs/img/tasks/demo/field_length_check.png
delete mode 100644 docs/img/tasks/demo/multi_table_accuracy_check.png
delete mode 100644 docs/img/tasks/demo/multi_table_comparison_check.png
delete mode 100644 docs/img/tasks/demo/null_check.png
delete mode 100644 docs/img/tasks/demo/regexp_check.png
delete mode 100644 docs/img/tasks/demo/result.png
delete mode 100644 docs/img/tasks/demo/rule_detail.png
delete mode 100644 docs/img/tasks/demo/rule_list.png
delete mode 100644 docs/img/tasks/demo/table_count_check.png
delete mode 100644 docs/img/tasks/demo/timeliness_check.png
delete mode 100644 docs/img/tasks/demo/uniqueness_check.png
delete mode 100644 dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/DataQualityController.java
delete mode 100644 dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/dto/RuleDefinition.java
delete mode 100644 dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/DqExecuteResultService.java
delete mode 100644 dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/DqRuleService.java
delete mode 100644 dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/DqExecuteResultServiceImpl.java
delete mode 100644 dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/DqRuleServiceImpl.java
delete mode 100644 dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/DataQualityControllerTest.java
delete mode 100644 dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/DqRuleServiceTest.java
delete mode 100644 dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/DqWorkflowInstanceExecuteResultServiceTest.java
delete mode 100644 dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/DqComparisonType.java
delete mode 100644 dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/DqExecuteResult.java
delete mode 100644 dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/DqExecuteResultAlertContent.java
delete mode 100644 dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/DqRule.java
delete mode 100644 dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/DqRuleExecuteSql.java
delete mode 100644 dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/DqRuleInputEntry.java
delete mode 100644 dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/DqTaskStatisticsValue.java
delete mode 100644 dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/DqComparisonTypeMapper.java
delete mode 100644 dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/DqExecuteResultMapper.java
delete mode 100644 dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/DqRuleExecuteSqlMapper.java
delete mode 100644 dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/DqRuleInputEntryMapper.java
delete mode 100644 dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/DqRuleMapper.java
delete mode 100644 dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/DqTaskStatisticsValueMapper.java
delete mode 100644 dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/repository/DqExecuteResultDao.java
delete mode 100644 dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/repository/impl/DqExecuteResultDaoImpl.java
delete mode 100644 dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/utils/DqRuleUtils.java
delete mode 100644 dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/DqComparisonTypeMapper.xml
delete mode 100644 dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/DqExecuteResultMapper.xml
delete mode 100644 dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/DqExecuteSqlMapper.xml
delete mode 100644 dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/DqRuleInputEntryMapper.xml
delete mode 100644 dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/DqRuleMapper.xml
delete mode 100644 dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/DqTaskStatisticsValueMapper.xml
delete mode 100644 dolphinscheduler-dao/src/test/java/org/apache/dolphinscheduler/dao/mapper/DqRuleInputEntryMapperTest.java
delete mode 100644 dolphinscheduler-data-quality/pom.xml
delete mode 100644 dolphinscheduler-data-quality/src/main/java/org/apache/dolphinscheduler/data/quality/Constants.java
delete mode 100644 dolphinscheduler-data-quality/src/main/java/org/apache/dolphinscheduler/data/quality/DataQualityApplication.java
delete mode 100644 dolphinscheduler-data-quality/src/main/java/org/apache/dolphinscheduler/data/quality/config/BaseConfig.java
delete mode 100644 dolphinscheduler-data-quality/src/main/java/org/apache/dolphinscheduler/data/quality/config/Config.java
delete mode 100644 dolphinscheduler-data-quality/src/main/java/org/apache/dolphinscheduler/data/quality/config/DataQualityConfiguration.java
delete mode 100644 dolphinscheduler-data-quality/src/main/java/org/apache/dolphinscheduler/data/quality/config/EnvConfig.java
delete mode 100644 dolphinscheduler-data-quality/src/main/java/org/apache/dolphinscheduler/data/quality/config/IConfig.java
delete mode 100644 dolphinscheduler-data-quality/src/main/java/org/apache/dolphinscheduler/data/quality/config/ReaderConfig.java
delete mode 100644 dolphinscheduler-data-quality/src/main/java/org/apache/dolphinscheduler/data/quality/config/TransformerConfig.java
delete mode 100644 dolphinscheduler-data-quality/src/main/java/org/apache/dolphinscheduler/data/quality/config/ValidateResult.java
delete mode 100644 dolphinscheduler-data-quality/src/main/java/org/apache/dolphinscheduler/data/quality/config/WriterConfig.java
delete mode 100644 dolphinscheduler-data-quality/src/main/java/org/apache/dolphinscheduler/data/quality/context/DataQualityContext.java
delete mode 100644 dolphinscheduler-data-quality/src/main/java/org/apache/dolphinscheduler/data/quality/enums/ReaderType.java
delete mode 100644 dolphinscheduler-data-quality/src/main/java/org/apache/dolphinscheduler/data/quality/enums/TransformerType.java
delete mode 100644 dolphinscheduler-data-quality/src/main/java/org/apache/dolphinscheduler/data/quality/enums/WriterType.java
delete mode 100644 dolphinscheduler-data-quality/src/main/java/org/apache/dolphinscheduler/data/quality/exception/ConfigRuntimeException.java
delete mode 100644 dolphinscheduler-data-quality/src/main/java/org/apache/dolphinscheduler/data/quality/exception/DataQualityException.java
delete mode 100644 dolphinscheduler-data-quality/src/main/java/org/apache/dolphinscheduler/data/quality/execution/Execution.java
delete mode 100644 dolphinscheduler-data-quality/src/main/java/org/apache/dolphinscheduler/data/quality/execution/SparkBatchExecution.java
delete mode 100644 dolphinscheduler-data-quality/src/main/java/org/apache/dolphinscheduler/data/quality/execution/SparkRuntimeEnvironment.java
delete mode 100644 dolphinscheduler-data-quality/src/main/java/org/apache/dolphinscheduler/data/quality/flow/Component.java
delete mode 100644 dolphinscheduler-data-quality/src/main/java/org/apache/dolphinscheduler/data/quality/flow/batch/BatchReader.java
delete mode 100644 dolphinscheduler-data-quality/src/main/java/org/apache/dolphinscheduler/data/quality/flow/batch/BatchTransformer.java
delete mode 100644 dolphinscheduler-data-quality/src/main/java/org/apache/dolphinscheduler/data/quality/flow/batch/BatchWriter.java
delete mode 100644 dolphinscheduler-data-quality/src/main/java/org/apache/dolphinscheduler/data/quality/flow/batch/reader/HiveReader.java
delete mode 100644 dolphinscheduler-data-quality/src/main/java/org/apache/dolphinscheduler/data/quality/flow/batch/reader/JdbcReader.java
delete mode 100644 dolphinscheduler-data-quality/src/main/java/org/apache/dolphinscheduler/data/quality/flow/batch/reader/ReaderFactory.java
delete mode 100644 dolphinscheduler-data-quality/src/main/java/org/apache/dolphinscheduler/data/quality/flow/batch/transformer/SqlTransformer.java
delete mode 100644 dolphinscheduler-data-quality/src/main/java/org/apache/dolphinscheduler/data/quality/flow/batch/transformer/TransformerFactory.java
delete mode 100644 dolphinscheduler-data-quality/src/main/java/org/apache/dolphinscheduler/data/quality/flow/batch/writer/JdbcWriter.java
delete mode 100644 dolphinscheduler-data-quality/src/main/java/org/apache/dolphinscheduler/data/quality/flow/batch/writer/WriterFactory.java
delete mode 100644 dolphinscheduler-data-quality/src/main/java/org/apache/dolphinscheduler/data/quality/flow/batch/writer/file/BaseFileWriter.java
delete mode 100644 dolphinscheduler-data-quality/src/main/java/org/apache/dolphinscheduler/data/quality/flow/batch/writer/file/HdfsFileWriter.java
delete mode 100644 dolphinscheduler-data-quality/src/main/java/org/apache/dolphinscheduler/data/quality/flow/batch/writer/file/LocalFileWriter.java
delete mode 100644 dolphinscheduler-data-quality/src/main/java/org/apache/dolphinscheduler/data/quality/utils/ConfigUtils.java
delete mode 100644 dolphinscheduler-data-quality/src/main/java/org/apache/dolphinscheduler/data/quality/utils/JsonUtils.java
delete mode 100644 dolphinscheduler-data-quality/src/main/java/org/apache/dolphinscheduler/data/quality/utils/ParserUtils.java
delete mode 100644 dolphinscheduler-data-quality/src/main/resources/log4j.properties
delete mode 100644 dolphinscheduler-data-quality/src/test/java/org/apache/dolphinscheduler/data/quality/SparkApplicationTestBase.java
delete mode 100644 dolphinscheduler-data-quality/src/test/java/org/apache/dolphinscheduler/data/quality/configuration/ConfigurationParserTest.java
delete mode 100644 dolphinscheduler-data-quality/src/test/java/org/apache/dolphinscheduler/data/quality/flow/FlowTestBase.java
delete mode 100644 dolphinscheduler-data-quality/src/test/java/org/apache/dolphinscheduler/data/quality/flow/reader/JdbcReaderTest.java
delete mode 100644 dolphinscheduler-data-quality/src/test/java/org/apache/dolphinscheduler/data/quality/flow/reader/ReaderFactoryTest.java
delete mode 100644 dolphinscheduler-data-quality/src/test/java/org/apache/dolphinscheduler/data/quality/flow/writer/JdbcWriterTest.java
delete mode 100644 dolphinscheduler-data-quality/src/test/java/org/apache/dolphinscheduler/data/quality/flow/writer/WriterFactoryTest.java
delete mode 100644 dolphinscheduler-data-quality/src/test/java/org/apache/dolphinscheduler/data/quality/utils/ConfigUtilsTest.java
delete mode 100644 dolphinscheduler-data-quality/src/test/resources/logback.xml
delete mode 100644 dolphinscheduler-task-plugin/dolphinscheduler-task-api/src/main/java/org/apache/dolphinscheduler/plugin/task/api/DataQualityTaskExecutionContext.java
delete mode 100644 dolphinscheduler-task-plugin/dolphinscheduler-task-api/src/main/java/org/apache/dolphinscheduler/plugin/task/api/enums/dp/DqFailureStrategy.java
delete mode 100644 dolphinscheduler-task-plugin/dolphinscheduler-task-api/src/main/java/org/apache/dolphinscheduler/plugin/task/api/enums/dp/DqTaskState.java
delete mode 100644 dolphinscheduler-task-plugin/dolphinscheduler-task-api/src/main/java/org/apache/dolphinscheduler/plugin/task/api/parameters/dataquality/DataQualityParameters.java
delete mode 100644 dolphinscheduler-task-plugin/dolphinscheduler-task-api/src/main/java/org/apache/dolphinscheduler/plugin/task/api/parameters/dataquality/spark/ProgramType.java
delete mode 100644 dolphinscheduler-task-plugin/dolphinscheduler-task-api/src/main/java/org/apache/dolphinscheduler/plugin/task/api/parameters/dataquality/spark/SparkConstants.java
delete mode 100644 dolphinscheduler-task-plugin/dolphinscheduler-task-api/src/main/java/org/apache/dolphinscheduler/plugin/task/api/parameters/dataquality/spark/SparkParameters.java
delete mode 100644 dolphinscheduler-task-plugin/dolphinscheduler-task-api/src/main/java/org/apache/dolphinscheduler/plugin/task/api/utils/DataQualityConstants.java
delete mode 100644 dolphinscheduler-task-plugin/dolphinscheduler-task-api/src/main/java/org/apache/dolphinscheduler/plugin/task/api/utils/JdbcUrlParser.java
delete mode 100644 dolphinscheduler-task-plugin/dolphinscheduler-task-api/src/test/java/org/apache/dolphinscheduler/plugin/task/api/enums/dp/DqFailureStrategyTest.java
delete mode 100644 dolphinscheduler-task-plugin/dolphinscheduler-task-api/src/test/java/org/apache/dolphinscheduler/plugin/task/api/enums/dp/DqTaskStateTest.java
delete mode 100644 dolphinscheduler-task-plugin/dolphinscheduler-task-api/src/test/java/org/apache/dolphinscheduler/plugin/task/api/utils/JdbcUrlParserTest.java
delete mode 100644 dolphinscheduler-task-plugin/dolphinscheduler-task-dataquality/pom.xml
delete mode 100644 dolphinscheduler-task-plugin/dolphinscheduler-task-dataquality/src/main/java/org/apache/dolphinscheduler/plugin/task/dq/DataQualityTask.java
delete mode 100644 dolphinscheduler-task-plugin/dolphinscheduler-task-dataquality/src/main/java/org/apache/dolphinscheduler/plugin/task/dq/DataQualityTaskChannel.java
delete mode 100644 dolphinscheduler-task-plugin/dolphinscheduler-task-dataquality/src/main/java/org/apache/dolphinscheduler/plugin/task/dq/DataQualityTaskChannelFactory.java
delete mode 100644 dolphinscheduler-task-plugin/dolphinscheduler-task-dataquality/src/main/java/org/apache/dolphinscheduler/plugin/task/dq/exception/DataQualityException.java
delete mode 100644 dolphinscheduler-task-plugin/dolphinscheduler-task-dataquality/src/main/java/org/apache/dolphinscheduler/plugin/task/dq/rule/RuleManager.java
delete mode 100644 dolphinscheduler-task-plugin/dolphinscheduler-task-dataquality/src/main/java/org/apache/dolphinscheduler/plugin/task/dq/rule/entity/DqRuleExecuteSql.java
delete mode 100644 dolphinscheduler-task-plugin/dolphinscheduler-task-dataquality/src/main/java/org/apache/dolphinscheduler/plugin/task/dq/rule/entity/DqRuleInputEntry.java
delete mode 100644 dolphinscheduler-task-plugin/dolphinscheduler-task-dataquality/src/main/java/org/apache/dolphinscheduler/plugin/task/dq/rule/parameter/BaseConfig.java
delete mode 100644 dolphinscheduler-task-plugin/dolphinscheduler-task-dataquality/src/main/java/org/apache/dolphinscheduler/plugin/task/dq/rule/parameter/DataQualityConfiguration.java
delete mode 100644 dolphinscheduler-task-plugin/dolphinscheduler-task-dataquality/src/main/java/org/apache/dolphinscheduler/plugin/task/dq/rule/parameter/EnvConfig.java
delete mode 100644 dolphinscheduler-task-plugin/dolphinscheduler-task-dataquality/src/main/java/org/apache/dolphinscheduler/plugin/task/dq/rule/parser/IRuleParser.java
delete mode 100644 dolphinscheduler-task-plugin/dolphinscheduler-task-dataquality/src/main/java/org/apache/dolphinscheduler/plugin/task/dq/rule/parser/MappingColumn.java
delete mode 100644 dolphinscheduler-task-plugin/dolphinscheduler-task-dataquality/src/main/java/org/apache/dolphinscheduler/plugin/task/dq/rule/parser/MultiTableAccuracyRuleParser.java
delete mode 100644 dolphinscheduler-task-plugin/dolphinscheduler-task-dataquality/src/main/java/org/apache/dolphinscheduler/plugin/task/dq/rule/parser/MultiTableComparisonRuleParser.java
delete mode 100644 dolphinscheduler-task-plugin/dolphinscheduler-task-dataquality/src/main/java/org/apache/dolphinscheduler/plugin/task/dq/rule/parser/SingleTableCustomSqlRuleParser.java
delete mode 100644 dolphinscheduler-task-plugin/dolphinscheduler-task-dataquality/src/main/java/org/apache/dolphinscheduler/plugin/task/dq/rule/parser/SingleTableRuleParser.java
delete mode 100644 dolphinscheduler-task-plugin/dolphinscheduler-task-dataquality/src/main/java/org/apache/dolphinscheduler/plugin/task/dq/utils/Md5Utils.java
delete mode 100644 dolphinscheduler-task-plugin/dolphinscheduler-task-dataquality/src/main/java/org/apache/dolphinscheduler/plugin/task/dq/utils/RuleParserUtils.java
delete mode 100644 dolphinscheduler-task-plugin/dolphinscheduler-task-dataquality/src/main/java/org/apache/dolphinscheduler/plugin/task/dq/utils/SparkArgsUtils.java
delete mode 100644 dolphinscheduler-task-plugin/dolphinscheduler-task-dataquality/src/test/java/org/apache/dolphinscheduler/plugin/task/dq/DataQualityParameterTest.java
delete mode 100644 dolphinscheduler-task-plugin/dolphinscheduler-task-dataquality/src/test/java/org/apache/dolphinscheduler/plugin/task/dq/DataQualityTaskTest.java
delete mode 100644 dolphinscheduler-task-plugin/dolphinscheduler-task-dataquality/src/test/java/org/apache/dolphinscheduler/plugin/task/dq/utils/Md5UtilsTest.java
delete mode 100644 dolphinscheduler-ui/public/images/task-icons/data_quality.png
delete mode 100644 dolphinscheduler-ui/public/images/task-icons/data_quality_hover.png
delete mode 100644 dolphinscheduler-ui/src/locales/en_US/data-quality.ts
delete mode 100644 dolphinscheduler-ui/src/locales/zh_CN/data-quality.ts
delete mode 100644 dolphinscheduler-ui/src/router/modules/data-quality.ts
delete mode 100644 dolphinscheduler-ui/src/service/modules/data-quality/index.ts
delete mode 100644 dolphinscheduler-ui/src/service/modules/data-quality/types.ts
delete mode 100644 dolphinscheduler-ui/src/views/data-quality/rule/components/rule-modal.tsx
delete mode 100644 dolphinscheduler-ui/src/views/data-quality/rule/components/table-action.tsx
delete mode 100644 dolphinscheduler-ui/src/views/data-quality/rule/index.tsx
delete mode 100644 dolphinscheduler-ui/src/views/data-quality/rule/use-table.ts
delete mode 100644 dolphinscheduler-ui/src/views/data-quality/task-result/index.tsx
delete mode 100644 dolphinscheduler-ui/src/views/data-quality/task-result/use-table.ts
delete mode 100644 dolphinscheduler-ui/src/views/projects/task/components/node/fields/use-rules.ts
delete mode 100644 dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-data-quality.ts
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 7a9e8f785a..d1bc3385dc 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -26,7 +26,6 @@
/dolphinscheduler-common/ @SbloodyS
/dolphinscheduler-dao/ @SbloodyS @ruanwenjun
/dolphinscheduler-dao-plugin/ @SbloodyS @ruanwenjun
-/dolphinscheduler-data-quality/ @SbloodyS
/dolphinscheduler-datasource-plugin/ @SbloodyS
/dolphinscheduler-dist/ @SbloodyS
/dolphinscheduler-e2e/ @SbloodyS
diff --git a/.github/actions/labeler/labeler.yml b/.github/actions/labeler/labeler.yml
index 6bd9b6daf1..de0f8319bf 100644
--- a/.github/actions/labeler/labeler.yml
+++ b/.github/actions/labeler/labeler.yml
@@ -23,7 +23,6 @@ backend:
- 'dolphinscheduler-common/**/*'
- 'dolphinscheduler-dao/**/*'
- 'dolphinscheduler-dao-plugin/**/*'
- - 'dolphinscheduler-data-quality/**/*'
- 'dolphinscheduler-datasource-plugin/**/*'
- 'dolphinscheduler-dist/**/*'
- 'dolphinscheduler-extract/**/*'
diff --git a/config/plugins_config b/config/plugins_config
index 6fac612b01..eff859100f 100644
--- a/config/plugins_config
+++ b/config/plugins_config
@@ -77,7 +77,6 @@ dolphinscheduler-storage-s3
dolphinscheduler-task-aliyunserverlessspark
dolphinscheduler-task-chunjun
dolphinscheduler-task-datafactory
-dolphinscheduler-task-dataquality
dolphinscheduler-task-datasync
dolphinscheduler-task-datax
dolphinscheduler-task-dinky
diff --git a/deploy/kubernetes/dolphinscheduler/README.md b/deploy/kubernetes/dolphinscheduler/README.md
index 4a38a5e4d3..d64053ffdd 100644
--- a/deploy/kubernetes/dolphinscheduler/README.md
+++ b/deploy/kubernetes/dolphinscheduler/README.md
@@ -131,7 +131,6 @@ Please refer to the [Quick Start in Kubernetes](../../../docs/docs/en/guide/inst
| conf.common."aws.s3.endpoint" | string | `"http://minio:9000"` | You need to set this parameter when private cloud s3. If S3 uses public cloud, you only need to set resource.aws.region or set to the endpoint of a public cloud such as S3.cn-north-1.amazonaws.com.cn |
| conf.common."aws.s3.region" | string | `"ca-central-1"` | The AWS Region to use. if resource.storage.type=S3, This configuration is required |
| conf.common."conda.path" | string | `"/opt/anaconda3/etc/profile.d/conda.sh"` | set path of conda.sh |
-| conf.common."data-quality.jar.dir" | string | `nil` | data quality option |
| conf.common."data.basedir.path" | string | `"/tmp/dolphinscheduler"` | user data local directory path, please make sure the directory exists and have read write permissions |
| conf.common."datasource.encryption.enable" | bool | `false` | datasource encryption enable |
| conf.common."datasource.encryption.salt" | string | `"!@#$%^&*"` | datasource encryption salt |
diff --git a/deploy/kubernetes/dolphinscheduler/values.yaml b/deploy/kubernetes/dolphinscheduler/values.yaml
index 41a7dfb9c2..5658a29c11 100644
--- a/deploy/kubernetes/dolphinscheduler/values.yaml
+++ b/deploy/kubernetes/dolphinscheduler/values.yaml
@@ -336,9 +336,6 @@ conf:
# -- datasource encryption salt
datasource.encryption.salt: '!@#$%^&*'
- # -- data quality option
- data-quality.jar.dir:
-
# -- Whether hive SQL is executed in the same session
support.hive.oneSession: false
@@ -987,7 +984,6 @@ api:
# cloud: []
# logic: []
# dataIntegration: []
- # dataQuality: []
# machineLearning: []
# other: []
diff --git a/docs/configs/docsdev.js b/docs/configs/docsdev.js
index 8cf9d4d2f9..0fa7adf261 100644
--- a/docs/configs/docsdev.js
+++ b/docs/configs/docsdev.js
@@ -457,10 +457,6 @@ export default {
}
],
},
- {
- title: 'Data Quality',
- link: '/en-us/docs/dev/user_doc/guide/data-quality.html',
- },
{
title: 'Remote Logging',
link: '/en-us/docs/dev/user_doc/guide/remote-logging.html',
@@ -1160,10 +1156,6 @@ export default {
}
],
},
- {
- title: '数据质量',
- link: '/zh-cn/docs/dev/user_doc/guide/data-quality.html',
- },
{
title: '远程日志存储',
link: '/zh-cn/docs/dev/user_doc/guide/remote-logging.html',
diff --git a/docs/docs/en/architecture/configuration.md b/docs/docs/en/architecture/configuration.md
index 567163faed..86d4357e1b 100644
--- a/docs/docs/en/architecture/configuration.md
+++ b/docs/docs/en/architecture/configuration.md
@@ -224,7 +224,6 @@ The default configuration is as follows:
| yarn.job.history.status.address | http://ds1:19888/ws/v1/history/mapreduce/jobs/%s | job history status url of yarn |
| datasource.encryption.enable | false | whether to enable datasource encryption |
| datasource.encryption.salt | !@#$%^&* | the salt of the datasource encryption |
-| data-quality.jar.dir | | the jar of data quality |
| support.hive.oneSession | false | specify whether hive SQL is executed in the same session |
| sudo.enable | true | whether to enable sudo |
| alert.rpc.port | 50052 | the RPC port of Alert Server |
diff --git a/docs/docs/en/guide/data-quality.md b/docs/docs/en/guide/data-quality.md
deleted file mode 100644
index dca777d76f..0000000000
--- a/docs/docs/en/guide/data-quality.md
+++ /dev/null
@@ -1,313 +0,0 @@
-# Data Quality
-
-## Introduction
-
-The data quality task is used to check the data accuracy during the integration and processing of data. Data quality tasks in this release include single-table checking, single-table custom SQL checking, multi-table accuracy, and two-table value comparisons. The running environment of the data quality task is Spark 2.4.0, and other versions have not been verified, and users can verify by themselves.
-
-The execution logic of the data quality task is as follows:
-
-- The user defines the task in the interface, and the user input value is stored in `TaskParam`.
-- When running a task, `Master` will parse `TaskParam`, encapsulate the parameters required by `DataQualityTask` and send it to `Worker`.
-- Worker runs the data quality task. After the data quality task finishes running, it writes the statistical results to the specified storage engine.
-- The current data quality task result is stored in the `t_ds_dq_execute_result` table of `dolphinscheduler`
- `Worker` sends the task result to `Master`, after `Master` receives `TaskResponse`, it will judge whether the task type is `DataQualityTask`, if so, it will read the corresponding result from `t_ds_dq_execute_result` according to `taskInstanceId`, and then The result is judged according to the check mode, operator and threshold configured by the user.
-- If the result is a failure, the corresponding operation, alarm or interruption will be performed according to the failure policy configured by the user.
-- If you package `data-quality` separately, remember to modify the package name to be consistent with `data-quality.jar.dir` in `common.properties` with attribute name `data-quality.jar.dir`
-- If the old version is upgraded and used, you need to execute the `sql` update script to initialize the database before running.
-- `dolphinscheduler-data-quality-dev-SNAPSHOT.jar` was built with no dependencies. If a `JDBC` driver is required, you can set the `-jars` parameter in the `node settings` `Option Parameters`, e.g. `--jars /lib/jars/mysql-connector-java-8.0.16.jar`.
-- Currently only `MySQL`, `PostgreSQL` and `HIVE` data sources have been tested, other data sources have not been tested yet.
-- `Spark` needs to be configured to read `Hive` metadata, `Spark` does not use `jdbc` to read `Hive`.
-
-## Detailed Inspection Logic
-
-| **Parameter** | **Description** |
-|---------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| CheckMethod | [CheckFormula][Operator][Threshold], if the result is true, it indicates that the data does not meet expectations, and the failure strategy is executed. |
-| CheckFormula |
- Expected-Actual
- Actual-Expected
- (Actual/Expected)x100%
- (Expected-Actual)/Expected x100%
|
-| Operator | =, >, >=, <, <=, != |
-| ExpectedValue | - FixValue
- DailyAvg
- WeeklyAvg
- MonthlyAvg
- Last7DayAvg
- Last30DayAvg
- SrcTableTotalRows
- TargetTableTotalRows
|
-| Example | - CheckFormula:Actual-Expected
- Operator:>
- Threshold:0
- ExpectedValue:FixValue=9
|
-
-In the example, assuming that the actual value is 10, the operator is >, and the expected value is 9, then the result 10 -9 > 0 is true, which means that the row data in the empty column has exceeded the threshold, and the task is judged to fail.
-
-# Task Operation Guide
-
-## Null Value Check for Single Table Check
-
-### Inspection Introduction
-
-The goal of the null value check is to check the number of empty rows in the specified column. The number of empty rows can be compared with the total number of rows or a specified threshold. If it is greater than a certain threshold, it will be judged as failure.
-
-- The SQL statement that calculates the null of the specified column is as follows:
-
- ```sql
- SELECT COUNT(*) AS miss FROM ${src_table} WHERE (${src_field} is null or ${src_field} = '') AND (${src_filter})
- ```
-- The SQL to calculate the total number of rows in the table is as follows:
-
- ```sql
- SELECT COUNT(*) AS total FROM ${src_table} WHERE (${src_filter})
- ```
-
-### Interface Operation Guide
-
-![dataquality_null_check](../../../img/tasks/demo/null_check.png)
-
-| **Parameter** | **Description** |
-|------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| Source data type | Select MySQL, PostgreSQL, etc. |
-| Source data source | The corresponding data source under the source data type. |
-| Source data table | Drop-down to select the table where the validation data is located. |
-| Src filter conditions | Such as the title, it will also be used when counting the total number of rows in the table, optional. |
-| Src table check column | Drop-down to select the check column name. |
-| Check method | - [Expected-Actual]
- [Actual-Expected]
- [Actual/Expected]x100%
- [(Expected-Actual)/Expected]x100%
|
-| Check operators | =, >, >=, <, <=, ! = |
-| Threshold | The value used in the formula for comparison. |
-| Failure strategy | - Alert: The data quality task failed, the DolphinScheduler task result is successful, and an alert is sent.
- Blocking: The data quality task fails, the DolphinScheduler task result is failed, and an alarm is sent.
|
-| Expected value type | Select the desired type from the drop-down menu. |
-
-## Timeliness Check of Single Table Check
-
-### Inspection Introduction
-
-The timeliness check is used to check whether the data is processed within the expected time. The start time and end time can be specified to define the time range. If the amount of data within the time range does not reach the set threshold, the check task will be judged as fail.
-
-### Interface Operation Guide
-
-![dataquality_timeliness_check](../../../img/tasks/demo/timeliness_check.png)
-
-| **Parameter** | **Description** |
-|------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| Source data type | Select MySQL, PostgreSQL, etc. |
-| Source data source | The corresponding data source under the source data type. |
-| Source data table | Drop-down to select the table where the validation data is located. |
-| Src filter conditions | Such as the title, it will also be used when counting the total number of rows in the table, optional. |
-| Src table check column | Drop-down to select check column name. |
-| Start time | The start time of a time range. |
-| end time | The end time of a time range. |
-| Time Format | Set the corresponding time format. |
-| Check method | - [Expected-Actual]
- [Actual-Expected]
- [Actual/Expected]x100%
- [(Expected-Actual)/Expected]x100%
|
-| Check operators | =, >, >=, <, <=, ! = |
-| Threshold | The value used in the formula for comparison. |
-| Failure strategy | - Alert: The data quality task failed, the DolphinScheduler task result is successful, and an alert is sent.
- Blocking: The data quality task fails, the DolphinScheduler task result is failed, and an alarm is sent.
|
-| Expected value type | Select the desired type from the drop-down menu. |
-
-## Field Length Check for Single Table Check
-
-### Inspection Introduction
-
-The goal of field length verification is to check whether the length of the selected field meets the expectations. If there is data that does not meet the requirements, and the number of rows exceeds the threshold, the task will be judged to fail.
-
-### Interface Operation Guide
-
-![dataquality_length_check](../../../img/tasks/demo/field_length_check.png)
-
-| **Parameter** | **Description** |
-|------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| Source data type | Select MySQL, PostgreSQL, etc. |
-| Source data source | The corresponding data source under the source data type. |
-| Source data table | Drop-down to select the table where the validation data is located. |
-| Src filter conditions | Such as the title, it will also be used when counting the total number of rows in the table, optional. |
-| Src table check column | Drop-down to select the check column name. |
-| Logical operators | =, >, >=, <, <=, ! = |
-| Field length limit | Like the title. |
-| Check method | - [Expected-Actual]
- [Actual-Expected]
- [Actual/Expected]x100%
- [(Expected-Actual)/Expected]x100%
|
-| Check operators | =, >, >=, <, <=, ! = |
-| Threshold | The value used in the formula for comparison. |
-| Failure strategy | - Alert: The data quality task failed, the DolphinScheduler task result is successful, and an alert is sent.
- Blocking: The data quality task fails, the DolphinScheduler task result is failed, and an alarm is sent.
|
-| Expected value type | Select the desired type from the drop-down menu. |
-
-## Uniqueness Check for Single Table Check
-
-### Inspection Introduction
-
-The goal of the uniqueness check is to check whether the fields are duplicated. It is generally used to check whether the primary key is duplicated. If there are duplicates and the threshold is reached, the check task will be judged to be failed.
-
-### Interface Operation Guide
-
-![dataquality_uniqueness_check](../../../img/tasks/demo/uniqueness_check.png)
-
-| **Parameter** | **Description** |
-|------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| Source data type | Select MySQL, PostgreSQL, etc. |
-| Source data source | The corresponding data source under the source data type. |
-| Source data table | Drop-down to select the table where the validation data is located. |
-| Src filter conditions | Such as the title, it will also be used when counting the total number of rows in the table, optional. |
-| Src table check column | Drop-down to select the check column name. |
-| Check method | - [Expected-Actual]
- [Actual-Expected]
- [Actual/Expected]x100%
- [(Expected-Actual)/Expected]x100%
|
-| Check operators | =, >, >=, <, <=, ! = |
-| Threshold | The value used in the formula for comparison. |
-| Failure strategy | - Alert: The data quality task failed, the DolphinScheduler task result is successful, and an alert is sent.
- Blocking: The data quality task fails, the DolphinScheduler task result is failed, and an alarm is sent.
|
-| Expected value type | Select the desired type from the drop-down menu. |
-
-## Regular Expression Check for Single Table Check
-
-### Inspection Introduction
-
-The goal of regular expression verification is to check whether the format of the value of a field meets the requirements, such as time format, email format, ID card format, etc. If there is data that does not meet the format and exceeds the threshold, the task will be judged as failed.
-
-### Interface Operation Guide
-
-![dataquality_regex_check](../../../img/tasks/demo/regexp_check.png)
-
-| **Parameter** | **Description** |
-|------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| Source data type | Select MySQL, PostgreSQL, etc. |
-| Source data source | The corresponding data source under the source data type. |
-| Source data table | Drop-down to select the table where the validation data is located. |
-| Src filter conditions | Such as the title, it will also be used when counting the total number of rows in the table, optional. |
-| Src table check column | Drop-down to select check column name. |
-| Regular expression | As title. |
-| Check method | - [Expected-Actual]
- [Actual-Expected]
- [Actual/Expected]x100%
- [(Expected-Actual)/Expected]x100%
|
-| Check operators | =, >, >=, <, <=, ! = |
-| Threshold | The value used in the formula for comparison. |
-| Failure strategy | - Alert: The data quality task failed, the DolphinScheduler task result is successful, and an alert is sent.
- Blocking: The data quality task fails, the DolphinScheduler task result is failed, and an alarm is sent.
|
-| Expected value type | Select the desired type from the drop-down menu. |
-
-## Enumeration Value Validation for Single Table Check
-
-### Inspection Introduction
-
-The goal of enumeration value verification is to check whether the value of a field is within the range of the enumeration value. If there is data that is not in the range of the enumeration value and exceeds the threshold, the task will be judged to fail.
-
-### Interface Operation Guide
-
-![dataquality_enum_check](../../../img/tasks/demo/enumeration_check.png)
-
-| **Parameter** | **Description** |
-|-----------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| Source data type | Select MySQL, PostgreSQL, etc. |
-| Source data source | The corresponding data source under the source data type. |
-| Source data table | Drop-down to select the table where the validation data is located. |
-| Src table filter conditions | Such as title, also used when counting the total number of rows in the table, optional. |
-| Src table check column | Drop-down to select the check column name. |
-| List of enumeration values | Separated by commas. |
-| Check method | - [Expected-Actual]
- [Actual-Expected]
- [Actual/Expected]x100%
- [(Expected-Actual)/Expected]x100%
|
-| Check operators | =, >, >=, <, <=, ! = |
-| Threshold | The value used in the formula for comparison. |
-| Failure strategy | - Alert: The data quality task failed, the DolphinScheduler task result is successful, and an alert is sent.
- Blocking: The data quality task fails, the DolphinScheduler task result is failed, and an alarm is sent.
|
-| Expected value type | Select the desired type from the drop-down menu. |
-
-## Table Row Number Verification for Single Table Check
-
-### Inspection Introduction
-
-The goal of table row number verification is to check whether the number of rows in the table reaches the expected value. If the number of rows does not meet the standard, the task will be judged as failed.
-
-### Interface Operation Guide
-
-![dataquality_count_check](../../../img/tasks/demo/table_count_check.png)
-
-| **Parameter** | **Description** |
-|------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| Source data type | Select MySQL, PostgreSQL, etc. |
-| Source data source | The corresponding data source under the source data type. |
-| Source data table | Drop-down to select the table where the validation data is located. |
-| Src filter conditions | Such as the title, it will also be used when counting the total number of rows in the table, optional. |
-| Src table check column | Drop-down to select the check column name. |
-| Check method | - [Expected-Actual]
- [Actual-Expected]
- [Actual/Expected]x100%
- [(Expected-Actual)/Expected]x100%
|
-| Check operators | =, >, >=, <, <=, ! = |
-| Threshold | The value used in the formula for comparison. |
-| Failure strategy | - Alert: The data quality task failed, the DolphinScheduler task result is successful, and an alert is sent.
- Blocking: The data quality task fails, the DolphinScheduler task result is failed, and an alarm is sent.
|
-| Expected value type | Select the desired type from the drop-down menu. |
-
-## Custom SQL Check for Single Table Check
-
-### Interface Operation Guide
-
-![dataquality_custom_sql_check](../../../img/tasks/demo/custom_sql_check.png)
-
-| **Parameter** | **Description** |
-|------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| Source data type | Select MySQL, PostgreSQL, etc. |
-| Source data source | The corresponding data source under the source data type. |
-| Source data table | Drop-down to select the table where the data to be verified is located. |
-| Actual value name | Alias in SQL for statistical value calculation, such as max_num. |
-| Actual value calculation SQL | SQL for outputting actual values. Note:- The SQL must be statistical SQL, such as counting the number of rows, calculating the maximum value, minimum value, etc.
- Select max(a) as max_num from ${src_table}, the table name must be filled like this.
|
-| Src filter conditions | Such as the title, it will also be used when counting the total number of rows in the table, optional. |
-| Check method | - [Expected-Actual]
- [Actual-Expected]
- [Actual/Expected]x100%
- [(Expected-Actual)/Expected]x100%
|
-| Check operators | =, >, >=, <, <=, ! = |
-| Threshold | The value used in the formula for comparison. |
-| Failure strategy | - Alert: The data quality task failed, the DolphinScheduler task result is successful, and an alert is sent.
- Blocking: The data quality task fails, the DolphinScheduler task result is failed, and an alarm is sent.
|
-| Expected value type | Select the desired type from the drop-down menu. |
-
-## Accuracy Check of Multi-table
-
-### Inspection Introduction
-
-Accuracy checks are performed by comparing the accuracy differences of data records for selected fields between two tables, examples are as follows
-- table test1
-
-| c1 | c2 |
-|:--:|:--:|
-| a | 1 |
-| b | 2 |
-
-- table test2
-
-| c21 | c22 |
-|:---:|:---:|
-| a | 1 |
-| b | 3 |
-
-If you compare the data in c1 and c21, the tables test1 and test2 are exactly the same. If you compare c2 and c22, the data in table test1 and table test2 are inconsistent.
-
-### Interface Operation Guide
-
-![dataquality_multi_table_accuracy_check](../../../img/tasks/demo/multi_table_accuracy_check.png)
-
-| **Parameter** | **Description** |
-|--------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| Source data type | Select MySQL, PostgreSQL, etc. |
-| Source data source | The corresponding data source under the source data type. |
-| Source data table | Drop-down to select the table where the data to be verified is located. |
-| Src filter conditions | Such as the title, it will also be used when counting the total number of rows in the table, optional. |
-| Target data type | Choose MySQL, PostgreSQL, etc. |
-| Target data source | The corresponding data source under the source data type. |
-| Target data table | Drop-down to select the table where the data to be verified is located. |
-| Target filter conditions | Such as the title, it will also be used when counting the total number of rows in the table, optional. |
-| Check column | Fill in the source data column, operator and target data column respectively. |
-| Verification method | Select the desired verification method. |
-| Operators | =, >, >=, <, <=, ! = |
-| Failure strategy | - Alert: The data quality task failed, the DolphinScheduler task result is successful, and an alert is sent.
- Blocking: The data quality task fails, the DolphinScheduler task result is failed, and an alarm is sent.
|
-| Expected value type | Select the desired type in the drop-down menu, only `SrcTableTotalRow`, `TargetTableTotalRow` and fixed value are suitable for selection here. |
-
-## Comparison of the values checked by the two tables
-
-### Inspection Introduction
-
-Two-table value comparison allows users to customize different SQL statistics for two tables and compare the corresponding values. For example, for the source table A, the total amount of a certain column is calculated, and for the target table, the total amount of a certain column is calculated. value sum2, compare sum1 and sum2 to determine the check result.
-
-### Interface Operation Guide
-
-![dataquality_multi_table_comparison_check](../../../img/tasks/demo/multi_table_comparison_check.png)
-
-| **Parameter** | **Description** |
-|--------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| Source data type | Select MySQL, PostgreSQL, etc. |
-| Source data source | The corresponding data source under the source data type. |
-| Source data table | The table where the data is to be verified. |
-| Actual value name | Calculate the alias in SQL for the actual value, such as max_age1. |
-| Actual value calculation SQL | SQL for outputting actual values. Note: - The SQL must be statistical SQL, such as counting the number of rows, calculating the maximum value, minimum value, etc.
- Select max(age) as max_age1 from ${src_table} The table name must be filled like this.
|
-| Target data type | Choose MySQL, PostgreSQL, etc. |
-| Target data source | The corresponding data source under the source data type. |
-| Target data table | The table where the data is to be verified. |
-| Expected value name | Calculate the alias in SQL for the expected value, such as max_age2. |
-| Expected value calculation SQL | SQL for outputting expected value. Note: - The SQL must be statistical SQL, such as counting the number of rows, calculating the maximum value, minimum value, etc.
- Select max(age) as max_age2 from ${target_table} The table name must be filled like this.
|
-| Verification method | Select the desired verification method. |
-| Operators | =, >, >=, <, <=, ! = |
-| Failure strategy | - Alert: The data quality task failed, the DolphinScheduler task result is successful, and an alert is sent.
- Blocking: The data quality task fails, the DolphinScheduler task result is failed, and an alarm is sent.
|
-
-## Task result view
-
-![dataquality_result](../../../img/tasks/demo/result.png)
-
-## Rule View
-
-### List of rules
-
-![dataquality_rule_list](../../../img/tasks/demo/rule_list.png)
-
-### Rules Details
-
-![dataquality_rule_detail](../../../img/tasks/demo/rule_detail.png)
diff --git a/docs/docs/en/guide/upgrade/incompatible.md b/docs/docs/en/guide/upgrade/incompatible.md
index c0549badd2..c263d97ac4 100644
--- a/docs/docs/en/guide/upgrade/incompatible.md
+++ b/docs/docs/en/guide/upgrade/incompatible.md
@@ -31,5 +31,6 @@ This document records the incompatible updates between each version. You need to
* Remove the `udf-manage` function from the `resource center` ([#16209])(https://github.com/apache/dolphinscheduler/pull/16209)
* Remove the `Pigeon` from the `Task Plugin` ([#16218])(https://github.com/apache/dolphinscheduler/pull/16218)
* Uniformly name `process` in code as `workflow` ([#16515])(https://github.com/apache/dolphinscheduler/pull/16515)
-* Deprecated upgrade code of 1.x and 2.x in 3.3.0-release ([#16543])(https://github.com/apache/dolphinscheduler/pull/16543)
+* Deprecated upgrade code of 1.x and 2.x ([#16543])(https://github.com/apache/dolphinscheduler/pull/16543)
+* Remove the `Data Quality` module ([#16794])(https://github.com/apache/dolphinscheduler/pull/16794)
diff --git a/docs/docs/zh/architecture/configuration.md b/docs/docs/zh/architecture/configuration.md
index 8bec9c042e..8eed519f78 100644
--- a/docs/docs/zh/architecture/configuration.md
+++ b/docs/docs/zh/architecture/configuration.md
@@ -224,7 +224,6 @@ common.properties配置文件目前主要是配置hadoop/s3/yarn/applicationId
| yarn.job.history.status.address | http://ds1:19888/ws/v1/history/mapreduce/jobs/%s | yarn的作业历史状态URL |
| datasource.encryption.enable | false | 是否启用datasource 加密 |
| datasource.encryption.salt | !@#$%^&* | datasource加密使用的salt |
-| data-quality.jar.dir | | 配置数据质量使用的jar包 |
| support.hive.oneSession | false | 设置hive SQL是否在同一个session中执行 |
| sudo.enable | true | 是否开启sudo |
| alert.rpc.port | 50052 | Alert Server的RPC端口 |
diff --git a/docs/docs/zh/guide/data-quality.md b/docs/docs/zh/guide/data-quality.md
deleted file mode 100644
index 17b2a55cb2..0000000000
--- a/docs/docs/zh/guide/data-quality.md
+++ /dev/null
@@ -1,357 +0,0 @@
-# 概述
-
-## 任务类型介绍
-
-数据质量任务是用于检查数据在集成、处理过程中的数据准确性。本版本的数据质量任务包括单表检查、单表自定义SQL检查、多表准确性以及两表值比对。数据质量任务的运行环境为Spark2.4.0,其他版本尚未进行过验证,用户可自行验证。
-
-- 数据质量任务的执行逻辑如下:
-
-> 用户在界面定义任务,用户输入值保存在`TaskParam`中
-> 运行任务时,`Master`会解析`TaskParam`,封装`DataQualityTask`所需要的参数下发至`Worker。
-> Worker`运行数据质量任务,数据质量任务在运行结束之后将统计结果写入到指定的存储引擎中,当前数据质量任务结果存储在`dolphinscheduler`的`t_ds_dq_execute_result`表中
-> `Worker`发送任务结果给`Master`,`Master`收到`TaskResponse`之后会判断任务类型是否为`DataQualityTask`,如果是的话会根据`taskInstanceId`从`t_ds_dq_execute_result`中读取相应的结果,然后根据用户配置好的检查方式,操作符和阈值进行结果判断,如果结果为失败的话,会根据用户配置好的的失败策略进行相应的操作,告警或者中断
->
- ## 注意事项
-
-- 如果单独打包`data-quality`的话,记得修改包路径和`data-quality.jar.dir`一致,配置内容在 `common.properties` 中的 `data-quality.jar.dir`
-- 如果是老版本升级使用,运行之前需要先执行`SQL`更新脚本进行数据库初始化。
-- 当前 `dolphinscheduler-data-quality-dev-SNAPSHOT.jar` 是瘦包,不包含任何 `JDBC` 驱动。
- 如果有 `JDBC` 驱动需要,可以在`节点设置` `选项参数`处设置 `--jars` 参数,
- 如:`--jars /lib/jars/mysql-connector-java-8.0.16.jar`。
-- 当前只测试了`MySQL`、`PostgreSQL`和`HIVE`数据源,其他数据源暂时未测试过。
-- `Spark`需要配置好读取`Hive`元数据,`Spark`不是采用`JDBC`的方式读取`Hive`。
-
-## 检查逻辑详解
-
-- 校验公式:[校验方式][操作符][阈值],如果结果为真,则表明数据不符合期望,执行失败策略
-- 校验方式:
- - [Expected-Actual][期望值-实际值]
- - [Actual-Expected][实际值-期望值]
- - [Actual/Expected][实际值/期望值]x100%
- - [(Expected-Actual)/Expected][(期望值-实际值)/期望值]x100%
-- 操作符:=、>、>=、<、<=、!=
-- 期望值类型
- - 固定值
- - 日均值
- - 周均值
- - 月均值
- - 最近7天均值
- - 最近30天均值
- - 源表总行数
- - 目标表总行数
-- 例子
- - 校验方式为:[Actual-Expected][实际值-期望值]
- - [操作符]:>
- - [阈值]:0
- - 期望值类型:固定值=9。
-
- 假设实际值为10,操作符为 >, 期望值为9,那么结果 10 -9 > 0 为真,那就意味列为空的行数据已经超过阈值,任务被判定为失败
-
-# 任务操作指南
-
-## 单表检查之空值检查
-
-### 检查介绍
-
-空值检查的目标是检查出指定列为空的行数,可将为空的行数与总行数或者指定阈值进行比较,如果大于某个阈值则判定为失败
-- 计算指定列为空的SQL语句如下:
-
-```sql
-SELECT COUNT(*) AS miss FROM ${src_table} WHERE (${src_field} is null or ${src_field} = '') AND (${src_filter})
-```
-
-- 计算表总行数的SQL如下:
-
- ```sql
- SELECT COUNT(*) AS total FROM ${src_table} WHERE (${src_filter})
- ```
-
-### 界面操作指南
-
-![dataquality_null_check](../../../img/tasks/demo/null_check.png)
-- 源数据类型:选择MySQL、PostgreSQL等
-- 源数据源:源数据类型下对应的数据源
-- 源数据表:下拉选择验证数据所在表
-- 源过滤条件:如标题,统计表总行数的时候也会用到,选填
-- 源表检查列:下拉选择检查列名
-- 校验方式:
-- [Expected-Actual][期望值-实际值]
-- [Actual-Expected][实际值-期望值]
-- [Actual/Expected][实际值/期望值]x100%
-- [(Expected-Actual)/Expected][(期望值-实际值)/期望值]x100%
-- 校验操作符:=,>、>=、<、<=、!=
-- 阈值:公式中用于比较的值
-- 失败策略
-- 告警:数据质量任务失败了,DolphinScheduler任务结果为成功,发送告警
-- 阻断:数据质量任务失败了,DolphinScheduler任务结果为失败,发送告警
-- 期望值类型:在下拉菜单中选择所要的类型
-
-## 单表检查之及时性检查
-
-### 检查介绍
-
-及时性检查用于检查数据是否在预期时间内处理完成,可指定开始时间、结束时间来界定时间范围,如果在该时间范围内的数据量没有达到设定的阈值,那么会判断该检查任务为失败
-
-### 界面操作指南
-
-![dataquality_timeliness_check](../../../img/tasks/demo/timeliness_check.png)
-- 源数据类型:选择MySQL、PostgreSQL等
-- 源数据源:源数据类型下对应的数据源
-- 源数据表:下拉选择验证数据所在表
-- 源过滤条件:如标题,统计表总行数的时候也会用到,选填
-- 源表检查列:下拉选择检查列名
-- 起始时间:某个时间范围的开始时间
-- 结束时间:某个时间范围的结束时间
-- 时间格式:设置对应的时间格式
-- 校验方式:
-- [Expected-Actual][期望值-实际值]
-- [Actual-Expected][实际值-期望值]
-- [Actual/Expected][实际值/期望值]x100%
-- [(Expected-Actual)/Expected][(期望值-实际值)/期望值]x100%
-- 校验操作符:=,>、>=、<、<=、!=
-- 阈值:公式中用于比较的值
-- 失败策略
-- 告警:数据质量任务失败了,DolphinScheduler任务结果为成功,发送告警
-- 阻断:数据质量任务失败了,DolphinScheduler任务结果为失败,发送告警
-- 期望值类型:在下拉菜单中选择所要的类型
-
-## 单表检查之字段长度校验
-
-### 检查介绍
-
-字段长度校验的目标是检查所选字段的长度是否满足预期,如果有存在不满足要求的数据,并且行数超过阈值则会判断任务为失败
-
-### 界面操作指南
-
-![dataquality_length_check](../../../img/tasks/demo/field_length_check.png)
-- 源数据类型:选择MySQL、PostgreSQL等
-- 源数据源:源数据类型下对应的数据源
-- 源数据表:下拉选择验证数据所在表
-- 源过滤条件:如标题,统计表总行数的时候也会用到,选填
-- 源表检查列:下拉选择检查列名
-- 逻辑操作符:=,>、>=、<、<=、!=
-- 字段长度限制:如标题
-- 校验方式:
-- [Expected-Actual][期望值-实际值]
-- [Actual-Expected][实际值-期望值]
-- [Actual/Expected][实际值/期望值]x100%
-- [(Expected-Actual)/Expected][(期望值-实际值)/期望值]x100%
-- 校验操作符:=,>、>=、<、<=、!=
-- 阈值:公式中用于比较的值
-- 失败策略
-- 告警:数据质量任务失败了,DolphinScheduler任务结果为成功,发送告警
-- 阻断:数据质量任务失败了,DolphinScheduler任务结果为失败,发送告警
-- 期望值类型:在下拉菜单中选择所要的类型
-
-## 单表检查之唯一性校验
-
-### 检查介绍
-
-唯一性校验的目标是检查字段是否存在重复的情况,一般用于检验primary key是否有重复,如果存在重复且达到阈值,则会判断检查任务为失败
-
-### 界面操作指南
-
-![dataquality_uniqueness_check](../../../img/tasks/demo/uniqueness_check.png)
-- 源数据类型:选择MySQL、PostgreSQL等
-- 源数据源:源数据类型下对应的数据源
-- 源数据表:下拉选择验证数据所在表
-- 源过滤条件:如标题,统计表总行数的时候也会用到,选填
-- 源表检查列:下拉选择检查列名
-- 校验方式:
-- [Expected-Actual][期望值-实际值]
-- [Actual-Expected][实际值-期望值]
-- [Actual/Expected][实际值/期望值]x100%
-- [(Expected-Actual)/Expected][(期望值-实际值)/期望值]x100%
-- 校验操作符:=,>、>=、<、<=、!=
-- 阈值:公式中用于比较的值
-- 失败策略
-- 告警:数据质量任务失败了,DolphinScheduler任务结果为成功,发送告警
-- 阻断:数据质量任务失败了,DolphinScheduler任务结果为失败,发送告警
-- 期望值类型:在下拉菜单中选择所要的类型
-
-## 单表检查之正则表达式校验
-
-### 检查介绍
-
-正则表达式校验的目标是检查某字段的值的格式是否符合要求,例如时间格式、邮箱格式、身份证格式等等,如果存在不符合格式的数据并超过阈值,则会判断任务为失败
-
-### 界面操作指南
-
-![dataquality_regex_check](../../../img/tasks/demo/regexp_check.png)
-- 源数据类型:选择MySQL、PostgreSQL等
-- 源数据源:源数据类型下对应的数据源
-- 源数据表:下拉选择验证数据所在表
-- 源过滤条件:如标题,统计表总行数的时候也会用到,选填
-- 源表检查列:下拉选择检查列名
-- 正则表达式:如标题
-- 校验方式:
-- [Expected-Actual][期望值-实际值]
-- [Actual-Expected][实际值-期望值]
-- [Actual/Expected][实际值/期望值]x100%
-- [(Expected-Actual)/Expected][(期望值-实际值)/期望值]x100%
-- 校验操作符:=,>、>=、<、<=、!=
-- 阈值:公式中用于比较的值
-- 失败策略
-- 告警:数据质量任务失败了,DolphinScheduler任务结果为成功,发送告警
-- 阻断:数据质量任务失败了,DolphinScheduler任务结果为失败,发送告警
-- 期望值类型:在下拉菜单中选择所要的类型
-
-## 单表检查之枚举值校验
-
-### 检查介绍
-
-枚举值校验的目标是检查某字段的值是否在枚举值的范围内,如果存在不在枚举值范围里的数据并超过阈值,则会判断任务为失败
-
-### 界面操作指南
-
-![dataquality_enum_check](../../../img/tasks/demo/enumeration_check.png)
-- 源数据类型:选择MySQL、PostgreSQL等
-- 源数据源:源数据类型下对应的数据源
-- 源数据表:下拉选择验证数据所在表
-- 源表过滤条件:如标题,统计表总行数的时候也会用到,选填
-- 源表检查列:下拉选择检查列名
-- 枚举值列表:用英文逗号,隔开
-- 校验方式:
-- [Expected-Actual][期望值-实际值]
-- [Actual-Expected][实际值-期望值]
-- [Actual/Expected][实际值/期望值]x100%
-- [(Expected-Actual)/Expected][(期望值-实际值)/期望值]x100%
-- 校验操作符:=,>、>=、<、<=、!=
-- 阈值:公式中用于比较的值
-- 失败策略
-- 告警:数据质量任务失败了,DolphinScheduler任务结果为成功,发送告警
-- 阻断:数据质量任务失败了,DolphinScheduler任务结果为失败,发送告警
-- 期望值类型:在下拉菜单中选择所要的类型
-
-## 单表检查之表行数校验
-
-### 检查介绍
-
-表行数校验的目标是检查表的行数是否达到预期的值,如果行数未达标,则会判断任务为失败
-
-### 界面操作指南
-
-![dataquality_count_check](../../../img/tasks/demo/table_count_check.png)
-- 源数据类型:选择MySQL、PostgreSQL等
-- 源数据源:源数据类型下对应的数据源
-- 源数据表:下拉选择验证数据所在表
-- 源过滤条件:如标题,统计表总行数的时候也会用到,选填
-- 源表检查列:下拉选择检查列名
-- 校验方式:
-- [Expected-Actual][期望值-实际值]
-- [Actual-Expected][实际值-期望值]
-- [Actual/Expected][实际值/期望值]x100%
-- [(Expected-Actual)/Expected][(期望值-实际值)/期望值]x100%
-- 校验操作符:=,>、>=、<、<=、!=
-- 阈值:公式中用于比较的值
-- 失败策略
-- 告警:数据质量任务失败了,DolphinScheduler任务结果为成功,发送告警
-- 阻断:数据质量任务失败了,DolphinScheduler任务结果为失败,发送告警
-- 期望值类型:在下拉菜单中选择所要的类型
-
-## 单表检查之自定义SQL检查
-
-### 检查介绍
-
-### 界面操作指南
-
-![dataquality_custom_sql_check](../../../img/tasks/demo/custom_sql_check.png)
-- 源数据类型:选择MySQL、PostgreSQL等
-- 源数据源:源数据类型下对应的数据源
-- 源数据表:下拉选择要验证数据所在表
-- 实际值名:为统计值计算SQL中的别名,如max_num
-- 实际值计算SQL: 用于输出实际值的SQL、
-- 注意点:该SQL必须为统计SQL,例如统计行数,计算最大值、最小值等
-- select max(a) as max_num from ${src_table},表名必须这么填
-- 源过滤条件:如标题,统计表总行数的时候也会用到,选填
-- 校验方式:
-- 校验操作符:=,>、>=、<、<=、!=
-- 阈值:公式中用于比较的值
-- 失败策略
-- 告警:数据质量任务失败了,DolphinScheduler任务结果为成功,发送告警
-- 阻断:数据质量任务失败了,DolphinScheduler任务结果为失败,发送告警
-- 期望值类型:在下拉菜单中选择所要的类型
-
-## 多表检查之准确性检查
-
-### 检查介绍
-
-准确性检查是通过比较两个表之间所选字段的数据记录的准确性差异,例子如下
-- 表test1
-
-| c1 | c2 |
-|:--:|:--:|
-| a | 1 |
-| b | 2 |
-
-- 表test2
-
-| c21 | c22 |
-|:---:|:---:|
-| a | 1 |
-| b | 3 |
-
-如果对比c1和c21中的数据,则表test1和test2完全一致。 如果对比c2和c22则表test1和表test2中的数据则存在不一致了。
-
-### 界面操作指南
-
-![dataquality_multi_table_accuracy_check](../../../img/tasks/demo/multi_table_accuracy_check.png)
-- 源数据类型:选择MySQL、PostgreSQL等
-- 源数据源:源数据类型下对应的数据源
-- 源数据表:下拉选择要验证数据所在表
-- 源过滤条件:如标题,统计表总行数的时候也会用到,选填
-- 目标数据类型:选择MySQL、PostgreSQL等
-- 目标数据源:源数据类型下对应的数据源
-- 目标数据表:下拉选择要验证数据所在表
-- 目标过滤条件:如标题,统计表总行数的时候也会用到,选填
-- 检查列:
-- 分别填写 源数据列,操作符,目标数据列
-- 校验方式:选择想要的校验方式
-- 操作符:=,>、>=、<、<=、!=
-- 失败策略
-- 告警:数据质量任务失败了,DolphinScheduler任务结果为成功,发送告警
-- 阻断:数据质量任务失败了,DolphinScheduler任务结果为失败,发送告警
-- 期望值类型:在下拉菜单中选择所要的类型,这里只适合选择SrcTableTotalRow、TargetTableTotalRow和固定值
-
-## 两表检查之值比对
-
-### 检查介绍
-
-两表值比对允许用户对两张表自定义不同的SQL统计出相应的值进行比对,例如针对源表A统计出某一列的金额总值sum1,针对目标表统计出某一列的金额总值sum2,将sum1和sum2进行比较来判定检查结果
-
-### 界面操作指南
-
-![dataquality_multi_table_comparison_check](../../../img/tasks/demo/multi_table_comparison_check.png)
-- 源数据类型:选择MySQL、PostgreSQL等
-- 源数据源:源数据类型下对应的数据源
-- 源数据表:要验证数据所在表
-- 实际值名:为实际值计算SQL中的别名,如max_age1
-- 实际值计算SQL: 用于输出实际值的SQL、
-- 注意点:该SQL必须为统计SQL,例如统计行数,计算最大值、最小值等
-- select max(age) as max_age1 from ${src_table} 表名必须这么填
-- 目标数据类型:选择MySQL、PostgreSQL等
-- 目标数据源:源数据类型下对应的数据源
-- 目标数据表:要验证数据所在表
-- 期望值名:为期望值计算SQL中的别名,如max_age2
-- 期望值计算SQL: 用于输出期望值的SQL、
-- 注意点:该SQL必须为统计SQL,例如统计行数,计算最大值、最小值等
-- select max(age) as max_age2 from ${target_table} 表名必须这么填
-- 校验方式:选择想要的校验方式
-- 操作符:=,>、>=、<、<=、!=
-- 失败策略
-- 告警:数据质量任务失败了,DolphinScheduler任务结果为成功,发送告警
-- 阻断:数据质量任务失败了,DolphinScheduler任务结果为失败,发送告警
-
-## 任务结果查看
-
-![dataquality_result](../../../img/tasks/demo/result.png)
-
-## 规则查看
-
-### 规则列表
-
-![dataquality_rule_list](../../../img/tasks/demo/rule_list.png)
-
-### 规则详情
-
-![dataquality_rule_detail](../../../img/tasks/demo/rule_detail.png)
diff --git a/docs/docs/zh/guide/upgrade/incompatible.md b/docs/docs/zh/guide/upgrade/incompatible.md
index 098992294d..f1fb24d9c9 100644
--- a/docs/docs/zh/guide/upgrade/incompatible.md
+++ b/docs/docs/zh/guide/upgrade/incompatible.md
@@ -26,8 +26,9 @@
## 3.3.0
-* 从 `资源中心` 中移除了 `udf-manage` 功能 ([#16209])(https://github.com/apache/dolphinscheduler/pull/16209)
-* 从 `任务插件` 中移除了 `Pigeon` 类型 ([#16218])(https://github.com/apache/dolphinscheduler/pull/16218)
+* 从 `资源中心` 中移除 `udf-manage` 功能 ([#16209])(https://github.com/apache/dolphinscheduler/pull/16209)
+* 从 `任务插件` 中移除 `Pigeon` 类型 ([#16218])(https://github.com/apache/dolphinscheduler/pull/16218)
* 统一代码中的 `process` 为 `workflow` ([#16515])(https://github.com/apache/dolphinscheduler/pull/16515)
-* 在 3.3.0-release 中废弃了从 1.x 至 2.x 的升级代码 ([#16543])(https://github.com/apache/dolphinscheduler/pull/16543)
+* 废弃从 1.x 至 2.x 的升级代码 ([#16543])(https://github.com/apache/dolphinscheduler/pull/16543)
+* 移除 `数据质量` 模块 ([#16794])(https://github.com/apache/dolphinscheduler/pull/16794)
diff --git a/docs/img/tasks/demo/custom_sql_check.png b/docs/img/tasks/demo/custom_sql_check.png
deleted file mode 100644
index b1e1b9b6f8bbd16b87839027906597ce6f482f6d..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 20259
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
diff --git a/docs/img/tasks/demo/enumeration_check.png b/docs/img/tasks/demo/enumeration_check.png
deleted file mode 100644
index e2e16554cfa756389822aa24944df0d8c0772b2d..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 20145
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 |