org.zodiac.fastorm.rdb.utils.SqlUtils Maven / Gradle / Ivy
The newest version!
package org.zodiac.fastorm.rdb.utils;
import org.slf4j.Logger;
import org.zodiac.commons.util.time.DateFormatter;
import org.zodiac.fastorm.rdb.executor.NullValue;
import org.zodiac.fastorm.rdb.executor.PrepareSqlRequest;
import org.zodiac.fastorm.rdb.executor.SqlRequest;
import org.zodiac.fastorm.rdb.operator.builder.fragments.BatchSqlFragments;
import org.zodiac.fastorm.rdb.operator.builder.fragments.EmptySqlFragments;
import org.zodiac.fastorm.rdb.operator.builder.fragments.SqlFragments;
import javax.annotation.Nonnull;
import java.util.Arrays;
import java.util.Date;
public abstract class SqlUtils {
private SqlUtils() {
super();
}
/*Use cache to avoid duplicate creation.*/
/* -Dplatform.fastorm.question-marks.cache-size=200 */
static final SqlFragments[] Q_M_CACHE;
static {
int defaultSize = Runtime.getRuntime().maxMemory() > 4 * 1024 * 1024 * 1024L ? 500 : 200;
Q_M_CACHE = new SqlFragments[Integer.getInteger("platform.fastorm.question-marks.cache-size", defaultSize) + 1];
for (int i = 0; i < Q_M_CACHE.length; i++) {
String[] arr = new String[i];
Arrays.fill(arr, "?");
Q_M_CACHE[i] = SqlFragments.single(String.join(",", arr));
}
}
/**
* Create a SQL fragment with continuous precompiled parameter placeholders, typically used for operations such as 'in (?,?)'.
*
* @param len Length.
* @return The {@link SqlFragments} .
*/
public static SqlFragments createQuestionMarks(int len) {
if (len == 0) {
return EmptySqlFragments.getInstance();
}
int cacheSize = Q_M_CACHE.length;
if (len < cacheSize) {
return Q_M_CACHE[len];
}
/*Starting from 1.*/
cacheSize -= 1;
int size = len / cacheSize;
int remainder = len % cacheSize;
BatchSqlFragments batch = new BatchSqlFragments(
size * 2 + (remainder > 0 ? 1 : 0), 0);
for (int i = 0; i < size; i++) {
if (i > 0) {
batch.add(SqlFragments.COMMA);
}
batch.add(Q_M_CACHE[cacheSize]);
}
if (remainder > 0) {
if (size > 0) {
batch.add(SqlFragments.COMMA);
}
batch.add(Q_M_CACHE[remainder]);
}
return batch;
}
/**
* Converting {@code SQL} parameters to string is commonly used for operations such as printing {@code SQL} parameters
*
* @param parameters The parameters.
* @return The string.
*/
public static String sqlParameterToString(Object[] parameters) {
if (parameters == null) {
return "";
}
StringBuilder builder = new StringBuilder();
int i = 0;
for (Object param : parameters) {
if (i++ != 0) {
builder.append(",");
}
builder.append(param);
if (!(param instanceof NullValue)) {
builder.append("(");
builder.append(param == null ? "null" : param.getClass().getSimpleName());
builder.append(")");
}
}
return builder.toString();
}
/**
* Print {@code SQL}.
*
* @param log The {@link Logger}.
* @param sqlRequest The {@link SqlRequest}.
*/
public static void printSql(Logger log, SqlRequest sqlRequest) {
if (log.isDebugEnabled()) {
if (sqlRequest.isNotEmpty()) {
boolean hasParameter = sqlRequest.getParameters() != null && sqlRequest.getParameters().length > 0;
log.debug("==> {}: {}", hasParameter ? "Preparing" : " Execute", sqlRequest.getSql());
if (hasParameter) {
log.debug("==> Parameters: {}", sqlParameterToString(sqlRequest.getParameters()));
if (sqlRequest instanceof PrepareSqlRequest) {
log.debug("==> Native: {}", sqlRequest.toNativeSql());
}
}
}
}
}
/**
* Convert {@code SQL} and parameters into native {@code SQL} statements, typically used for log printing.
*
* @param sql The {@code SQL}.
* @param parameters Precompiled parameters.
* @return The native {@code SQL}.
*/
public static String toNativeSql(String sql, Object... parameters) {
if (parameters == null) {
return sql;
}
String[] stringParameter = new String[parameters.length];
int len = 0;
for (int i = 0; i < parameters.length; i++) {
Object parameter = parameters[i];
if (parameter instanceof Number
|| parameter instanceof Boolean) {
stringParameter[i] = parameter.toString();
} else if (parameter instanceof Date) {
stringParameter[i] = "'" + DateFormatter.toString(((Date) parameter), "yyyy-MM-dd HH:mm:ss") + "'";
} else if (parameter instanceof NullValue) {
stringParameter[i] = "null";
} else if (parameter == null) {
stringParameter[i] = "null";
} else {
stringParameter[i] = "'" + parameter + "'";
}
len += stringParameter.length;
}
return sqlParameterToString(sql, len, stringParameter);
}
@Nonnull
private static String sqlParameterToString(String sql, int len, String[] stringParameter) {
StringBuilder builder = new StringBuilder(sql.length() + len + 16);
int parameterIndex = 0;
for (int i = 0, sqlLen = sql.length(); i < sqlLen; i++) {
char c = sql.charAt(i);
if (c == '?') {
if (stringParameter.length > parameterIndex) {
builder.append(stringParameter[parameterIndex++]);
} else {
builder.append("unbound");
}
} else {
builder.append(c);
}
}
return builder.toString();
}
}