Browse Source

[Improvement][SQL Task]use default sql segment separator (#10869)

3.2.0-release
zhuxt2015 2 years ago committed by GitHub
parent
commit
e6832220c3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      docs/docs/en/guide/upgrade/incompatible.md
  2. 4
      docs/docs/zh/guide/task/sql.md
  3. 2
      docs/docs/zh/guide/upgrade/incompatible.md
  4. 8
      dolphinscheduler-spi/src/main/java/org/apache/dolphinscheduler/spi/enums/DbType.java
  5. 18
      dolphinscheduler-task-plugin/dolphinscheduler-task-api/src/main/java/org/apache/dolphinscheduler/plugin/task/api/parameters/SqlParameters.java
  6. 64
      dolphinscheduler-task-plugin/dolphinscheduler-task-sql/src/main/java/org/apache/dolphinscheduler/plugin/task/sql/SqlSplitter.java
  7. 46
      dolphinscheduler-task-plugin/dolphinscheduler-task-sql/src/main/java/org/apache/dolphinscheduler/plugin/task/sql/SqlTask.java
  8. 2
      dolphinscheduler-ui/src/locales/en_US/project.ts
  9. 2
      dolphinscheduler-ui/src/locales/zh_CN/project.ts
  10. 10
      dolphinscheduler-ui/src/views/projects/task/components/node/fields/use-sql-type.ts
  11. 1
      dolphinscheduler-ui/src/views/projects/task/components/node/format-data.ts
  12. 1
      dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-sql.ts
  13. 1
      dolphinscheduler-ui/src/views/projects/task/components/node/types.ts

2
docs/docs/en/guide/upgrade/incompatible.md

@ -9,4 +9,4 @@ This document records the incompatible updates between each version. You need to
## 3.0.0 ## 3.0.0
* Copy and import workflow without 'copy' suffix [#10607](https://github.com/apache/dolphinscheduler/pull/10607) * Copy and import workflow without 'copy' suffix [#10607](https://github.com/apache/dolphinscheduler/pull/10607)
* Use semicolon as default sql segment separator [#10869](https://github.com/apache/dolphinscheduler/pull/10869)

4
docs/docs/zh/guide/task/sql.md

@ -20,9 +20,7 @@ SQL任务类型,用于连接数据库并执行相应SQL。
- sql类型:支持查询和非查询两种。 - sql类型:支持查询和非查询两种。
- 查询:支持 `DML select` 类型的命令,是有结果集返回的,可以指定邮件通知为表格、附件或表格附件三种模板; - 查询:支持 `DML select` 类型的命令,是有结果集返回的,可以指定邮件通知为表格、附件或表格附件三种模板;
- 非查询:支持 `DDL`全部命令 和 `DML update、delete、insert` 三种类型的命令; - 非查询:支持 `DDL`全部命令 和 `DML update、delete、insert` 三种类型的命令;
- 分段执行符号:提供在数据源不支持一次执行多段SQL语句时,拆分SQL语句的符号来进行多次调用数据源执行方法。 - 默认采用`;\n`作为SQL分隔符,拆分成多段SQL语句执行。Hive支持一次执行多段SQL语句,故不会拆分。
例子:1.当数据源选择Hive数据源时,不需要填写此参数。因为Hive数据源本身支持一次执行多段SQL语句;
2.当数据源选择MySQL数据源时,并且要执行多段SQL语句时,需要填写此参数为分号 `;`。因为MySQL数据源不支持一次执行多段SQL语句;
- sql参数:输入参数格式为key1=value1;key2=value2… - sql参数:输入参数格式为key1=value1;key2=value2…
- sql语句:SQL语句 - sql语句:SQL语句
- UDF函数:对于HIVE类型的数据源,可以引用资源中心中创建的UDF函数,其他类型的数据源暂不支持UDF函数。 - UDF函数:对于HIVE类型的数据源,可以引用资源中心中创建的UDF函数,其他类型的数据源暂不支持UDF函数。

2
docs/docs/zh/guide/upgrade/incompatible.md

@ -9,4 +9,4 @@
## 3.0.0 ## 3.0.0
* Copy and import workflow without 'copy' suffix [#10607](https://github.com/apache/dolphinscheduler/pull/10607) * Copy and import workflow without 'copy' suffix [#10607](https://github.com/apache/dolphinscheduler/pull/10607)
* Use semicolon as default sql segment separator [#10869](https://github.com/apache/dolphinscheduler/pull/10869)

8
dolphinscheduler-spi/src/main/java/org/apache/dolphinscheduler/spi/enums/DbType.java

@ -75,4 +75,12 @@ public enum DbType {
public boolean isHive() { public boolean isHive() {
return this == DbType.HIVE; return this == DbType.HIVE;
} }
/**
* support execute multiple segmented statements at a time
* @return
*/
public boolean isSupportMultipleStatement() {
return isHive() || this == DbType.SPARK;
}
} }

18
dolphinscheduler-task-plugin/dolphinscheduler-task-api/src/main/java/org/apache/dolphinscheduler/plugin/task/api/parameters/SqlParameters.java

@ -114,15 +114,6 @@ public class SqlParameters extends AbstractParameters {
private int limit; private int limit;
/**
* segment separator
*
* <p>The segment separator is used
* when the data source does not support multi-segment SQL execution,
* and the client needs to split the SQL and execute it multiple times.</p>
*/
private String segmentSeparator;
public int getLimit() { public int getLimit() {
return limit; return limit;
} }
@ -235,14 +226,6 @@ public class SqlParameters extends AbstractParameters {
this.groupId = groupId; this.groupId = groupId;
} }
public String getSegmentSeparator() {
return segmentSeparator;
}
public void setSegmentSeparator(String segmentSeparator) {
this.segmentSeparator = segmentSeparator;
}
@Override @Override
public boolean checkParameters() { public boolean checkParameters() {
return datasource != 0 && StringUtils.isNotEmpty(type) && StringUtils.isNotEmpty(sql); return datasource != 0 && StringUtils.isNotEmpty(type) && StringUtils.isNotEmpty(sql);
@ -310,7 +293,6 @@ public class SqlParameters extends AbstractParameters {
+ ", sendEmail=" + sendEmail + ", sendEmail=" + sendEmail
+ ", displayRows=" + displayRows + ", displayRows=" + displayRows
+ ", limit=" + limit + ", limit=" + limit
+ ", segmentSeparator=" + segmentSeparator
+ ", udfs='" + udfs + '\'' + ", udfs='" + udfs + '\''
+ ", showType='" + showType + '\'' + ", showType='" + showType + '\''
+ ", connParams='" + connParams + '\'' + ", connParams='" + connParams + '\''

64
dolphinscheduler-task-plugin/dolphinscheduler-task-sql/src/main/java/org/apache/dolphinscheduler/plugin/task/sql/SqlSplitter.java

@ -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 org.apache.dolphinscheduler.plugin.task.sql;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.google.common.base.Strings;
public class SqlSplitter {
private SqlSplitter() {
}
private static final String LINE_SEPARATOR = "\n";
/**
* split sql by segment separator
* <p>The segment separator is used
* when the data source does not support multi-segment SQL execution,
* and the client needs to split the SQL and execute it multiple times.</p>
* @param sql
* @param segmentSeparator
* @return
*/
public static List<String> split(String sql, String segmentSeparator) {
if (Strings.isNullOrEmpty(segmentSeparator)) {
return Collections.singletonList(sql);
}
String[] lines = sql.split(LINE_SEPARATOR);
List<String> segments = new ArrayList<>();
StringBuilder stmt = new StringBuilder();
for (String line : lines) {
if (line.trim().isEmpty() || line.startsWith("--")) {
continue;
}
stmt.append(LINE_SEPARATOR).append(line);
if (line.trim().endsWith(segmentSeparator)) {
segments.add(stmt.toString());
stmt.setLength(0);
}
}
if (stmt.length() > 0) {
segments.add(stmt.toString());
}
return segments;
}
}

46
dolphinscheduler-task-plugin/dolphinscheduler-task-sql/src/main/java/org/apache/dolphinscheduler/plugin/task/sql/SqlTask.java

@ -17,9 +17,6 @@
package org.apache.dolphinscheduler.plugin.task.sql; package org.apache.dolphinscheduler.plugin.task.sql;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.dolphinscheduler.plugin.datasource.api.plugin.DataSourceClientProvider; import org.apache.dolphinscheduler.plugin.datasource.api.plugin.DataSourceClientProvider;
import org.apache.dolphinscheduler.plugin.datasource.api.utils.CommonUtils; import org.apache.dolphinscheduler.plugin.datasource.api.utils.CommonUtils;
import org.apache.dolphinscheduler.plugin.datasource.api.utils.DataSourceUtils; import org.apache.dolphinscheduler.plugin.datasource.api.utils.DataSourceUtils;
@ -38,7 +35,8 @@ import org.apache.dolphinscheduler.spi.datasource.BaseConnectionParam;
import org.apache.dolphinscheduler.spi.enums.DbType; import org.apache.dolphinscheduler.spi.enums.DbType;
import org.apache.dolphinscheduler.spi.utils.JSONUtils; import org.apache.dolphinscheduler.spi.utils.JSONUtils;
import org.apache.dolphinscheduler.spi.utils.StringUtils; import org.apache.dolphinscheduler.spi.utils.StringUtils;
import org.slf4j.Logger;
import org.apache.commons.collections4.CollectionUtils;
import java.sql.Connection; import java.sql.Connection;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
@ -48,6 +46,7 @@ import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -56,6 +55,11 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.slf4j.Logger;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
public class SqlTask extends AbstractTask { public class SqlTask extends AbstractTask {
/** /**
@ -88,6 +92,8 @@ public class SqlTask extends AbstractTask {
public static final int TEST_FLAG_YES = 1; public static final int TEST_FLAG_YES = 1;
private static final String SQL_SEPARATOR = ";\n";
/** /**
* Abstract Yarn Task * Abstract Yarn Task
* *
@ -127,15 +133,18 @@ public class SqlTask extends AbstractTask {
sqlParameters.getConnParams(), sqlParameters.getConnParams(),
sqlParameters.getVarPool(), sqlParameters.getVarPool(),
sqlParameters.getLimit()); sqlParameters.getLimit());
String separator = SQL_SEPARATOR;
try { try {
// get datasource // get datasource
baseConnectionParam = (BaseConnectionParam) DataSourceUtils.buildConnectionParams( baseConnectionParam = (BaseConnectionParam) DataSourceUtils.buildConnectionParams(
DbType.valueOf(sqlParameters.getType()), DbType.valueOf(sqlParameters.getType()),
sqlTaskExecutionContext.getConnectionParams()); sqlTaskExecutionContext.getConnectionParams());
if (DbType.valueOf(sqlParameters.getType()).isSupportMultipleStatement()) {
separator = "";
}
// ready to execute SQL and parameter entity Map // ready to execute SQL and parameter entity Map
List<SqlBinds> mainStatementSqlBinds = SqlSplitter.split(sqlParameters.getSql(), sqlParameters.getSegmentSeparator()) List<SqlBinds> mainStatementSqlBinds = split(sqlParameters.getSql(), separator)
.stream() .stream()
.map(this::getSqlAndSqlParamsMap) .map(this::getSqlAndSqlParamsMap)
.collect(Collectors.toList()); .collect(Collectors.toList());
@ -170,6 +179,31 @@ public class SqlTask extends AbstractTask {
} }
/**
* split sql by segment separator
* <p>The segment separator is used
* when the data source does not support multi-segment SQL execution,
* and the client needs to split the SQL and execute it multiple times.</p>
* @param sql
* @param segmentSeparator
* @return
*/
public static List<String> split(String sql, String segmentSeparator) {
if (StringUtils.isEmpty(segmentSeparator)) {
return Collections.singletonList(sql);
}
String[] lines = sql.split(segmentSeparator);
List<String> segments = new ArrayList<>();
for (String line : lines) {
if (line.trim().isEmpty() || line.startsWith("--")) {
continue;
}
segments.add(line);
}
return segments;
}
/** /**
* execute function and sql * execute function and sql
* *

2
dolphinscheduler-ui/src/locales/en_US/project.ts

@ -648,8 +648,6 @@ export default {
emr_flow_define_json_tips: 'Please enter the definition of the job flow.', emr_flow_define_json_tips: 'Please enter the definition of the job flow.',
emr_steps_define_json: 'stepsDefineJson', emr_steps_define_json: 'stepsDefineJson',
emr_steps_define_json_tips: 'Please enter the definition of the emr step.', emr_steps_define_json_tips: 'Please enter the definition of the emr step.',
segment_separator: 'Segment Execution Separator',
segment_separator_tips: 'Please enter the segment execution separator',
zeppelin_note_id: 'zeppelinNoteId', zeppelin_note_id: 'zeppelinNoteId',
zeppelin_note_id_tips: 'Please enter the note id of your zeppelin note', zeppelin_note_id_tips: 'Please enter the note id of your zeppelin note',
zeppelin_paragraph_id: 'zeppelinParagraphId', zeppelin_paragraph_id: 'zeppelinParagraphId',

2
dolphinscheduler-ui/src/locales/zh_CN/project.ts

@ -642,8 +642,6 @@ export default {
emr_flow_define_json_tips: '请输入工作流定义', emr_flow_define_json_tips: '请输入工作流定义',
emr_steps_define_json: 'stepsDefineJson', emr_steps_define_json: 'stepsDefineJson',
emr_steps_define_json_tips: '请输入EMR步骤定义', emr_steps_define_json_tips: '请输入EMR步骤定义',
segment_separator: '分段执行符号',
segment_separator_tips: '请输入分段执行符号',
zeppelin_note_id: 'zeppelinNoteId', zeppelin_note_id: 'zeppelinNoteId',
zeppelin_note_id_tips: '请输入zeppelin note id', zeppelin_note_id_tips: '请输入zeppelin note id',
zeppelin_paragraph_id: 'zeppelinParagraphId', zeppelin_paragraph_id: 'zeppelinParagraphId',

10
dolphinscheduler-ui/src/views/projects/task/components/node/fields/use-sql-type.ts

@ -24,7 +24,6 @@ import type { IJsonItem } from '../types'
export function useSqlType(model: { [field: string]: any }): IJsonItem[] { export function useSqlType(model: { [field: string]: any }): IJsonItem[] {
const { t } = useI18n() const { t } = useI18n()
const querySpan = computed(() => (model.sqlType === '0' ? 6 : 0)) const querySpan = computed(() => (model.sqlType === '0' ? 6 : 0))
const nonQuerySpan = computed(() => (model.sqlType === '1' ? 18 : 0))
const emailSpan = computed(() => const emailSpan = computed(() =>
model.sqlType === '0' && model.sendEmail ? 24 : 0 model.sqlType === '0' && model.sendEmail ? 24 : 0
) )
@ -68,15 +67,6 @@ export function useSqlType(model: { [field: string]: any }): IJsonItem[] {
required: true required: true
} }
}, },
{
type: 'input',
field: 'segmentSeparator',
name: t('project.node.segment_separator'),
props: {
placeholder: t('project.node.segment_separator_tips')
},
span: nonQuerySpan
},
{ {
type: 'switch', type: 'switch',
field: 'sendEmail', field: 'sendEmail',

1
dolphinscheduler-ui/src/views/projects/task/components/node/format-data.ts

@ -189,7 +189,6 @@ export function formatParams(data: INodeData): {
taskParams.sqlType = data.sqlType taskParams.sqlType = data.sqlType
taskParams.preStatements = data.preStatements taskParams.preStatements = data.preStatements
taskParams.postStatements = data.postStatements taskParams.postStatements = data.postStatements
taskParams.segmentSeparator = data.segmentSeparator
taskParams.sendEmail = data.sendEmail taskParams.sendEmail = data.sendEmail
taskParams.displayRows = data.displayRows taskParams.displayRows = data.displayRows
if (data.sqlType === '0' && data.sendEmail) { if (data.sqlType === '0' && data.sendEmail) {

1
dolphinscheduler-ui/src/views/projects/task/components/node/tasks/use-sql.ts

@ -46,7 +46,6 @@ export function useSql({
timeout: 30, timeout: 30,
type: 'MYSQL', type: 'MYSQL',
displayRows: 10, displayRows: 10,
segmentSeparator: '',
sql: '', sql: '',
sqlType: '0', sqlType: '0',
preStatements: [], preStatements: [],

1
dolphinscheduler-ui/src/views/projects/task/components/node/types.ts

@ -253,7 +253,6 @@ interface ITaskParams {
datasource?: string datasource?: string
sql?: string sql?: string
sqlType?: string sqlType?: string
segmentSeparator?: string
sendEmail?: boolean sendEmail?: boolean
displayRows?: number displayRows?: number
title?: string title?: string

Loading…
Cancel
Save