From 30cc169930d4ea85e1823e9df8aafcbb7ffc8ba1 Mon Sep 17 00:00:00 2001 From: qianmoQ Date: Sun, 29 Oct 2023 02:25:19 +0800 Subject: [PATCH 1/2] [Metadata] [Editor] Supports transactions to execute multiple non-query SQL --- .../datacap/spi/adapter/JdbcAdapter.java | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/core/datacap-spi/src/main/java/io/edurt/datacap/spi/adapter/JdbcAdapter.java b/core/datacap-spi/src/main/java/io/edurt/datacap/spi/adapter/JdbcAdapter.java index 7cfb5671..88f725eb 100644 --- a/core/datacap-spi/src/main/java/io/edurt/datacap/spi/adapter/JdbcAdapter.java +++ b/core/datacap-spi/src/main/java/io/edurt/datacap/spi/adapter/JdbcAdapter.java @@ -11,10 +11,10 @@ import io.edurt.datacap.spi.model.Time; import lombok.extern.slf4j.Slf4j; import java.sql.Connection; -import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; +import java.sql.Statement; import java.util.ArrayList; import java.util.Date; import java.util.List; @@ -47,11 +47,11 @@ public class JdbcAdapter Connection connection = (Connection) this.jdbcConnection.getConnection(); JdbcConfigure configure = (JdbcConfigure) this.jdbcConnection.getConfigure(); if (response.getIsConnected()) { - try (PreparedStatement statement = connection.prepareStatement(content)) { + try (Statement statement = connection.createStatement()) { List headers = new ArrayList<>(); List types = new ArrayList<>(); List columns = new ArrayList<>(); - try (ResultSet resultSet = statement.executeQuery()) { + try (ResultSet resultSet = statement.executeQuery(content)) { boolean isPresent = true; JdbcColumn jdbcColumn = new JdbcColumn(resultSet); while (resultSet.next()) { @@ -75,10 +75,27 @@ public class JdbcAdapter headers.add("result"); types.add(Integer.class.getSimpleName()); List _columns = new ArrayList<>(); - _columns.add(statement.executeUpdate()); + connection.setAutoCommit(false); + String[] parts = content.replaceAll("[\\r\\n|\\r|\\n]+", " ") + .split("(?<=\\);)|(?<=\\r\\n)|(?<=\\r)|(?<=\\n)|(?<=\\n;)|(?<=\\r;)|(?<=\\r\\n;)|(?<=;)"); + int count = 0; + for (String part : parts) { + if (!part.trim().isEmpty()) { + count += statement.executeUpdate(part); + } + } + _columns.add(count); + connection.commit(); columns.add(handlerFormatter(configure.getFormat(), headers, _columns)); } catch (SQLException updateEx) { + try { + connection.rollback(); + } + catch (SQLException rollbackEx) { + log.error("Rollback failed ", rollbackEx); + throw new SQLException(rollbackEx); + } throw new SQLException(updateEx); } } From e6932723638f997bd24eb4c7fbe187871c10753b Mon Sep 17 00:00:00 2001 From: qianmoQ Date: Sun, 29 Oct 2023 13:48:21 +0800 Subject: [PATCH 2/2] [Metadata] [Editor] The transformation is deleted and updated to multiple SQL statements --- .../edurt/datacap/common/sql/SqlBuilder.java | 4 + .../sql/builder/BaseAbstractBuilder.java | 16 ++ .../common/sql/builder/DeleteBuilder.java | 7 +- .../common/sql/builder/UpdateBuilder.java | 6 + .../service/impl/TableServiceImpl.java | 138 ++++++++++-------- 5 files changed, 106 insertions(+), 65 deletions(-) diff --git a/core/datacap-common/src/main/java/io/edurt/datacap/common/sql/SqlBuilder.java b/core/datacap-common/src/main/java/io/edurt/datacap/common/sql/SqlBuilder.java index 0b7ead1b..7da1dc9c 100644 --- a/core/datacap-common/src/main/java/io/edurt/datacap/common/sql/SqlBuilder.java +++ b/core/datacap-common/src/main/java/io/edurt/datacap/common/sql/SqlBuilder.java @@ -127,6 +127,8 @@ public class SqlBuilder if (configure.getWhere() != null) { UpdateBuilder.WHERE(applyUpdateWhere()); } + + UpdateBuilder.END(); return UpdateBuilder.SQL(); } @@ -143,6 +145,8 @@ public class SqlBuilder if (configure.getWhere() != null) { DeleteBuilder.WHERE(applyUpdateWhere()); } + + DeleteBuilder.END(); return DeleteBuilder.SQL(); } } diff --git a/core/datacap-common/src/main/java/io/edurt/datacap/common/sql/builder/BaseAbstractBuilder.java b/core/datacap-common/src/main/java/io/edurt/datacap/common/sql/builder/BaseAbstractBuilder.java index 7a8aeceb..53d5d73b 100644 --- a/core/datacap-common/src/main/java/io/edurt/datacap/common/sql/builder/BaseAbstractBuilder.java +++ b/core/datacap-common/src/main/java/io/edurt/datacap/common/sql/builder/BaseAbstractBuilder.java @@ -403,6 +403,12 @@ abstract class BaseAbstractBuilder return getSelf(); } + public T END() + { + sql().end = true; + return getSelf(); + } + private SQLStatement sql() { return sql; @@ -513,6 +519,7 @@ abstract class BaseAbstractBuilder List columns = new ArrayList<>(); List> valuesList = new ArrayList<>(); boolean distinct; + boolean end; String offset; String limit; LimitingRowsStrategy limitingRowsStrategy = LimitingRowsStrategy.NOP; @@ -580,6 +587,9 @@ abstract class BaseAbstractBuilder for (int i = 0; i < valuesList.size(); i++) { sqlClause(builder, i > 0 ? "," : "VALUES", valuesList.get(i), "(", ")", ", "); } + if (end) { + builder.append(";"); + } return builder.toString(); } @@ -588,6 +598,9 @@ abstract class BaseAbstractBuilder sqlClause(builder, "DELETE FROM", tables, "", "", ""); sqlClause(builder, "WHERE", where, "(", ")", " AND "); limitingRowsStrategy.appendClause(builder, null, limit); + if (end) { + builder.append(";"); + } return builder.toString(); } @@ -598,6 +611,9 @@ abstract class BaseAbstractBuilder sqlClause(builder, "SET", sets, "", "", ", "); sqlClause(builder, "WHERE", where, "(", ")", " AND "); limitingRowsStrategy.appendClause(builder, null, limit); + if (end) { + builder.append(";"); + } return builder.toString(); } diff --git a/core/datacap-common/src/main/java/io/edurt/datacap/common/sql/builder/DeleteBuilder.java b/core/datacap-common/src/main/java/io/edurt/datacap/common/sql/builder/DeleteBuilder.java index 6c559f02..da2fb99b 100644 --- a/core/datacap-common/src/main/java/io/edurt/datacap/common/sql/builder/DeleteBuilder.java +++ b/core/datacap-common/src/main/java/io/edurt/datacap/common/sql/builder/DeleteBuilder.java @@ -5,7 +5,7 @@ import java.util.List; public class DeleteBuilder { private static final ThreadLocal localSQL = new ThreadLocal<>(); - private static String symbol = " OR "; + private static String symbol = " AND "; static { BEGIN(); @@ -40,6 +40,11 @@ public class DeleteBuilder sql().WHERE(String.join(symbol, conditions)); } + public static void END() + { + sql().END(); + } + public static String SQL() { try { diff --git a/core/datacap-common/src/main/java/io/edurt/datacap/common/sql/builder/UpdateBuilder.java b/core/datacap-common/src/main/java/io/edurt/datacap/common/sql/builder/UpdateBuilder.java index 701a312e..c21b2bff 100644 --- a/core/datacap-common/src/main/java/io/edurt/datacap/common/sql/builder/UpdateBuilder.java +++ b/core/datacap-common/src/main/java/io/edurt/datacap/common/sql/builder/UpdateBuilder.java @@ -60,9 +60,15 @@ public class UpdateBuilder sql().AND(); } + public static void END() + { + sql().END(); + } + public static String SQL() { try { + sql().END(); return sql().toString(); } finally { diff --git a/core/datacap-service/src/main/java/io/edurt/datacap/service/service/impl/TableServiceImpl.java b/core/datacap-service/src/main/java/io/edurt/datacap/service/service/impl/TableServiceImpl.java index 2661cad4..030da39c 100644 --- a/core/datacap-service/src/main/java/io/edurt/datacap/service/service/impl/TableServiceImpl.java +++ b/core/datacap-service/src/main/java/io/edurt/datacap/service/service/impl/TableServiceImpl.java @@ -180,33 +180,22 @@ public class TableServiceImpl Configure updateConfigure = source.toConfigure(); updateConfigure.setFormat(FormatType.NONE); plugin.connect(updateConfigure); - SqlBody body = SqlBody.builder() - .type(SqlType.UPDATE) - .database(table.getDatabase().getName()) - .table(table.getName()) - .columns(configure.getColumns()) - .where(applyColumns(table, configure).stream() - .distinct() - .collect(Collectors.toList())) - .build(); - String sql = new SqlBuilder(body).getSql(); - Response response; - if (configure.isPreview()) { - response = Response.builder() - .isSuccessful(true) - .isConnected(true) - .headers(Lists.newArrayList()) - .columns(Lists.newArrayList()) - .types(Lists.newArrayList()) - .content(sql) + List allSql = Lists.newArrayList(); + configure.getColumns().forEach(v -> { + SqlBody body = SqlBody.builder() + .type(SqlType.UPDATE) + .database(table.getDatabase().getName()) + .table(table.getName()) + .columns(Arrays.asList(v)) + .where(applyColumns(table, configure, v) + .stream() + .distinct() + .collect(Collectors.toList())) .build(); - } - else { - response = plugin.execute(sql); - plugin.destroy(); - response.setContent(sql); - } - return CommonResponse.success(response); + allSql.add(new SqlBuilder(body).getSql()); + }); + String sql = String.join("\n\n", allSql); + return CommonResponse.success(getResponse(configure, plugin, sql)); } catch (Exception ex) { return CommonResponse.failure(ExceptionUtils.getMessage(ex)); @@ -228,37 +217,33 @@ public class TableServiceImpl Configure updateConfigure = source.toConfigure(); updateConfigure.setFormat(FormatType.NONE); plugin.connect(updateConfigure); - SqlBody body = SqlBody.builder() - .type(SqlType.DELETE) - .database(table.getDatabase().getName()) - .table(table.getName()) - .where(applyColumns(table, configure)) - .build(); - String sql = new SqlBuilder(body).getSql(); - Response response; - if (configure.isPreview()) { - response = Response.builder() - .isSuccessful(true) - .isConnected(true) - .headers(Lists.newArrayList()) - .columns(Lists.newArrayList()) - .types(Lists.newArrayList()) - .content(sql) + List allSql = Lists.newArrayList(); + configure.getColumns().forEach(v -> { + SqlBody body = SqlBody.builder() + .type(SqlType.DELETE) + .database(table.getDatabase().getName()) + .table(table.getName()) + .where(applyColumns(table, configure, v)) .build(); - } - else { - response = plugin.execute(sql); - plugin.destroy(); - response.setContent(sql); - } - return CommonResponse.success(response); + allSql.add(new SqlBuilder(body).getSql()); + }); + String sql = String.join("\n\n", allSql); + return CommonResponse.success(getResponse(configure, plugin, sql)); } catch (Exception ex) { return CommonResponse.failure(ExceptionUtils.getMessage(ex)); } } - private List applyColumns(TableEntity table, TableFilter configure) + /** + * Applies the columns of a table to a given configuration. + * + * @param table the table entity containing the columns + * @param configure the table filter configuration to apply the columns to + * @param column the SQL column to apply + * @return a list of SQL columns that match the applied configuration + */ + private List applyColumns(TableEntity table, TableFilter configure, SqlColumn column) { List wheres = Lists.newArrayList(); List originColumns = table.getColumns() @@ -267,25 +252,50 @@ public class TableServiceImpl .collect(Collectors.toList()); if (originColumns.size() > 0) { // If the table contains a primary key, update the data using the primary key as a condition - originColumns.forEach(item -> configure.getColumns() - .stream() - .forEach(v -> wheres.add(SqlColumn.builder() - .column(item.getName()) - .operator(SqlOperator.EQ) - .value(String.valueOf(v.getOriginal().get(item.getName()))) - .build()))); + originColumns.forEach(item -> wheres.add(SqlColumn.builder() + .column(item.getName()) + .operator(SqlOperator.EQ) + .value(String.valueOf(column.getOriginal().get(item.getName()))) + .build())); } else { // If the current data does not have a primary key, it is updated based on all data columns table.getColumns() - .forEach(item -> configure.getColumns() - .stream() - .forEach(v -> wheres.add(SqlColumn.builder() - .column(item.getName()) - .operator(SqlOperator.EQ) - .value(String.valueOf(v.getOriginal().get(item.getName()))) - .build()))); + .forEach(item -> wheres.add(SqlColumn.builder() + .column(item.getName()) + .operator(SqlOperator.EQ) + .value(String.valueOf(column.getOriginal().get(item.getName()))) + .build())); } return wheres; } + + /** + * Retrieves a response based on the provided table filter, plugin, and SQL query. + * + * @param configure the table filter to configure the response + * @param plugin the plugin to execute the SQL query + * @param sql the SQL query to execute + * @return the response containing the result of the SQL query + */ + private Response getResponse(TableFilter configure, Plugin plugin, String sql) + { + Response response; + if (configure.isPreview()) { + response = Response.builder() + .isSuccessful(true) + .isConnected(true) + .headers(Lists.newArrayList()) + .columns(Lists.newArrayList()) + .types(Lists.newArrayList()) + .content(sql) + .build(); + } + else { + response = plugin.execute(sql); + plugin.destroy(); + response.setContent(sql); + } + return response; + } }