do not use an object array for parameters

This commit is contained in:
Jörg Prante 2025-03-13 17:28:43 +01:00
parent 1578483688
commit bfe943606e
8 changed files with 44 additions and 55 deletions

View file

@ -6,8 +6,6 @@ import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.testcontainers.containers.MariaDBContainer; import org.testcontainers.containers.MariaDBContainer;
import org.xbib.jdbc.query.Config;
import org.xbib.jdbc.query.ConfigSupplier;
import org.xbib.jdbc.query.DatabaseProvider; import org.xbib.jdbc.query.DatabaseProvider;
import org.xbib.jdbc.query.OptionsOverride; import org.xbib.jdbc.query.OptionsOverride;
import org.xbib.jdbc.query.Schema; import org.xbib.jdbc.query.Schema;
@ -45,12 +43,8 @@ public class MariaDBTest extends CommonTest {
@Override @Override
protected DatabaseProvider createDatabaseProvider(OptionsOverride options) { protected DatabaseProvider createDatabaseProvider(OptionsOverride options) {
Config config = ConfigSupplier.of() return DatabaseProvider.builder(getClass().getClassLoader(),
.property("database.url", mariaDBContainer.getJdbcUrl()) mariaDBContainer.getJdbcUrl(), null, null, "testUser", "testPassword")
.property("database.user", "testUser")
.property("database.password", "testPassword")
.get();
return DatabaseProvider.builder(config)
.withSqlParameterLogging() .withSqlParameterLogging()
.withSqlInExceptionMessages() .withSqlInExceptionMessages()
.withOptions(options) .withOptions(options)

View file

@ -7,8 +7,6 @@ import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.testcontainers.containers.OracleContainer; import org.testcontainers.containers.OracleContainer;
import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.junit.jupiter.Testcontainers;
import org.xbib.jdbc.query.Config;
import org.xbib.jdbc.query.ConfigSupplier;
import org.xbib.jdbc.query.DatabaseProvider; import org.xbib.jdbc.query.DatabaseProvider;
import org.xbib.jdbc.query.OptionsOverride; import org.xbib.jdbc.query.OptionsOverride;
import org.xbib.jdbc.query.Schema; import org.xbib.jdbc.query.Schema;
@ -46,12 +44,8 @@ public class OracleTest extends CommonTest {
@Override @Override
protected DatabaseProvider createDatabaseProvider(OptionsOverride options) throws Exception { protected DatabaseProvider createDatabaseProvider(OptionsOverride options) throws Exception {
Config config = ConfigSupplier.of() return DatabaseProvider.builder(getClass().getClassLoader(),
.property("database.url", oracleContainer.getJdbcUrl()) oracleContainer.getJdbcUrl(), null, null, "testUser", "testPassword")
.property("database.user", "testUser")
.property("database.password", "testPassword")
.get();
return DatabaseProvider.builder(config)
.withSqlParameterLogging() .withSqlParameterLogging()
.withSqlInExceptionMessages() .withSqlInExceptionMessages()
.withOptions(options) .withOptions(options)

View file

@ -20,7 +20,7 @@ public class MixedParameterSql {
private final String sqlToExecute; private final String sqlToExecute;
private final Object[] args; private final List<Object> args;
public MixedParameterSql(String sql, List<Object> positionalArgs, Map<String, Object> nameToArg) { public MixedParameterSql(String sql, List<Object> positionalArgs, Map<String, Object> nameToArg) {
if (positionalArgs == null) { if (positionalArgs == null) {
@ -95,12 +95,12 @@ public class MixedParameterSql {
} }
} }
this.sqlToExecute = newSql.toString(); this.sqlToExecute = newSql.toString();
args = argsList.toArray(new Object[argsList.size()]); args = argsList;
if (currentPositionalArg != positionalArgs.size()) { if (currentPositionalArg != positionalArgs.size()) {
throw new DatabaseException("Wrong number of positional parameters were provided (expected: " throw new DatabaseException("Wrong number of positional parameters were provided (expected: "
+ currentPositionalArg + ", actual: " + positionalArgs.size() + ")"); + currentPositionalArg + ", actual: " + positionalArgs.size() + ")");
} }
if (nameToArg.size() > args.length - Math.max(0, positionalArgs.size() - 1) + rewrittenArgs.size()) { if (nameToArg.size() > args.size() - Math.max(0, positionalArgs.size() - 1) + rewrittenArgs.size()) {
Set<String> unusedNames = new HashSet<>(nameToArg.keySet()); Set<String> unusedNames = new HashSet<>(nameToArg.keySet());
unusedNames.removeAll(argNamesList); unusedNames.removeAll(argNamesList);
unusedNames.removeAll(rewrittenArgs); unusedNames.removeAll(rewrittenArgs);
@ -114,7 +114,7 @@ public class MixedParameterSql {
return sqlToExecute; return sqlToExecute;
} }
public Object[] getArgs() { public List<Object> getArgs() {
return args; return args;
} }
} }

View file

@ -412,8 +412,8 @@ public class SqlInsertImpl implements SqlInsert {
PreparedStatement ps = null; PreparedStatement ps = null;
Metric metric = new Metric(log.isLoggable(Level.FINE)); Metric metric = new Metric(log.isLoggable(Level.FINE));
String executeSql = sql; String executeSql = sql;
Object[] firstRowParameters = null; List<Object> firstRowParameters = null;
List<Object[]> parameters = new ArrayList<>(); List<List<Object>> parameters = new ArrayList<>();
boolean isSuccess = false; boolean isSuccess = false;
String errorCode = null; String errorCode = null;
Exception logEx = null; Exception logEx = null;
@ -434,7 +434,7 @@ public class SqlInsertImpl implements SqlInsert {
if (connection != null) { if (connection != null) {
ps = connection.prepareStatement(executeSql); ps = connection.prepareStatement(executeSql);
for (Object[] params : parameters) { for (List<Object> params : parameters) {
adaptor.addParameters(ps, params); adaptor.addParameters(ps, params);
ps.addBatch(); ps.addBatch();
} }
@ -470,7 +470,7 @@ public class SqlInsertImpl implements SqlInsert {
PreparedStatement ps = null; PreparedStatement ps = null;
Metric metric = new Metric(log.isLoggable(Level.FINE)); Metric metric = new Metric(log.isLoggable(Level.FINE));
String executeSql = sql; String executeSql = sql;
Object[] parameters = null; List<Object> parameters = null;
boolean isSuccess = false; boolean isSuccess = false;
String errorCode = null; String errorCode = null;
Exception logEx = null; Exception logEx = null;
@ -520,7 +520,7 @@ public class SqlInsertImpl implements SqlInsert {
ResultSet rs = null; ResultSet rs = null;
Metric metric = new Metric(log.isLoggable(Level.FINE)); Metric metric = new Metric(log.isLoggable(Level.FINE));
String executeSql = sql; String executeSql = sql;
Object[] parameters = null; List<Object> parameters = null;
boolean isSuccess = false; boolean isSuccess = false;
String errorCode = null; String errorCode = null;
Exception logEx = null; Exception logEx = null;
@ -577,7 +577,7 @@ public class SqlInsertImpl implements SqlInsert {
ResultSet rs = null; ResultSet rs = null;
Metric metric = new Metric(log.isLoggable(Level.FINE)); Metric metric = new Metric(log.isLoggable(Level.FINE));
String executeSql = sql; String executeSql = sql;
Object[] parameters = null; List<Object> parameters = null;
boolean isSuccess = false; boolean isSuccess = false;
String errorCode = null; String errorCode = null;
Exception logEx = null; Exception logEx = null;

View file

@ -575,11 +575,10 @@ public class SqlSelectImpl implements SqlSelect {
} }
private <T> T queryWithTimeout(RowsHandler<T> handler) { private <T> T queryWithTimeout(RowsHandler<T> handler) {
assert ps == null;
ResultSet rs = null; ResultSet rs = null;
Metric metric = new Metric(logger.isLoggable(Level.FINE)); Metric metric = new Metric(logger.isLoggable(Level.FINE));
String executeSql = sql; String executeSql = sql;
Object[] parameters = null; List<Object> parameters = null;
boolean isWarn = false; boolean isWarn = false;
boolean isSuccess = false; boolean isSuccess = false;
String errorCode = null; String errorCode = null;

View file

@ -260,8 +260,8 @@ public class SqlUpdateImpl implements SqlUpdate {
PreparedStatement ps = null; PreparedStatement ps = null;
Metric metric = new Metric(log.isLoggable(Level.FINE)); Metric metric = new Metric(log.isLoggable(Level.FINE));
String executeSql = sql; String executeSql = sql;
Object[] firstRowParameters = null; List<Object> firstRowParameters = null;
List<Object[]> parameters = new ArrayList<>(); List<List<Object>> parameters = new ArrayList<>();
boolean isSuccess = false; boolean isSuccess = false;
String errorCode = null; String errorCode = null;
Exception logEx = null; Exception logEx = null;
@ -281,7 +281,7 @@ public class SqlUpdateImpl implements SqlUpdate {
} }
if (connection != null) { if (connection != null) {
ps = connection.prepareStatement(executeSql); ps = connection.prepareStatement(executeSql);
for (Object[] params : parameters) { for (List<Object> params : parameters) {
adaptor.addParameters(ps, params); adaptor.addParameters(ps, params);
ps.addBatch(); ps.addBatch();
} }
@ -314,7 +314,7 @@ public class SqlUpdateImpl implements SqlUpdate {
PreparedStatement ps = null; PreparedStatement ps = null;
Metric metric = new Metric(log.isLoggable(Level.FINE)); Metric metric = new Metric(log.isLoggable(Level.FINE));
String executeSql = sql; String executeSql = sql;
Object[] parameters = null; List<Object> parameters = null;
boolean isSuccess = false; boolean isSuccess = false;
String errorCode = null; String errorCode = null;
Exception logEx = null; Exception logEx = null;

View file

@ -15,6 +15,7 @@ import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.ZoneId; import java.time.ZoneId;
import java.util.Date; import java.util.Date;
import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -32,9 +33,9 @@ public class StatementAdapter {
this.options = options; this.options = options;
} }
public void addParameters(PreparedStatement ps, Object[] parameters) throws SQLException { public void addParameters(PreparedStatement ps, List<Object> parameters) throws SQLException {
for (int i = 0; i < parameters.length; i++) { for (int i = 0; i < parameters.size(); i++) {
Object parameter = parameters[i]; Object parameter = parameters.get(i);
// Unwrap secret args here so we can use them // Unwrap secret args here so we can use them
if (parameter instanceof SecretArg) { if (parameter instanceof SecretArg) {
parameter = ((SecretArg) parameter).getArg(); parameter = ((SecretArg) parameter).getArg();

View file

@ -8,7 +8,8 @@ import java.io.InputStream;
import java.io.Reader; import java.io.Reader;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.Arrays; import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
@ -21,45 +22,45 @@ public class DebugSql {
public static final String PARAM_SQL_SEPARATOR = "\tParamSql:\t"; public static final String PARAM_SQL_SEPARATOR = "\tParamSql:\t";
public static void printSql(StringBuilder buf, String sql, Object[] args, Options options) { public static void printSql(StringBuilder buf, String sql, List<Object> args, Options options) {
printSql(buf, sql, args, true, options.isLogParameters(), options); printSql(buf, sql, args, true, options.isLogParameters(), options);
} }
public static void printSql(StringBuilder buf, String sql, Object[] args, boolean includeExecSql, public static void printSql(StringBuilder buf, String sql, List<Object> args, boolean includeExecSql,
boolean includeParameters, Options options) { boolean includeParameters, Options options) {
Object[] argsToPrint = args; List<Object> argsToPrint = args;
if (argsToPrint == null) { if (argsToPrint == null) {
argsToPrint = new Object[0]; argsToPrint = new ArrayList<>();
} }
int batchSize = -1; int batchSize = -1;
if (argsToPrint.length > 0 && argsToPrint instanceof Object[][]) { if (!argsToPrint.isEmpty() && argsToPrint.getFirst() instanceof List) {
// The arguments provided were from a batch - just use the first set // The arguments provided were from a batch - just use the first set
batchSize = argsToPrint.length; batchSize = argsToPrint.size();
argsToPrint = (Object[]) argsToPrint[0]; argsToPrint = (List<Object>) argsToPrint.getFirst();
} }
String[] sqlParts = sql.split("\\?"); String[] sqlParts = sql.split("\\?");
if (sqlParts.length != argsToPrint.length + (sql.endsWith("?") ? 0 : 1)) { if (sqlParts.length != argsToPrint.size() + (sql.endsWith("?") ? 0 : 1)) {
buf.append("(wrong # args) query: "); buf.append("(wrong # args) query: ");
buf.append(sql); buf.append(sql);
if (args != null) { if (args != null) {
buf.append(" args: "); buf.append(" args: ");
if (includeParameters) { if (includeParameters) {
buf.append(Arrays.toString(argsToPrint)); buf.append(argsToPrint);
} else { } else {
buf.append(argsToPrint.length); buf.append(argsToPrint.size());
} }
} }
} else { } else {
if (includeExecSql) { if (includeExecSql) {
buf.append(removeTabs(sql)); buf.append(removeTabs(sql));
} }
if (includeParameters && argsToPrint.length > 0) { if (includeParameters && argsToPrint.size() > 0) {
if (includeExecSql) { if (includeExecSql) {
buf.append(PARAM_SQL_SEPARATOR); buf.append(PARAM_SQL_SEPARATOR);
} }
for (int i = 0; i < argsToPrint.length; i++) { for (int i = 0; i < argsToPrint.size(); i++) {
buf.append(removeTabs(sqlParts[i])); buf.append(removeTabs(sqlParts[i]));
Object argToPrint = argsToPrint[i]; Object argToPrint = argsToPrint.get(i);
if (argToPrint instanceof String argToPrintString) { if (argToPrint instanceof String argToPrintString) {
int maxLength = options.maxStringLengthParam(); int maxLength = options.maxStringLengthParam();
if (argToPrintString.length() > maxLength && maxLength > 0) { if (argToPrintString.length() > maxLength && maxLength > 0) {
@ -101,7 +102,7 @@ public class DebugSql {
buf.append("<unknown:").append(argToPrint.getClass().getName()).append(">"); buf.append("<unknown:").append(argToPrint.getClass().getName()).append(">");
} }
} }
if (sqlParts.length > argsToPrint.length) { if (sqlParts.length > argsToPrint.size()) {
buf.append(sqlParts[sqlParts.length - 1]); buf.append(sqlParts[sqlParts.length - 1]);
} }
} }
@ -121,7 +122,7 @@ public class DebugSql {
return s == null ? null : s.replace("'", "''"); return s == null ? null : s.replace("'", "''");
} }
public static String exceptionMessage(String sql, Object[] parameters, String errorCode, Options options) { public static String exceptionMessage(String sql, List<Object> parameters, String errorCode, Options options) {
StringBuilder buf = new StringBuilder("Error executing SQL"); StringBuilder buf = new StringBuilder("Error executing SQL");
if (errorCode != null) { if (errorCode != null) {
buf.append(" (errorCode=").append(errorCode).append(")"); buf.append(" (errorCode=").append(errorCode).append(")");
@ -133,20 +134,20 @@ public class DebugSql {
return buf.toString(); return buf.toString();
} }
public static void logSuccess(String sqlType, Logger log, Metric metric, String sql, Object[] args, Options options) { public static void logSuccess(String sqlType, Logger log, Metric metric, String sql, List<Object> args, Options options) {
if (log.isLoggable(Level.FINEST)) { if (log.isLoggable(Level.FINEST)) {
log.log(Level.FINEST, () -> logMiddle('\t', sqlType, metric, null, sql, args, options)); log.log(Level.FINEST, () -> logMiddle('\t', sqlType, metric, null, sql, args, options));
} }
} }
public static void logWarning(String sqlType, Logger log, Metric metric, String errorCode, String sql, Object[] args, public static void logWarning(String sqlType, Logger log, Metric metric, String errorCode, String sql, List<Object> args,
Options options, Throwable t) { Options options, Throwable t) {
if (log.isLoggable(Level.WARNING)) { if (log.isLoggable(Level.WARNING)) {
log.log(Level.WARNING, logMiddle(' ', sqlType, metric, errorCode, sql, args, options), t); log.log(Level.WARNING, logMiddle(' ', sqlType, metric, errorCode, sql, args, options), t);
} }
} }
public static void logError(String sqlType, Logger log, Metric metric, String errorCode, String sql, Object[] args, public static void logError(String sqlType, Logger log, Metric metric, String errorCode, String sql, List<Object> args,
Options options, Throwable t) { Options options, Throwable t) {
if (log.isLoggable(Level.SEVERE)) { if (log.isLoggable(Level.SEVERE)) {
log.log(Level.SEVERE, logMiddle(' ', sqlType, metric, errorCode, sql, args, options), t); log.log(Level.SEVERE, logMiddle(' ', sqlType, metric, errorCode, sql, args, options), t);
@ -154,7 +155,7 @@ public class DebugSql {
} }
private static String logMiddle(char separator, String sqlType, Metric metric, private static String logMiddle(char separator, String sqlType, Metric metric,
String errorCode, String sql, Object[] args, Options options) { String errorCode, String sql, List<Object> args, Options options) {
StringBuilder buf = new StringBuilder(); StringBuilder buf = new StringBuilder();
if (errorCode != null) { if (errorCode != null) {
buf.append("errorCode=").append(errorCode).append(" "); buf.append("errorCode=").append(errorCode).append(" ");