
com.github.chengyuxing.sql.utils.SqlGenerator Maven / Gradle / Ivy
package com.github.chengyuxing.sql.utils;
import com.github.chengyuxing.common.script.expression.Patterns;
import com.github.chengyuxing.common.utils.ObjectUtil;
import com.github.chengyuxing.sql.dsl.types.StandardOperator;
import com.github.chengyuxing.sql.plugins.NamedParamFormatter;
import com.github.chengyuxing.sql.plugins.TemplateFormatter;
import org.jetbrains.annotations.NotNull;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static com.github.chengyuxing.sql.utils.SqlUtil.*;
/**
* Sql generate tool.
*/
public class SqlGenerator {
private final char namedParamPrefix;
/**
* Named parameter pattern.
*/
private final Pattern namedParamPattern;
/**
* Default implementation: {@link SqlUtil#parseValue(Object, boolean) parseValue(value, true)}
*/
private NamedParamFormatter namedParamFormatter = v -> parseValue(v, true);
/**
* Sql template ({@code ${[!]key}}) formatter.
* Default implementation: {@link SqlUtil#parseValue(Object, boolean) parseValue(value, boolean)}
*/
private TemplateFormatter templateFormatter = SqlUtil::parseValue;
/**
* Constructs a new SqlGenerator with named parameter prefix.
*
* @param namedParamPrefix named parameter prefix
*/
public SqlGenerator(char namedParamPrefix) {
if (namedParamPrefix == ' ') {
throw new IllegalArgumentException("prefix char cannot be empty.");
}
this.namedParamPrefix = namedParamPrefix;
this.namedParamPattern = Pattern.compile(String.format(
"(?> argNameIndexMapping,
Map args) {
}
/**
* Generate prepared sql by named parameter sql, e.g.
* before:
*
* select * from table where id = :id
*
* after:
*
* select * from table where id = ?
*
*
* @param sql named parameter sql
* @param args data of named parameter
* @return GeneratedSqlMetaData
*/
public GeneratedSqlMetaData generatePreparedSql(final String sql, Map args) {
return parseNamedParameterSql(sql, args, true);
}
/**
* Generate normal sql by named parameter sql.
*
* @param sql named parameter sql
* @param args data of named parameter
* @return normal sql
* @see #setNamedParamFormatter(NamedParamFormatter)
* @see #setTemplateFormatter(TemplateFormatter)
*/
public String generateSql(final String sql, Map args) {
return parseNamedParameterSql(sql, args, false).resultSql();
}
/**
* Generate sql by named parameter sql.
*
* @param sql named parameter sql
* @param args data of named parameter
* @param prepare prepare or not
* @return GeneratedSqlMetaData
*/
protected GeneratedSqlMetaData parseNamedParameterSql(final String sql, Map args, boolean prepare) {
// resolve the sql string template first
String fullSql = SqlUtil.formatSql(sql, args, templateFormatter);
if (fullSql.lastIndexOf(namedParamPrefix) < 0) {
return new GeneratedSqlMetaData(sql, fullSql, Collections.emptyMap(), args);
}
Map> indexMap = new HashMap<>();
StringBuilder parsedSql = new StringBuilder();
Matcher matcher = namedParamPattern.matcher(fullSql);
int index = 1;
int lastMatchEnd = 0;
while (matcher.find()) {
parsedSql.append(fullSql, lastMatchEnd, matcher.start());
String name = matcher.group(1);
if (name != null) {
if (prepare) {
if (!indexMap.containsKey(name)) {
indexMap.put(name, new ArrayList<>());
}
indexMap.get(name).add(index);
parsedSql.append("?");
index++;
} else {
Object value = name.contains(".") ? ObjectUtil.getDeepValue(args, name) : args.get(name);
parsedSql.append(namedParamFormatter.format(value));
}
} else {
parsedSql.append(matcher.group());
}
lastMatchEnd = matcher.end();
}
parsedSql.append(fullSql.substring(lastMatchEnd));
return new GeneratedSqlMetaData(sql, parsedSql.toString(), indexMap, args);
}
/**
* Generate named parameter insert statement.
*
* @param tableName table name
* @param data data
* @param columns table columns
* @param ignoreNull ignore null value or not
* @return named parameter insert statement
*/
public String generateNamedParamInsert(final String tableName, Collection columns, final Map data, boolean ignoreNull) {
StringJoiner f = new StringJoiner(", ");
StringJoiner h = new StringJoiner(", ");
for (String column : columns) {
if (ignoreNull && Objects.isNull(data.get(column))) {
continue;
}
f.add(column);
h.add(namedParamPrefix + column);
}
return "insert into " + tableName + "(" + f + ") values (" + h + ")";
}
/**
* Generate named parameter update statement.
*
* @param tableName table name
* @param data data
* @param columns table columns
* @param ignoreNull ignore null value or not
* @return named parameter update sets statement
*/
public String generateNamedParamUpdate(String tableName, Collection columns, Map data, boolean ignoreNull) {
StringJoiner sb = new StringJoiner(",\n\t");
for (String column : columns) {
if (ignoreNull && Objects.isNull(data.get(column))) {
continue;
}
sb.add(column + StandardOperator.EQ.padWithSpace() + namedParamPrefix + column);
}
return "update " + tableName + "\nset " + sb;
}
/**
* Generate count query by record query.
*
* @param recordQuery record query
* @return count query
*/
public String generateCountQuery(@NotNull final String recordQuery) {
return "select count(*) from (" + recordQuery + ") t_4_rabbit";
}
public Pattern getNamedParamPattern() {
return namedParamPattern;
}
public char getNamedParamPrefix() {
return namedParamPrefix;
}
public NamedParamFormatter getNamedParamFormatter() {
return namedParamFormatter;
}
public void setNamedParamFormatter(NamedParamFormatter namedParamFormatter) {
this.namedParamFormatter = namedParamFormatter;
}
public TemplateFormatter getTemplateFormatter() {
return templateFormatter;
}
public void setTemplateFormatter(TemplateFormatter templateFormatter) {
this.templateFormatter = templateFormatter;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy