package org.test4j.module.dbfit.environment;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.regex.Pattern;
import org.test4j.module.database.environment.DBEnvironment;
import org.test4j.module.database.environment.normalise.NameNormaliser;
import org.test4j.module.database.environment.typesmap.MySQLTypeMap;
import org.test4j.module.database.utility.DBHelper;
import org.test4j.module.dbfit.model.DbParameterAccessor;
public class DbFitMySqlEnvironment extends DbFitAbstractDBEnvironment {
public DbFitMySqlEnvironment(DBEnvironment dbEnvironemnt) {
super(dbEnvironemnt);
}
public boolean supportsOuputOnInsert() {
return false;
}
private static String paramNamePattern = "@([A-Za-z0-9_]+)";
private static Pattern paramRegex = Pattern.compile(paramNamePattern);
public Pattern getParameterPattern() {
return paramRegex;
}
// mysql jdbc driver does not support named parameters - so just map them
// to standard jdbc question marks
protected String parseCommandText(String commandText, String[] vars) {
if (vars == null || vars.length == 0) {
return commandText;
}
String sql = commandText;
for (String var : vars) {
sql = sql.replace("@" + var, "?");
}
return sql;
}
public Map<String, DbParameterAccessor> getAllColumns(String tableOrViewName) throws SQLException {
String[] qualifiers = NameNormaliser.normaliseName(tableOrViewName).split("\\.");
String qry = " select column_name, data_type, character_maximum_length "
+ " as direction from information_schema.columns where ";
if (qualifiers.length == 2) {
qry += " lower(table_schema)=? and lower(table_name)=? ";
} else {
qry += " (table_schema=database() and lower(table_name)=?)";
}
qry += " order by ordinal_position";
return readIntoParams(qualifiers, qry);
}
private Map<String, DbParameterAccessor> readIntoParams(String[] queryParameters, String query) throws SQLException {
PreparedStatement dc = null;
ResultSet rs = null;
try {
dc = this.connect().prepareStatement(query);
for (int i = 0; i < queryParameters.length; i++) {
dc.setString(i + 1, NameNormaliser.normaliseName(queryParameters[i]));
}
rs = dc.executeQuery();
Map<String, DbParameterAccessor> allParams = new HashMap<String, DbParameterAccessor>();
int position = 0;
while (rs.next()) {
String paramName = rs.getString(1);
if (paramName == null)
paramName = "";
String dataType = rs.getString(2);
DbParameterAccessor dbp = new DbParameterAccessor(paramName, DbParameterAccessor.INPUT,
getSqlType(dataType), getJavaClass(dataType), position++);
allParams.put(NameNormaliser.normaliseName(paramName), dbp);
}
return allParams;
} finally {
DBHelper.closeResultSet(rs);
rs = null;
DBHelper.closeStatement(dc);
dc = null;
}
}
private static String normaliseTypeName(String dataType) {
return dataType.toUpperCase().trim();
}
private static int getSqlType(String dataType) {
dataType = normaliseTypeName(dataType);
Integer type = MySQLTypeMap.getSQLType(dataType);
if (type != null) {
return type;
} else {
throw new UnsupportedOperationException("Type " + dataType + " is not supported");
}
}
@SuppressWarnings("rawtypes")
public Class getJavaClass(String dataType) {
dataType = normaliseTypeName(dataType);
Class clazz = MySQLTypeMap.getJavaType(dataType);
if (clazz != null) {
return clazz;
} else {
return String.class;
// throw new UnsupportedOperationException("Type " + dataType +
// " is not supported");
}
}
public Map<String, DbParameterAccessor> getAllProcedureParameters(String procName) throws SQLException {
String[] qualifiers = NameNormaliser.normaliseName(procName).split("\\.");
String qry = " select type,param_list,returns from mysql.proc where ";
if (qualifiers.length == 2) {
qry += " lower(db)=? and lower(name)=? ";
} else {
qry += " (db=database() and lower(name)=?)";
}
PreparedStatement dc = null;
ResultSet rs = null;
try {
dc = this.connect().prepareStatement(qry);
for (int i = 0; i < qualifiers.length; i++) {
dc.setString(i + 1, NameNormaliser.normaliseName(qualifiers[i]));
}
rs = dc.executeQuery();
if (!rs.next()) {
throw new SQLException("Unknown procedure " + procName);
}
Map<String, DbParameterAccessor> allParams = new HashMap<String, DbParameterAccessor>();
String type = rs.getString(1);
String paramList = rs.getString(2);
String returns = rs.getString(3);
int position = 0;
for (String param : paramList.split(",")) {
StringTokenizer s = new StringTokenizer(param.trim().toLowerCase(), " ()");
String token = s.nextToken();
int direction = DbParameterAccessor.INPUT;
if (token.equals("inout")) {
direction = DbParameterAccessor.INPUT_OUTPUT;
token = s.nextToken();
}
if (token.equals("in")) {
token = s.nextToken();
} else if (token.equals("out")) {
direction = DbParameterAccessor.OUTPUT;
token = s.nextToken();
}
String paramName = token;
String dataType = s.nextToken();
DbParameterAccessor dbp = new DbParameterAccessor(paramName, direction, getSqlType(dataType),
getJavaClass(dataType), position++);
allParams.put(NameNormaliser.normaliseName(paramName), dbp);
}
if ("FUNCTION".equals(type)) {
StringTokenizer s = new StringTokenizer(returns.trim().toLowerCase(), " ()");
String dataType = s.nextToken();
allParams.put("", new DbParameterAccessor("", DbParameterAccessor.RETURN_VALUE, getSqlType(dataType),
getJavaClass(dataType), -1));
}
return allParams;
} finally {
DBHelper.closeResultSet(rs);
rs = null;
DBHelper.closeStatement(dc);
dc = null;
}
}
public String getFieldQuato() {
return "`";
}
}