Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide query parameters to execution listener #86

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions fluent-jdbc/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/target/
/.settings/
/.classpath
/.project
/*.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package org.codejargon.fluentjdbc.api.mapper;

import java.math.BigDecimal;

import org.codejargon.fluentjdbc.api.query.CallableMapper;

/**
* <p>A set of common mappers for convenience.</p>
* @see org.codejargon.fluentjdbc.api.mapper.ObjectMappers
*/
public abstract class CallableMappers {
private static final CallableMapper<Integer> singleInteger = (cs) -> cs.getInt(1);
private static final CallableMapper<Long> singleLong = (cs) -> cs.getLong(1);
private static final CallableMapper<String> singleString = (cs) -> cs.getString(1);
private static final CallableMapper<BigDecimal> singleBigDecimal = (cs) -> cs.getBigDecimal(1);
private static final CallableMapper<Boolean> singleBoolean = (cs) -> cs.getBoolean(1);

/**
* Maps the first Integer column.
* @return first Integer column
*/
public static CallableMapper<Integer> singleInteger() {
return singleInteger;
}

/**
* Maps the first Long column.
* @return first Long column
*/
public static CallableMapper<Long> singleLong() {
return singleLong;
}

/**
* Maps the first string column
* @return first string column
*/
public static CallableMapper<String> singleString() {
return singleString;
}

/**
* Maps the first BigDecimal column
* @return first BigDecimal column
*/
public static CallableMapper<BigDecimal> singleBigDecimal() {
return singleBigDecimal;
}

/**
* Maps the first Boolean column
* @return first Boolean column
*/
public static CallableMapper<Boolean> singleBoolean() {
return singleBoolean;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* $Id: $
*
* Copyright (c) 2021, CGI. All rights reserved.
* CGI PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package org.codejargon.fluentjdbc.api.query;

import java.sql.CallableStatement;
import java.sql.SQLException;

/**
* The {@code CallableResultMapper} class implements ...
* TODO write proper class description
*
* @author wiedermanna
*/
public interface CallableMapper<T> {
T map(CallableStatement statement) throws SQLException;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package org.codejargon.fluentjdbc.api.query;

import java.sql.CallableStatement;
import java.util.List;
import java.util.Map;

/**
* Select query for a SQL statement. A SelectQuery is mutable, non-threadsafe.
*/
public interface CallableQuery {
/**
* Adds positional query parameters.
*
* @param params additional query parameters
* @return this
*/
CallableQuery params(List<?> params);

/**
* Adds positional query parameters.
*
* @param params additional query parameters
* @return this
*/
CallableQuery params(Object... params);

/**
* Adds named query paramaters.
*
* @param namedParams additional named query parameters
* @return this
*/
CallableQuery namedParams(Map<String, ?> namedParams);

/**
* Adds a named query parameter
*
* @param name name of parameter
* @param parameter value of parameter
* @return this
*/
CallableQuery namedParam(String name, Object parameter);

/**
* Sets a custom error handler
*
* @param sqlErrorHandler
* @return this
*/
CallableQuery errorHandler(SqlErrorHandler sqlErrorHandler);

/**
* executes the callable statement and returns a single result.
*
* @param mapper {@link CallableStatement} mapper
* @param <T> result type
* @return exactly one result
* @throws org.codejargon.fluentjdbc.api.FluentJdbcException if no result found
*/
<T> T result(CallableMapper<T> mapper);
}
Original file line number Diff line number Diff line change
@@ -2,10 +2,6 @@

import org.codejargon.fluentjdbc.api.query.inspection.DatabaseInspection;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.function.Function;

/**
* <p>FluentJdbc Query API to create select, update/insert, and batch update/insert queries. Immutable, thread-safe.</p>
* @see org.codejargon.fluentjdbc.api.integration.ConnectionProvider
@@ -35,6 +31,14 @@ public interface Query {
*/
BatchQuery batch(String sql);

/**
* Creates a callable query for SQL statement
*
* @param sql callable SQL statement
* @return callable query for SQL statement
*/
CallableQuery call(String sql);

/**
* Transaction control
*
Original file line number Diff line number Diff line change
@@ -3,19 +3,24 @@
import java.sql.SQLException;
import java.util.Optional;

import org.codejargon.fluentjdbc.api.query.listen.QueryInfo;

public interface SqlErrorHandler {
enum Action {
RETRY
}

/**
* Handles SQL errors, may implement logging, etc. The handler should always rethrow an exception in case of
* a critical error. Otherwise retry action can be triggered. The handler is responsible to implement
* delay or limitations for the retry.
* Handles SQL errors, may implement logging, etc. The handler should always
* re-throw an exception in case of a critical error. Otherwise retry action can
* be triggered. The handler is responsible to implement delay or limitations
* for the retry.
*
* @param e the error
* @param sql The sql query. Always present unless the error was thrown by direct plainConnection() usage.
* @return In case no exception is thrown, otherwise action needs to be returned ( eg retry ).
* @param e the error
* @param queryInfo Query info including the SQL query. Always present unless
* the error was thrown by direct plainConnection() usage.
* @return In case no exception is thrown, otherwise action needs to be returned
* ( eg retry ).
*/
Action handle(SQLException e, Optional<String> sql) throws SQLException;
Action handle(SQLException e, Optional<QueryInfo> queryInfo) throws SQLException;
}
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@

public interface ExecutionDetails {
Boolean success();
String sql();
QueryInfo queryInfo();
Long executionTimeMs();
Optional<SQLException> sqlException();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
*
*/
package org.codejargon.fluentjdbc.api.query.listen;

import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
* Information about what was executed - query + parameters. Parameters are not available for batch executions
*
* @author bwc
*/
public interface QueryInfo {

/**
* @return the sql query which was executed
*/
String sql();

/**
* @return optional parameters
*/
Optional<List<Object>> params();

/**
* @return optional named parameters
*/
Optional<Map<String, Object>> namedParams();

}
Original file line number Diff line number Diff line change
@@ -1,28 +1,34 @@
package org.codejargon.fluentjdbc.internal.query;

import org.codejargon.fluentjdbc.api.FluentJdbcException;
import org.codejargon.fluentjdbc.api.query.*;
import org.codejargon.fluentjdbc.internal.query.namedparameter.NamedTransformedSql;
import org.codejargon.fluentjdbc.internal.query.namedparameter.NamedTransformedSqlFactory;
import org.codejargon.fluentjdbc.internal.support.Ints;
import org.codejargon.fluentjdbc.internal.query.namedparameter.SqlAndParamsForNamed;
import org.codejargon.fluentjdbc.internal.support.Preconditions;
import static java.util.Optional.empty;
import static java.util.stream.Collectors.toList;
import static org.codejargon.fluentjdbc.internal.support.Iterables.stream;
import static org.codejargon.fluentjdbc.internal.support.Sneaky.consumer;

import java.awt.geom.AffineTransform;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

import static java.util.Optional.empty;
import static java.util.stream.Collectors.toList;
import static org.codejargon.fluentjdbc.internal.support.Sneaky.consumer;
import static org.codejargon.fluentjdbc.internal.support.Iterables.stream;
import org.codejargon.fluentjdbc.api.FluentJdbcException;
import org.codejargon.fluentjdbc.api.query.BatchQuery;
import org.codejargon.fluentjdbc.api.query.Mapper;
import org.codejargon.fluentjdbc.api.query.SqlErrorHandler;
import org.codejargon.fluentjdbc.api.query.UpdateResult;
import org.codejargon.fluentjdbc.api.query.UpdateResultGenKeys;
import org.codejargon.fluentjdbc.internal.query.namedparameter.NamedTransformedSql;
import org.codejargon.fluentjdbc.internal.query.namedparameter.NamedTransformedSqlFactory;
import org.codejargon.fluentjdbc.internal.query.namedparameter.SqlAndParamsForNamed;
import org.codejargon.fluentjdbc.internal.support.Ints;
import org.codejargon.fluentjdbc.internal.support.Preconditions;

class BatchQueryInternal implements BatchQuery {
private static final String namedSet = "Named parameters are already set.";
@@ -111,7 +117,7 @@ private <T> List<UpdateResult> run(FetchGenKey<T> fetchGen) {
Preconditions.checkArgument(params.isPresent() || namedParams.isPresent(), "Parameters must be set to run a batch query");
return query.query(
connection -> params.isPresent() ? positional(connection, fetchGen) : named(connection, fetchGen),
Optional.of(sql),
Optional.of(QueryInfoInternal.of(sql)),
sqlErrorHandler.get()
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package org.codejargon.fluentjdbc.internal.query;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

import org.codejargon.fluentjdbc.api.FluentJdbcException;
import org.codejargon.fluentjdbc.api.query.CallableMapper;
import org.codejargon.fluentjdbc.api.query.CallableQuery;
import org.codejargon.fluentjdbc.api.query.SqlErrorHandler;

class CallableQueryInternal extends SingleQueryBase implements CallableQuery {

CallableQueryInternal(String sql, QueryInternal query) {
super(query, sql);
}

@Override
public CallableQuery params(List<?> params) {
addParameters(params);
return this;
}

@Override
public CallableQuery params(Object... params) {
addParameters(params);
return this;
}

@Override
public CallableQuery namedParams(Map<String, ?> namedParams) {
addNamedParameters(namedParams);
return this;
}

@Override
public CallableQuery namedParam(String name, Object parameter) {
addNamedParameter(name, parameter);
return this;
}

@Override
public CallableQuery errorHandler(SqlErrorHandler sqlErrorHandler ) {
this.sqlErrorHandler = () -> sqlErrorHandler;
return this;
}


@Override
public <T> T result(CallableMapper<T> mapper) {
return runQuery(ps -> {
if (ps instanceof CallableStatement) {
CallableStatement cs = (CallableStatement)ps;
cs.execute();
return mapper.map(cs);
} else {
throw new FluentJdbcException("No out parameters specified for call");
}
}, sqlErrorHandler.get());
}

@Override
void customizeQuery(PreparedStatement statement, QueryConfig config) throws SQLException {
// nothing to do here for callable statements
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package org.codejargon.fluentjdbc.internal.query;

import java.util.Optional;

import org.codejargon.fluentjdbc.api.query.inspection.DatabaseInspection;
import org.codejargon.fluentjdbc.api.query.inspection.MetaDataAccess;
import org.codejargon.fluentjdbc.api.query.inspection.MetaDataResultSet;
import org.codejargon.fluentjdbc.api.query.inspection.MetaDataSelect;

import java.util.Optional;

class DatabaseInspectionInternal implements DatabaseInspection {
private final QueryInternal query;

@@ -18,7 +18,7 @@ class DatabaseInspectionInternal implements DatabaseInspection {
public <T> T accessMetaData(MetaDataAccess<T> access) {
return query.query(
connection -> access.access(connection.getMetaData()),
Optional.of("JDBC Database Inspection"),
Optional.of(QueryInfoInternal.of("JDBC Database Inspection")),
query.config.defaultSqlErrorHandler.get()
);
}
Loading