package org.test4j.module.dbfit.environment;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.sql.DataSource;
import org.test4j.module.database.environment.DBEnvironment;
import org.test4j.module.database.environment.TableMeta;
import org.test4j.module.database.environment.types.DB2Environment;
import org.test4j.module.database.environment.types.DerbyEnvironment;
import org.test4j.module.database.environment.types.MySqlEnvironment;
import org.test4j.module.database.environment.types.OracleEnvironment;
import org.test4j.module.database.environment.types.SqlServerEnvironment;
import org.test4j.module.database.transaction.TransactionManagementConfiguration;
import org.test4j.module.dbfit.model.BigDecimalParseDelegate;
import org.test4j.module.dbfit.model.DbParameterAccessor;
import org.test4j.module.dbfit.model.SqlDateParseDelegate;
import org.test4j.module.dbfit.model.SqlTimestampParseDelegate;
import org.test4j.module.dbfit.utility.SymbolUtil;
import fit.TypeAdapter;
public abstract class DbFitAbstractDBEnvironment implements DbFitEnvironment {
protected DBEnvironment dbEnviroment;
protected DbFitAbstractDBEnvironment(DBEnvironment dbEnvironemnt) {
this.dbEnviroment = dbEnvironemnt;
TypeAdapter.registerParseDelegate(BigDecimal.class, BigDecimalParseDelegate.class);
TypeAdapter.registerParseDelegate(java.sql.Date.class, SqlDateParseDelegate.class);
TypeAdapter.registerParseDelegate(java.sql.Timestamp.class, SqlTimestampParseDelegate.class);
}
public final PreparedStatement createStatementWithBoundFixtureSymbols(String commandText) throws SQLException {
String text = SymbolUtil.replacedBySymbols(commandText);
String paramNames[] = extractParamNames(text);
String sql = parseCommandText(text, paramNames);
Connection connection = this.connect();
PreparedStatement cs = connection.prepareStatement(sql);
for (int i = 0; i < paramNames.length; i++) {
Object value = org.test4j.module.dbfit.utility.SymbolUtil.getSymbol(paramNames[i]);
cs.setObject(i + 1, value);
}
return cs;
}
protected String parseCommandText(String commandText, String[] vars) {
return commandText;
}
/**
* MUST RETURN PARAMETER NAMES IN EXACT ORDER AS IN STATEMENT. IF SINGLE
* PARAMETER APPEARS MULTIPLE TIMES, MUST BE LISTED MULTIPLE TIMES IN THE
* ARRAY ALSO
*/
public String[] extractParamNames(String commandText) {
ArrayList<String> hs = new ArrayList<String>();
Matcher mc = getParameterPattern().matcher(commandText);
while (mc.find()) {
String var = mc.group(1);
if (SymbolUtil.hasSymbol(var)) {
hs.add(var);
}
}
String[] array = new String[hs.size()];
return hs.toArray(array);
}
/**
* by default, this will support retrieving a single autogenerated key via
* JDBC. DB environments which support automated column retrieval after
* insert, like oracle, should override this and put in parameters for OUT
* accessors
*/
public String buildInsertCommand(String tableName, DbParameterAccessor[] accessors) {
StringBuilder sb = new StringBuilder("insert into ");
sb.append(tableName).append("(");
String comma = "";
StringBuilder values = new StringBuilder();
for (DbParameterAccessor accessor : accessors) {
if (accessor.getDirection() == DbParameterAccessor.INPUT) {
sb.append(comma);
values.append(comma);
sb.append(this.getFieldQuato()).append(accessor.getName()).append(this.getFieldQuato());
// values.append(":").append(accessor.getName());
values.append("?");
comma = ",";
}
}
sb.append(") values (");
sb.append(values);
sb.append(")");
return sb.toString();
}
public String buildDeleteCommand(String tableName, DbParameterAccessor[] accessors) {
StringBuilder sb = new StringBuilder("delete from " + tableName + " where ");
String comma = "";
for (DbParameterAccessor accessor : accessors) {
if (accessor.getDirection() == DbParameterAccessor.INPUT) {
sb.append(comma);
sb.append(accessor.getName());
sb.append("=?");
comma = ",";
}
}
return sb.toString();
}
public final void teardown() throws SQLException {
}
// ===========================================
public void setDataSource(String driver, String url, String schemas, String username, String password) {
this.dbEnviroment.setDataSource(driver, url, schemas, username, password);
}
/**
* 连接当前数据源
*
* @return
*/
public Connection connect() {
return this.dbEnviroment.connect();
}
public void commit() {
this.dbEnviroment.commit();
}
public void rollback() {
this.dbEnviroment.rollback();
}
public int getExceptionCode(SQLException dbException) {
return this.dbEnviroment.getExceptionCode(dbException);
}
protected abstract Pattern getParameterPattern();
/**
* by default, this is set to false.
*
* @see org.test4j.module.database.environment.DBEnvironment#supportsOuputOnInsert()
*/
public boolean supportsOuputOnInsert() {
return false;
}
/**
* 连接数据源,如果先前没有建立过连接的话
*
* @param environment
* @return 返回数据源连接
* @throws SQLException
*/
public Connection connectIfNeeded() {
return this.dbEnviroment.connect();
}
/**
* 获得数据表的元信息
*
* @param table
* @return
* @throws Exception
*/
public TableMeta getTableMetaData(String table) {
return this.dbEnviroment.getTableMetaData(table);
}
public Object getDefaultValue(String javaType) {
return this.dbEnviroment.getDefaultValue(javaType);
}
public Object toObjectValue(String input, String javaType) {
return this.dbEnviroment.toObjectValue(input, javaType);
}
/**
* {@inheritDoc} <br>
* <br>
* 默认不做转换
*/
public Object converToSqlValue(Object value) {
return value;
}
/** Check the validity of the supplied connection. */
public static void checkConnectionValid(final Connection conn) throws SQLException {
if (conn == null || conn.isClosed()) {
throw new IllegalArgumentException("No open connection to a database is available. "
+ "Make sure your database is running and that you have connected before performing any queries.");
}
}
public static DbFitEnvironment convert(DBEnvironment environment) {
DbFitEnvironment dbfit = null;
if (environment instanceof DB2Environment) {
dbfit = new DbFitDB2Environment(environment);
} else if (environment instanceof DerbyEnvironment) {
dbfit = new DbFitDerbyEnvironment(environment);
} else if (environment instanceof MySqlEnvironment) {
dbfit = new DbFitMySqlEnvironment(environment);
} else if (environment instanceof OracleEnvironment) {
dbfit = new DbFitOracleEnvironment(environment);
} else if (environment instanceof SqlServerEnvironment) {
dbfit = new DbFitSqlServerEnvironment(environment);
}
if (dbfit == null) {
throw new RuntimeException("unkown database type[" + environment.getClass().getName() + "].");
} else {
return dbfit;
}
}
public DataSource getDataSource() {
return this.dbEnviroment.getDataSource();
}
public DataSource getDataSourceAndActivateTransactionIfNeeded() {
return this.dbEnviroment.getDataSourceAndActivateTransactionIfNeeded();
}
public void registerTransactionManagementConfiguration(
TransactionManagementConfiguration transactionManagementConfiguration) {
this.dbEnviroment.registerTransactionManagementConfiguration(transactionManagementConfiguration);
}
public void startTransaction() {
this.dbEnviroment.startTransaction();
}
public void endTransaction() {
this.dbEnviroment.endTransaction();
}
}