mirror of
https://gitee.com/devlive-community/datacap.git
synced 2024-12-02 20:17:45 +08:00
[Core] Support dsl query (#216)
This commit is contained in:
commit
124ab96456
20
builder/pom.xml
Normal file
20
builder/pom.xml
Normal file
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>io.edurt.datacap</groupId>
|
||||
<artifactId>incubator-datacap</artifactId>
|
||||
<version>1.5.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<groupId>io.edurt.datacap.plugin.builder</groupId>
|
||||
<artifactId>datacap-builder</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<name>DataCap for builder</name>
|
||||
|
||||
<modules>
|
||||
<module>sql</module>
|
||||
</modules>
|
||||
</project>
|
38
builder/sql/pom.xml
Normal file
38
builder/sql/pom.xml
Normal file
@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>io.edurt.datacap.plugin.builder</groupId>
|
||||
<artifactId>datacap-builder</artifactId>
|
||||
<version>1.5.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>datacap-builder-sql</artifactId>
|
||||
<name>DataCap for builder (SQL)</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.edurt.datacap.common</groupId>
|
||||
<artifactId>datacap-common</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.findbugs</groupId>
|
||||
<artifactId>findbugs</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
<version>${plugin.maven.checkstyle.version}</version>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
@ -0,0 +1,77 @@
|
||||
package io.edurt.datacap.plugin.builder.sql;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||
import io.edurt.datacap.plugin.builder.sql.builder.SelectBuilder;
|
||||
import io.edurt.datacap.plugin.builder.sql.configure.SqlBody;
|
||||
import io.edurt.datacap.plugin.builder.sql.configure.SqlColumn;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@SuppressFBWarnings(value = {"DM_STRING_VOID_CTOR"},
|
||||
justification = "I prefer to suppress these FindBugs warnings")
|
||||
public class SqlBuilder
|
||||
{
|
||||
private final SqlBody configure;
|
||||
|
||||
public SqlBuilder(SqlBody configure)
|
||||
{
|
||||
this.configure = configure;
|
||||
}
|
||||
|
||||
public String getSql()
|
||||
{
|
||||
String sql = new String();
|
||||
switch (configure.getType()) {
|
||||
case SELECT:
|
||||
sql = getSelect();
|
||||
break;
|
||||
default:
|
||||
Preconditions.checkArgument(false, "Not support type");
|
||||
}
|
||||
return sql;
|
||||
}
|
||||
|
||||
private String applyDatabaseAndTable()
|
||||
{
|
||||
Preconditions.checkArgument(StringUtils.isNotEmpty(configure.getTable()), "The table name must be specified");
|
||||
if (StringUtils.isNotEmpty(configure.getDatabase())) {
|
||||
return String.format("%s.%s", configure.getDatabase(), configure.getTable());
|
||||
}
|
||||
return configure.getTable();
|
||||
}
|
||||
|
||||
private List<String> applySelectColumns()
|
||||
{
|
||||
Preconditions.checkArgument(ArrayUtils.isNotEmpty(configure.getColumns().toArray(new SqlColumn[0])), "The columns must be specified");
|
||||
return configure.getColumns().stream()
|
||||
.map(SqlColumn::getColumn)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private List<String> applyOrderByColumns()
|
||||
{
|
||||
return configure.getOrders().stream()
|
||||
.map(v -> String.join(" ", v.getColumn(), v.getOrder().name()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private String getSelect()
|
||||
{
|
||||
SelectBuilder.BEGIN();
|
||||
SelectBuilder.SELECT(applySelectColumns());
|
||||
SelectBuilder.FROM(applyDatabaseAndTable());
|
||||
|
||||
if (ObjectUtils.isNotEmpty(configure.getOrders())) {
|
||||
SelectBuilder.ORDER_BY(applyOrderByColumns());
|
||||
}
|
||||
|
||||
SelectBuilder.LIMIT(configure.getLimit());
|
||||
SelectBuilder.OFFSET(configure.getOffset());
|
||||
return SelectBuilder.SQL();
|
||||
}
|
||||
}
|
@ -0,0 +1,637 @@
|
||||
// CHECKSTYLE:OFF
|
||||
package io.edurt.datacap.plugin.builder.sql.builder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
// CHECKSTYLE:DISABLE:<CheckName>
|
||||
abstract class BaseAbstractBuilder<T>
|
||||
{
|
||||
|
||||
private static final String AND = ") \nAND (";
|
||||
private static final String OR = ") \nOR (";
|
||||
|
||||
private final SQLStatement sql = new SQLStatement();
|
||||
|
||||
public abstract T getSelf();
|
||||
|
||||
public T UPDATE(String table)
|
||||
{
|
||||
sql().statementType = SQLStatement.StatementType.UPDATE;
|
||||
sql().tables.add(table);
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
public T SET(String sets)
|
||||
{
|
||||
sql().sets.add(sets);
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.4.2
|
||||
*/
|
||||
public T SET(String... sets)
|
||||
{
|
||||
sql().sets.addAll(Arrays.asList(sets));
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
public T INSERT_INTO(String tableName)
|
||||
{
|
||||
sql().statementType = SQLStatement.StatementType.INSERT;
|
||||
sql().tables.add(tableName);
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
public T VALUES(String columns, String values)
|
||||
{
|
||||
INTO_COLUMNS(columns);
|
||||
INTO_VALUES(values);
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.4.2
|
||||
*/
|
||||
public T INTO_COLUMNS(String... columns)
|
||||
{
|
||||
sql().columns.addAll(Arrays.asList(columns));
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.4.2
|
||||
*/
|
||||
public T INTO_VALUES(String... values)
|
||||
{
|
||||
List<String> list = sql().valuesList.get(sql().valuesList.size() - 1);
|
||||
for (String value : values) {
|
||||
list.add(value);
|
||||
}
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
public T SELECT(String columns)
|
||||
{
|
||||
sql().statementType = SQLStatement.StatementType.SELECT;
|
||||
sql().select.add(columns);
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.4.2
|
||||
*/
|
||||
public T SELECT(String... columns)
|
||||
{
|
||||
sql().statementType = SQLStatement.StatementType.SELECT;
|
||||
sql().select.addAll(Arrays.asList(columns));
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
public T SELECT_DISTINCT(String columns)
|
||||
{
|
||||
sql().distinct = true;
|
||||
SELECT(columns);
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.4.2
|
||||
*/
|
||||
public T SELECT_DISTINCT(String... columns)
|
||||
{
|
||||
sql().distinct = true;
|
||||
SELECT(columns);
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
public T DELETE_FROM(String table)
|
||||
{
|
||||
sql().statementType = SQLStatement.StatementType.DELETE;
|
||||
sql().tables.add(table);
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
public T FROM(String table)
|
||||
{
|
||||
sql().tables.add(table);
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.4.2
|
||||
*/
|
||||
public T FROM(String... tables)
|
||||
{
|
||||
sql().tables.addAll(Arrays.asList(tables));
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
public T JOIN(String join)
|
||||
{
|
||||
sql().join.add(join);
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.4.2
|
||||
*/
|
||||
public T JOIN(String... joins)
|
||||
{
|
||||
sql().join.addAll(Arrays.asList(joins));
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
public T INNER_JOIN(String join)
|
||||
{
|
||||
sql().innerJoin.add(join);
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.4.2
|
||||
*/
|
||||
public T INNER_JOIN(String... joins)
|
||||
{
|
||||
sql().innerJoin.addAll(Arrays.asList(joins));
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
public T LEFT_OUTER_JOIN(String join)
|
||||
{
|
||||
sql().leftOuterJoin.add(join);
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.4.2
|
||||
*/
|
||||
public T LEFT_OUTER_JOIN(String... joins)
|
||||
{
|
||||
sql().leftOuterJoin.addAll(Arrays.asList(joins));
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
public T RIGHT_OUTER_JOIN(String join)
|
||||
{
|
||||
sql().rightOuterJoin.add(join);
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.4.2
|
||||
*/
|
||||
public T RIGHT_OUTER_JOIN(String... joins)
|
||||
{
|
||||
sql().rightOuterJoin.addAll(Arrays.asList(joins));
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
public T OUTER_JOIN(String join)
|
||||
{
|
||||
sql().outerJoin.add(join);
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.4.2
|
||||
*/
|
||||
public T OUTER_JOIN(String... joins)
|
||||
{
|
||||
sql().outerJoin.addAll(Arrays.asList(joins));
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
public T WHERE(String conditions)
|
||||
{
|
||||
sql().where.add(conditions);
|
||||
sql().lastList = sql().where;
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.4.2
|
||||
*/
|
||||
public T WHERE(String... conditions)
|
||||
{
|
||||
sql().where.addAll(Arrays.asList(conditions));
|
||||
sql().lastList = sql().where;
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
public T OR()
|
||||
{
|
||||
sql().lastList.add(OR);
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
public T AND()
|
||||
{
|
||||
sql().lastList.add(AND);
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
public T GROUP_BY(String columns)
|
||||
{
|
||||
sql().groupBy.add(columns);
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.4.2
|
||||
*/
|
||||
public T GROUP_BY(String... columns)
|
||||
{
|
||||
sql().groupBy.addAll(Arrays.asList(columns));
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
public T HAVING(String conditions)
|
||||
{
|
||||
sql().having.add(conditions);
|
||||
sql().lastList = sql().having;
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.4.2
|
||||
*/
|
||||
public T HAVING(String... conditions)
|
||||
{
|
||||
sql().having.addAll(Arrays.asList(conditions));
|
||||
sql().lastList = sql().having;
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
public T ORDER_BY(String columns)
|
||||
{
|
||||
sql().orderBy.add(columns);
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.4.2
|
||||
*/
|
||||
public T ORDER_BY(String... columns)
|
||||
{
|
||||
sql().orderBy.addAll(Arrays.asList(columns));
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the limit variable string(e.g. {@code "#{limit}"}).
|
||||
*
|
||||
* @param variable a limit variable string
|
||||
* @return a self instance
|
||||
* @see #OFFSET(String)
|
||||
* @since 3.5.2
|
||||
*/
|
||||
public T LIMIT(String variable)
|
||||
{
|
||||
sql().limit = variable;
|
||||
sql().limitingRowsStrategy = SQLStatement.LimitingRowsStrategy.OFFSET_LIMIT;
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the limit value.
|
||||
*
|
||||
* @param value an offset value
|
||||
* @return a self instance
|
||||
* @see #OFFSET(long)
|
||||
* @since 3.5.2
|
||||
*/
|
||||
public T LIMIT(long value)
|
||||
{
|
||||
return LIMIT(String.valueOf(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the offset variable string(e.g. {@code "#{offset}"}).
|
||||
*
|
||||
* @param variable a offset variable string
|
||||
* @return a self instance
|
||||
* @see #LIMIT(String)
|
||||
* @since 3.5.2
|
||||
*/
|
||||
public T OFFSET(String variable)
|
||||
{
|
||||
sql().offset = variable;
|
||||
sql().limitingRowsStrategy = SQLStatement.LimitingRowsStrategy.OFFSET_LIMIT;
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the offset value.
|
||||
*
|
||||
* @param value an offset value
|
||||
* @return a self instance
|
||||
* @since 3.5.2
|
||||
*/
|
||||
public T OFFSET(long value)
|
||||
{
|
||||
return OFFSET(String.valueOf(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the fetch first rows variable string(e.g. {@code "#{fetchFirstRows}"}).
|
||||
*
|
||||
* @param variable a fetch first rows variable string
|
||||
* @return a self instance
|
||||
* @see #OFFSET_ROWS(String)
|
||||
* @since 3.5.2
|
||||
*/
|
||||
public T FETCH_FIRST_ROWS_ONLY(String variable)
|
||||
{
|
||||
sql().limit = variable;
|
||||
sql().limitingRowsStrategy = SQLStatement.LimitingRowsStrategy.ISO;
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the fetch first rows value.
|
||||
*
|
||||
* @param value a fetch first rows value
|
||||
* @return a self instance
|
||||
* @see #OFFSET_ROWS(long)
|
||||
* @since 3.5.2
|
||||
*/
|
||||
public T FETCH_FIRST_ROWS_ONLY(int value)
|
||||
{
|
||||
return FETCH_FIRST_ROWS_ONLY(String.valueOf(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the offset rows variable string(e.g. {@code "#{offset}"}).
|
||||
*
|
||||
* @param variable a offset rows variable string
|
||||
* @return a self instance
|
||||
* @see #FETCH_FIRST_ROWS_ONLY(String)
|
||||
* @since 3.5.2
|
||||
*/
|
||||
public T OFFSET_ROWS(String variable)
|
||||
{
|
||||
sql().offset = variable;
|
||||
sql().limitingRowsStrategy = SQLStatement.LimitingRowsStrategy.ISO;
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the offset rows value.
|
||||
*
|
||||
* @param value an offset rows value
|
||||
* @return a self instance
|
||||
* @see #FETCH_FIRST_ROWS_ONLY(int)
|
||||
* @since 3.5.2
|
||||
*/
|
||||
public T OFFSET_ROWS(long value)
|
||||
{
|
||||
return OFFSET_ROWS(String.valueOf(value));
|
||||
}
|
||||
|
||||
/*
|
||||
* used to add a new inserted row while do multi-row insert.
|
||||
*
|
||||
* @since 3.5.2
|
||||
*/
|
||||
public T ADD_ROW()
|
||||
{
|
||||
sql().valuesList.add(new ArrayList<>());
|
||||
return getSelf();
|
||||
}
|
||||
|
||||
private SQLStatement sql()
|
||||
{
|
||||
return sql;
|
||||
}
|
||||
|
||||
public <A extends Appendable> A usingAppender(A a)
|
||||
{
|
||||
sql().sql(a);
|
||||
return a;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sql().sql(sb);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static class SafeAppendable
|
||||
{
|
||||
private final Appendable a;
|
||||
private boolean empty = true;
|
||||
|
||||
public SafeAppendable(Appendable a)
|
||||
{
|
||||
super();
|
||||
this.a = a;
|
||||
}
|
||||
|
||||
public SafeAppendable append(CharSequence s)
|
||||
{
|
||||
try {
|
||||
if (empty && s.length() > 0) {
|
||||
empty = false;
|
||||
}
|
||||
a.append(s);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return empty;
|
||||
}
|
||||
}
|
||||
|
||||
private static class SQLStatement
|
||||
{
|
||||
|
||||
public enum StatementType
|
||||
{
|
||||
DELETE, INSERT, SELECT, UPDATE
|
||||
}
|
||||
|
||||
private enum LimitingRowsStrategy
|
||||
{
|
||||
NOP {
|
||||
@Override
|
||||
protected void appendClause(SafeAppendable builder, String offset, String limit)
|
||||
{
|
||||
// NOP
|
||||
}
|
||||
}, ISO {
|
||||
@Override
|
||||
protected void appendClause(SafeAppendable builder, String offset, String limit)
|
||||
{
|
||||
if (offset != null) {
|
||||
builder.append(" OFFSET ").append(offset).append(" ROWS");
|
||||
}
|
||||
if (limit != null) {
|
||||
builder.append(" FETCH FIRST ").append(limit).append(" ROWS ONLY");
|
||||
}
|
||||
}
|
||||
}, OFFSET_LIMIT {
|
||||
@Override
|
||||
protected void appendClause(SafeAppendable builder, String offset, String limit)
|
||||
{
|
||||
if (limit != null) {
|
||||
builder.append(" LIMIT ").append(limit);
|
||||
}
|
||||
if (offset != null) {
|
||||
builder.append(" OFFSET ").append(offset);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
protected abstract void appendClause(SafeAppendable builder, String offset, String limit);
|
||||
}
|
||||
|
||||
StatementType statementType;
|
||||
List<String> sets = new ArrayList<>();
|
||||
List<String> select = new ArrayList<>();
|
||||
List<String> tables = new ArrayList<>();
|
||||
List<String> join = new ArrayList<>();
|
||||
List<String> innerJoin = new ArrayList<>();
|
||||
List<String> outerJoin = new ArrayList<>();
|
||||
List<String> leftOuterJoin = new ArrayList<>();
|
||||
List<String> rightOuterJoin = new ArrayList<>();
|
||||
List<String> where = new ArrayList<>();
|
||||
List<String> having = new ArrayList<>();
|
||||
List<String> groupBy = new ArrayList<>();
|
||||
List<String> orderBy = new ArrayList<>();
|
||||
List<String> lastList = new ArrayList<>();
|
||||
List<String> columns = new ArrayList<>();
|
||||
List<List<String>> valuesList = new ArrayList<>();
|
||||
boolean distinct;
|
||||
String offset;
|
||||
String limit;
|
||||
LimitingRowsStrategy limitingRowsStrategy = LimitingRowsStrategy.NOP;
|
||||
|
||||
public SQLStatement()
|
||||
{
|
||||
// Prevent Synthetic Access
|
||||
valuesList.add(new ArrayList<>());
|
||||
}
|
||||
|
||||
private void sqlClause(SafeAppendable builder, String keyword, List<String> parts, String open, String close, String conjunction)
|
||||
{
|
||||
if (!parts.isEmpty()) {
|
||||
if (!builder.isEmpty()) {
|
||||
builder.append("\n");
|
||||
}
|
||||
builder.append(keyword);
|
||||
builder.append(" ");
|
||||
builder.append(open);
|
||||
String last = "________";
|
||||
for (int i = 0, n = parts.size(); i < n; i++) {
|
||||
String part = parts.get(i);
|
||||
if (i > 0 && !part.equals(AND) && !part.equals(OR) && !last.equals(AND) && !last.equals(OR)) {
|
||||
builder.append(conjunction);
|
||||
}
|
||||
builder.append(part);
|
||||
last = part;
|
||||
}
|
||||
builder.append(close);
|
||||
}
|
||||
}
|
||||
|
||||
private String selectSQL(SafeAppendable builder)
|
||||
{
|
||||
if (distinct) {
|
||||
sqlClause(builder, "SELECT DISTINCT", select, "", "", ", ");
|
||||
}
|
||||
else {
|
||||
sqlClause(builder, "SELECT", select, "", "", ", ");
|
||||
}
|
||||
|
||||
sqlClause(builder, "FROM", tables, "", "", ", ");
|
||||
joins(builder);
|
||||
sqlClause(builder, "WHERE", where, "(", ")", " AND ");
|
||||
sqlClause(builder, "GROUP BY", groupBy, "", "", ", ");
|
||||
sqlClause(builder, "HAVING", having, "(", ")", " AND ");
|
||||
sqlClause(builder, "ORDER BY", orderBy, "", "", ", ");
|
||||
limitingRowsStrategy.appendClause(builder, offset, limit);
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private void joins(SafeAppendable builder)
|
||||
{
|
||||
sqlClause(builder, "JOIN", join, "", "", "\nJOIN ");
|
||||
sqlClause(builder, "INNER JOIN", innerJoin, "", "", "\nINNER JOIN ");
|
||||
sqlClause(builder, "OUTER JOIN", outerJoin, "", "", "\nOUTER JOIN ");
|
||||
sqlClause(builder, "LEFT OUTER JOIN", leftOuterJoin, "", "", "\nLEFT OUTER JOIN ");
|
||||
sqlClause(builder, "RIGHT OUTER JOIN", rightOuterJoin, "", "", "\nRIGHT OUTER JOIN ");
|
||||
}
|
||||
|
||||
private String insertSQL(SafeAppendable builder)
|
||||
{
|
||||
sqlClause(builder, "INSERT INTO", tables, "", "", "");
|
||||
sqlClause(builder, "", columns, "(", ")", ", ");
|
||||
for (int i = 0; i < valuesList.size(); i++) {
|
||||
sqlClause(builder, i > 0 ? "," : "VALUES", valuesList.get(i), "(", ")", ", ");
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private String deleteSQL(SafeAppendable builder)
|
||||
{
|
||||
sqlClause(builder, "DELETE FROM", tables, "", "", "");
|
||||
sqlClause(builder, "WHERE", where, "(", ")", " AND ");
|
||||
limitingRowsStrategy.appendClause(builder, null, limit);
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private String updateSQL(SafeAppendable builder)
|
||||
{
|
||||
sqlClause(builder, "UPDATE", tables, "", "", "");
|
||||
joins(builder);
|
||||
sqlClause(builder, "SET", sets, "", "", ", ");
|
||||
sqlClause(builder, "WHERE", where, "(", ")", " AND ");
|
||||
limitingRowsStrategy.appendClause(builder, null, limit);
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public String sql(Appendable a)
|
||||
{
|
||||
SafeAppendable builder = new SafeAppendable(a);
|
||||
if (statementType == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String answer;
|
||||
|
||||
switch (statementType) {
|
||||
case DELETE:
|
||||
answer = deleteSQL(builder);
|
||||
break;
|
||||
|
||||
case INSERT:
|
||||
answer = insertSQL(builder);
|
||||
break;
|
||||
|
||||
case SELECT:
|
||||
answer = selectSQL(builder);
|
||||
break;
|
||||
|
||||
case UPDATE:
|
||||
answer = updateSQL(builder);
|
||||
break;
|
||||
|
||||
default:
|
||||
answer = null;
|
||||
}
|
||||
|
||||
return answer;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package io.edurt.datacap.plugin.builder.sql.builder;
|
||||
|
||||
class BaseBuilder
|
||||
extends BaseAbstractBuilder<BaseBuilder>
|
||||
{
|
||||
@Override
|
||||
public BaseBuilder getSelf()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
}
|
@ -0,0 +1,108 @@
|
||||
package io.edurt.datacap.plugin.builder.sql.builder;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SelectBuilder
|
||||
{
|
||||
private static final ThreadLocal<BaseBuilder> localSQL = new ThreadLocal<>();
|
||||
private static String symbol = ", ";
|
||||
|
||||
static {
|
||||
BEGIN();
|
||||
}
|
||||
|
||||
private SelectBuilder()
|
||||
{
|
||||
// Prevent Instantiation
|
||||
}
|
||||
|
||||
public static void BEGIN()
|
||||
{
|
||||
RESET();
|
||||
}
|
||||
|
||||
public static void RESET()
|
||||
{
|
||||
localSQL.set(new BaseBuilder());
|
||||
}
|
||||
|
||||
public static void SELECT(String columns)
|
||||
{
|
||||
sql().SELECT(columns);
|
||||
}
|
||||
|
||||
public static void SELECT(List<String> columns)
|
||||
{
|
||||
sql().SELECT(String.join(symbol, columns));
|
||||
}
|
||||
|
||||
public static void SELECT_DISTINCT(String columns)
|
||||
{
|
||||
sql().SELECT_DISTINCT(columns);
|
||||
}
|
||||
|
||||
public static void FROM(String table)
|
||||
{
|
||||
sql().FROM(table);
|
||||
}
|
||||
|
||||
public static void WHERE(String conditions)
|
||||
{
|
||||
sql().WHERE(conditions);
|
||||
}
|
||||
|
||||
public static void OR()
|
||||
{
|
||||
sql().OR();
|
||||
}
|
||||
|
||||
public static void AND()
|
||||
{
|
||||
sql().AND();
|
||||
}
|
||||
|
||||
public static void GROUP_BY(String columns)
|
||||
{
|
||||
sql().GROUP_BY(columns);
|
||||
}
|
||||
|
||||
public static void HAVING(String conditions)
|
||||
{
|
||||
sql().HAVING(conditions);
|
||||
}
|
||||
|
||||
public static void ORDER_BY(String columns)
|
||||
{
|
||||
sql().ORDER_BY(columns);
|
||||
}
|
||||
|
||||
public static void ORDER_BY(List<String> columns)
|
||||
{
|
||||
sql().ORDER_BY(String.join(symbol, columns));
|
||||
}
|
||||
|
||||
public static void LIMIT(long value)
|
||||
{
|
||||
sql().LIMIT(value);
|
||||
}
|
||||
|
||||
public static void OFFSET(long value)
|
||||
{
|
||||
sql().OFFSET(value);
|
||||
}
|
||||
|
||||
public static String SQL()
|
||||
{
|
||||
try {
|
||||
return sql().toString();
|
||||
}
|
||||
finally {
|
||||
RESET();
|
||||
}
|
||||
}
|
||||
|
||||
private static BaseBuilder sql()
|
||||
{
|
||||
return localSQL.get();
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package io.edurt.datacap.plugin.builder.sql.configure;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@ToString
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class SqlBody
|
||||
{
|
||||
private String database;
|
||||
private String table;
|
||||
private List<SqlColumn> columns;
|
||||
private List<SqlColumn> orders;
|
||||
private int limit = 10;
|
||||
private int offset = 1;
|
||||
private SqlType type;
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package io.edurt.datacap.plugin.builder.sql.configure;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
|
||||
@Data
|
||||
@ToString
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class SqlColumn
|
||||
{
|
||||
private String column;
|
||||
private SqlOrder order;
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package io.edurt.datacap.plugin.builder.sql.configure;
|
||||
|
||||
public enum SqlOrder
|
||||
{
|
||||
ASC,
|
||||
DESC
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
package io.edurt.datacap.plugin.builder.sql.configure;
|
||||
|
||||
public enum SqlType
|
||||
{
|
||||
SELECT
|
||||
}
|
@ -18,5 +18,9 @@
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
7
pom.xml
7
pom.xml
@ -17,6 +17,7 @@
|
||||
<module>docs</module>
|
||||
<module>assets</module>
|
||||
<module>client</module>
|
||||
<module>builder</module>
|
||||
</modules>
|
||||
|
||||
<name>DataCap(Incubator)</name>
|
||||
@ -73,6 +74,7 @@
|
||||
<logback.version>1.2.11</logback.version>
|
||||
<slf4j.version>1.7.36</slf4j.version>
|
||||
<sql-formatter.version>2.0.3</sql-formatter.version>
|
||||
<guava.version>31.1-jre</guava.version>
|
||||
<commons-beanutils.version>1.9.4</commons-beanutils.version>
|
||||
<assembly-plugin.version>3.1.1</assembly-plugin.version>
|
||||
<plugin.maven.checkstyle.version>3.0.0</plugin.maven.checkstyle.version>
|
||||
@ -168,6 +170,11 @@
|
||||
<artifactId>sql-formatter</artifactId>
|
||||
<version>${sql-formatter.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>${guava.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
|
@ -94,6 +94,11 @@
|
||||
<groupId>io.edurt.datacap</groupId>
|
||||
<artifactId>datacap-spi</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.edurt.datacap.plugin.builder</groupId>
|
||||
<artifactId>datacap-builder-sql</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.edurt.datacap.plugin.jdbc</groupId>
|
||||
<artifactId>datacap-plugin-jdbc-mysql</artifactId>
|
||||
|
@ -0,0 +1,18 @@
|
||||
package io.edurt.datacap.server.body;
|
||||
|
||||
import io.edurt.datacap.plugin.builder.sql.configure.SqlBody;
|
||||
import io.edurt.datacap.spi.FormatType;
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
@ToString
|
||||
public class ExecuteDslBody
|
||||
{
|
||||
private String name;
|
||||
private SqlBody configure;
|
||||
private Map<String, Object> env;
|
||||
private FormatType format = FormatType.NONE;
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package io.edurt.datacap.server.controller.user;
|
||||
|
||||
import io.edurt.datacap.server.body.ExecuteDslBody;
|
||||
import io.edurt.datacap.server.common.Response;
|
||||
import io.edurt.datacap.server.entity.ExecuteEntity;
|
||||
import io.edurt.datacap.server.service.ExecuteService;
|
||||
@ -25,4 +26,10 @@ public class ExecuteController
|
||||
{
|
||||
return this.executeService.execute(configure);
|
||||
}
|
||||
|
||||
@PostMapping(value = {"dsl"})
|
||||
public Response<Object> executeDsl(@RequestBody ExecuteDslBody configure)
|
||||
{
|
||||
return this.executeService.execute(configure);
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,12 @@
|
||||
package io.edurt.datacap.server.service;
|
||||
|
||||
import io.edurt.datacap.server.body.ExecuteDslBody;
|
||||
import io.edurt.datacap.server.common.Response;
|
||||
import io.edurt.datacap.server.entity.ExecuteEntity;
|
||||
|
||||
public interface ExecuteService
|
||||
{
|
||||
Response<Object> execute(ExecuteEntity configure);
|
||||
|
||||
Response<Object> execute(ExecuteDslBody configure);
|
||||
}
|
||||
|
@ -1,7 +1,11 @@
|
||||
package io.edurt.datacap.server.service.impl;
|
||||
|
||||
import com.google.inject.Injector;
|
||||
import io.edurt.datacap.plugin.builder.sql.SqlBuilder;
|
||||
import io.edurt.datacap.plugin.builder.sql.configure.SqlBody;
|
||||
import io.edurt.datacap.plugin.builder.sql.configure.SqlType;
|
||||
import io.edurt.datacap.server.audit.AuditPlugin;
|
||||
import io.edurt.datacap.server.body.ExecuteDslBody;
|
||||
import io.edurt.datacap.server.common.PluginCommon;
|
||||
import io.edurt.datacap.server.common.Response;
|
||||
import io.edurt.datacap.server.common.ServiceState;
|
||||
@ -63,4 +67,18 @@ public class ExecuteServiceImpl
|
||||
}
|
||||
return Response.failure(ServiceState.PLUGIN_EXECUTE_FAILED, response.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response<Object> execute(ExecuteDslBody configure)
|
||||
{
|
||||
ExecuteEntity executeEntity = new ExecuteEntity();
|
||||
executeEntity.setEnv(configure.getEnv());
|
||||
executeEntity.setName(configure.getName());
|
||||
executeEntity.setFormat(configure.getFormat());
|
||||
SqlBody body = configure.getConfigure();
|
||||
body.setType(SqlType.SELECT);
|
||||
SqlBuilder builder = new SqlBuilder(body);
|
||||
executeEntity.setContent(builder.getSql());
|
||||
return this.execute(executeEntity);
|
||||
}
|
||||
}
|
||||
|
55
web/console-fe/src/model/ExecuteDslBody.ts
Normal file
55
web/console-fe/src/model/ExecuteDslBody.ts
Normal file
@ -0,0 +1,55 @@
|
||||
import {SqlBody} from "@/model/builder/SqlBody";
|
||||
|
||||
export class ExecuteDslBody
|
||||
{
|
||||
name: string;
|
||||
configure: SqlBody;
|
||||
env?: object;
|
||||
format?: string;
|
||||
|
||||
constructor(builder: ExecuteDslBodyBuilder)
|
||||
{
|
||||
this.name = builder.name;
|
||||
this.configure = builder.configure;
|
||||
this.format = builder.format;
|
||||
}
|
||||
}
|
||||
|
||||
export class ExecuteDslBodyBuilder
|
||||
{
|
||||
private readonly _name: string;
|
||||
private readonly _format: string;
|
||||
private _configure: SqlBody;
|
||||
|
||||
constructor(name: string, format: string)
|
||||
{
|
||||
this._name = name;
|
||||
this._format = format;
|
||||
}
|
||||
|
||||
setConfigure(configure: SqlBody)
|
||||
{
|
||||
this._configure = configure;
|
||||
return this;
|
||||
}
|
||||
|
||||
get name()
|
||||
{
|
||||
return this._name;
|
||||
}
|
||||
|
||||
get configure()
|
||||
{
|
||||
return this._configure;
|
||||
}
|
||||
|
||||
get format()
|
||||
{
|
||||
return this._format;
|
||||
}
|
||||
|
||||
build()
|
||||
{
|
||||
return new ExecuteDslBody(this);
|
||||
}
|
||||
}
|
111
web/console-fe/src/model/builder/SqlBody.ts
Normal file
111
web/console-fe/src/model/builder/SqlBody.ts
Normal file
@ -0,0 +1,111 @@
|
||||
import {SqlColumn} from "@/model/builder/SqlColumn";
|
||||
import {SqlType} from "@/model/builder/SqlType";
|
||||
|
||||
export class SqlBody
|
||||
{
|
||||
database: string;
|
||||
table: string;
|
||||
columns: Array<SqlColumn>;
|
||||
orders: Array<SqlColumn>;
|
||||
limit = 10;
|
||||
offset = 1;
|
||||
type: SqlType = SqlType.SELECT;
|
||||
|
||||
constructor(builder: SqlBodyBuilder)
|
||||
{
|
||||
this.database = builder.database;
|
||||
this.table = builder.table;
|
||||
this.columns = builder.columns;
|
||||
this.orders = builder.orders;
|
||||
this.limit = builder.limit;
|
||||
this.offset = builder.offset;
|
||||
this.type = builder.type;
|
||||
}
|
||||
}
|
||||
|
||||
export class SqlBodyBuilder
|
||||
{
|
||||
private readonly _database;
|
||||
private readonly _table;
|
||||
private _columns: Array<SqlColumn>;
|
||||
private _orders: Array<SqlColumn>;
|
||||
private _limit = 10;
|
||||
private _offset = 1;
|
||||
private _type: SqlType = SqlType.SELECT;
|
||||
|
||||
constructor(database: string, table: string)
|
||||
{
|
||||
this._database = database;
|
||||
this._table = table;
|
||||
}
|
||||
|
||||
setColumns(columns: Array<SqlColumn>)
|
||||
{
|
||||
this._columns = columns;
|
||||
return this;
|
||||
}
|
||||
|
||||
setOrders(orders: Array<SqlColumn>)
|
||||
{
|
||||
this._orders = orders;
|
||||
return this;
|
||||
}
|
||||
|
||||
setLimit(limit: number)
|
||||
{
|
||||
this._limit = limit;
|
||||
return this;
|
||||
}
|
||||
|
||||
setOffset(offset: number)
|
||||
{
|
||||
this._offset = offset;
|
||||
return this;
|
||||
}
|
||||
|
||||
setType(type: SqlType)
|
||||
{
|
||||
this._type = type;
|
||||
return this;
|
||||
}
|
||||
|
||||
get database()
|
||||
{
|
||||
return this._database;
|
||||
}
|
||||
|
||||
get table()
|
||||
{
|
||||
return this._table;
|
||||
}
|
||||
|
||||
get columns()
|
||||
{
|
||||
return this._columns;
|
||||
}
|
||||
|
||||
get orders()
|
||||
{
|
||||
return this._orders;
|
||||
}
|
||||
|
||||
get limit()
|
||||
{
|
||||
return this._limit;
|
||||
}
|
||||
|
||||
get offset()
|
||||
{
|
||||
return this._offset;
|
||||
}
|
||||
|
||||
get type()
|
||||
{
|
||||
return this._type;
|
||||
}
|
||||
|
||||
build()
|
||||
{
|
||||
return new SqlBody(this);
|
||||
}
|
||||
}
|
45
web/console-fe/src/model/builder/SqlColumn.ts
Normal file
45
web/console-fe/src/model/builder/SqlColumn.ts
Normal file
@ -0,0 +1,45 @@
|
||||
import {SqlOrder} from "@/model/builder/SqlOrder";
|
||||
|
||||
export class SqlColumn
|
||||
{
|
||||
column: string;
|
||||
order: SqlOrder;
|
||||
|
||||
constructor(builder: SqlColumnBuilder)
|
||||
{
|
||||
this.column = builder.column;
|
||||
this.order = builder.order;
|
||||
}
|
||||
}
|
||||
|
||||
export class SqlColumnBuilder
|
||||
{
|
||||
private readonly _column: string;
|
||||
private _order: SqlOrder;
|
||||
|
||||
constructor(column: string)
|
||||
{
|
||||
this._column = column;
|
||||
}
|
||||
|
||||
setOrder(order: SqlOrder)
|
||||
{
|
||||
this._order = order;
|
||||
return this;
|
||||
}
|
||||
|
||||
get column()
|
||||
{
|
||||
return this._column;
|
||||
}
|
||||
|
||||
get order()
|
||||
{
|
||||
return this._order;
|
||||
}
|
||||
|
||||
build()
|
||||
{
|
||||
return new SqlColumn(this);
|
||||
}
|
||||
}
|
5
web/console-fe/src/model/builder/SqlOrder.ts
Normal file
5
web/console-fe/src/model/builder/SqlOrder.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export enum SqlOrder
|
||||
{
|
||||
ASC = 'ASC',
|
||||
DESC = 'DESC'
|
||||
}
|
4
web/console-fe/src/model/builder/SqlType.ts
Normal file
4
web/console-fe/src/model/builder/SqlType.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export enum SqlType
|
||||
{
|
||||
SELECT = 'SELECT'
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
import {ResponseModel} from "@/model/ResponseModel";
|
||||
import {HttpCommon} from "@/common/HttpCommon";
|
||||
import {ExecuteModel} from "@/model/ExecuteModel";
|
||||
import {ExecuteDslBody} from "@/model/ExecuteDslBody";
|
||||
|
||||
const baseUrl = "/api/v1/execute";
|
||||
|
||||
@ -10,4 +11,9 @@ export class ExecuteService
|
||||
{
|
||||
return new HttpCommon().post(baseUrl, JSON.stringify(configure), cancelToken);
|
||||
}
|
||||
|
||||
executeDsl(configure: ExecuteDslBody): Promise<ResponseModel>
|
||||
{
|
||||
return new HttpCommon().post(baseUrl + '/dsl', configure, null);
|
||||
}
|
||||
}
|
||||
|
@ -2,9 +2,13 @@ import {ResponseModel} from "@/model/ResponseModel";
|
||||
import TemplateSqlService from "@/services/template/TemplateSqlService";
|
||||
import {SqlBody} from "@/model/template/SqlBody";
|
||||
import {ExecuteService} from "@/services/ExecuteService";
|
||||
import {ExecuteModel} from "@/model/ExecuteModel";
|
||||
import {Sql} from "@/model/sql/Sql";
|
||||
import squel from "squel";
|
||||
import {ExecuteDslBodyBuilder} from "@/model/ExecuteDslBody";
|
||||
import {SqlBodyBuilder} from "@/model/builder/SqlBody";
|
||||
import {SqlType} from "@/model/builder/SqlType";
|
||||
import {SqlColumn, SqlColumnBuilder} from "@/model/builder/SqlColumn";
|
||||
import {SqlOrder} from "@/model/builder/SqlOrder";
|
||||
|
||||
class ManagerService
|
||||
{
|
||||
@ -58,12 +62,25 @@ class ManagerService
|
||||
|
||||
getDataByConfigure(id: string, sql: Sql): Promise<ResponseModel>
|
||||
{
|
||||
const configure: ExecuteModel = {
|
||||
name: id,
|
||||
content: this.builderSql(sql),
|
||||
format: "JSON"
|
||||
const columns: SqlColumn[] = new Array<SqlColumn>();
|
||||
columns.push(new SqlColumnBuilder('*').build());
|
||||
|
||||
const orders: SqlColumn[] = new Array();
|
||||
if (sql.sort) {
|
||||
orders.push(new SqlColumnBuilder(sql.sort.column).setOrder(SqlOrder[sql.sort.sort]).build());
|
||||
}
|
||||
return new ExecuteService().execute(configure, null);
|
||||
|
||||
const sqlBody = new SqlBodyBuilder(sql.database, sql.table)
|
||||
.setColumns(columns)
|
||||
.setOrders(orders)
|
||||
.setType(SqlType.SELECT)
|
||||
.setLimit(sql.limit)
|
||||
.setOffset(sql.offset)
|
||||
.build();
|
||||
const configure = new ExecuteDslBodyBuilder(id, 'JSON')
|
||||
.setConfigure(sqlBody)
|
||||
.build();
|
||||
return new ExecuteService().executeDsl(configure);
|
||||
}
|
||||
|
||||
private builderSql(configure: Sql): string
|
||||
|
Loading…
Reference in New Issue
Block a user