All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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();
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy