com.github.javaclub.cdl.client.matrix.jdbc.SMatrixStatement Maven / Gradle / Ivy
package com.github.javaclub.cdl.client.matrix.jdbc;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import lombok.Getter;
import lombok.Setter;
import lombok.AccessLevel;
import com.github.javaclub.cdl.client.matrix.executor.StatementExecutor;
import com.github.javaclub.cdl.client.matrix.jdbc.adapter.AbstractStatementAdapter;
import com.github.javaclub.cdl.client.matrix.merger.ResultSetFactory;
import com.github.javaclub.cdl.client.matrix.parser.result.merger.MergeContext;
import com.github.javaclub.cdl.client.matrix.router.SQLExecutionUnit;
import com.github.javaclub.cdl.client.matrix.router.SQLRouteEngine;
import com.github.javaclub.cdl.client.matrix.router.SQLRouteResult;
import com.google.common.base.Charsets;
import com.google.common.hash.HashCode;
import com.google.common.hash.Hashing;
public class SMatrixStatement extends AbstractStatementAdapter {
private static final Logger log = LoggerFactory.getLogger(SMatrixStatement.class);
@Getter(AccessLevel.PROTECTED)
private final SMatrixConnection shardingConnection;
@Getter(AccessLevel.PROTECTED)
private final SQLRouteEngine sqlRouteEngine;
@Getter
private final int resultSetType;
@Getter
private final int resultSetConcurrency;
@Getter
private final int resultSetHoldability;
private final Map cachedRoutedStatements = new HashMap<>();
@Getter(AccessLevel.PROTECTED)
@Setter(AccessLevel.PROTECTED)
private MergeContext mergeContext;
@Getter(AccessLevel.PROTECTED)
@Setter(AccessLevel.PROTECTED)
private ResultSet currentResultSet;
public SMatrixStatement(final SQLRouteEngine sqlRouteEngine, final SMatrixConnection shardingConnection) throws SQLException {
this(sqlRouteEngine, shardingConnection, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT);
}
public SMatrixStatement(final SQLRouteEngine sqlRouteEngine, final SMatrixConnection shardingConnection, final int resultSetType, final int resultSetConcurrency) throws SQLException {
this(sqlRouteEngine, shardingConnection, resultSetType, resultSetConcurrency, ResultSet.HOLD_CURSORS_OVER_COMMIT);
}
public SMatrixStatement(final SQLRouteEngine sqlRouteEngine, final SMatrixConnection shardingConnection,
final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) throws SQLException {
super(Statement.class);
this.shardingConnection = shardingConnection;
this.sqlRouteEngine = sqlRouteEngine;
this.resultSetType = resultSetType;
this.resultSetConcurrency = resultSetConcurrency;
this.resultSetHoldability = resultSetHoldability;
}
@Override
public Connection getConnection() throws SQLException {
return shardingConnection;
}
@Override
public ResultSet executeQuery(final String sql) throws SQLException {
if (null != currentResultSet && !currentResultSet.isClosed()) {
currentResultSet.close();
}
currentResultSet = ResultSetFactory.getResultSet(generateExecutor(sql).executeQuery(), mergeContext);
return currentResultSet;
}
@Override
public int executeUpdate(final String sql) throws SQLException {
return generateExecutor(sql).executeUpdate();
}
@Override
public int executeUpdate(final String sql, final int autoGeneratedKeys) throws SQLException {
return generateExecutor(sql).executeUpdate(autoGeneratedKeys);
}
@Override
public int executeUpdate(final String sql, final int[] columnIndexes) throws SQLException {
return generateExecutor(sql).executeUpdate(columnIndexes);
}
@Override
public int executeUpdate(final String sql, final String[] columnNames) throws SQLException {
return generateExecutor(sql).executeUpdate(columnNames);
}
@Override
public boolean execute(final String sql) throws SQLException {
return generateExecutor(sql).execute();
}
@Override
public boolean execute(final String sql, final int autoGeneratedKeys) throws SQLException {
return generateExecutor(sql).execute(autoGeneratedKeys);
}
@Override
public boolean execute(final String sql, final int[] columnIndexes) throws SQLException {
return generateExecutor(sql).execute(columnIndexes);
}
@Override
public boolean execute(final String sql, final String[] columnNames) throws SQLException {
return generateExecutor(sql).execute(columnNames);
}
private StatementExecutor generateExecutor(final String sql) throws SQLException {
StatementExecutor result = new StatementExecutor();
SQLRouteResult sqlRouteResult = sqlRouteEngine.route(sql, Collections.emptyList());
if(sqlRouteResult.isNotShardTable()){
setNotShard(true);
}
log.debug("route size:{} {}", sqlRouteResult.getExecutionUnits().size(), sql);
mergeContext = sqlRouteResult.getMergeContext();
for (SQLExecutionUnit each : sqlRouteResult.getExecutionUnits()) {
log.debug("one route:{},{}", each.getGroupName(), each.getSql());
result.addStatement(each.getSql(), generateStatement(each.getSql(), each.getGroupName()));
}
return result;
}
private Statement generateStatement(final String sql, final String dataSourceName) throws SQLException {
HashCode hashCode = Hashing.md5().newHasher().putString(sql, Charsets.UTF_8).putString(dataSourceName, Charsets.UTF_8).hash();
if (cachedRoutedStatements.containsKey(hashCode)) {
return cachedRoutedStatements.get(hashCode);
}
Connection connection = shardingConnection.getConnection(dataSourceName);
Statement result;
if (0 == resultSetHoldability) {
result = connection.createStatement(resultSetType, resultSetConcurrency);
} else {
result = connection.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);
}
replayMethodsInvovation(result);
cachedRoutedStatements.put(hashCode, result);
return result;
}
@Override
public ResultSet getResultSet() throws SQLException {
if (null != currentResultSet) {
return currentResultSet;
}
List resultSets = new ArrayList<>(getRoutedStatements().size());
for (Statement each : getRoutedStatements()) {
resultSets.add(each.getResultSet());
}
currentResultSet = ResultSetFactory.getResultSet(resultSets, mergeContext);
return currentResultSet;
}
@Override
public Collection extends Statement> getRoutedStatements() throws SQLException {
return cachedRoutedStatements.values();
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy