/*
* This software is distributed under the terms of the FSF
* Gnu Lesser General Public License (see lgpl.txt).
*
* This program is distributed WITHOUT ANY WARRANTY. See the
* GNU General Public License for more details.
*/
package com.scooterframework.orm.sqldataexpress.vendor;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Map;
import java.util.Properties;
import com.scooterframework.common.logging.LogUtil;
import com.scooterframework.common.util.Util;
import com.scooterframework.orm.sqldataexpress.config.DatabaseConfig;
import com.scooterframework.orm.sqldataexpress.object.Parameter;
import com.scooterframework.orm.sqldataexpress.processor.DataProcessor;
import com.scooterframework.orm.sqldataexpress.util.SqlExpressUtil;
/**
* MySQLDBAdapter class applies to MySQL database.
*
* @author (Fei) John Chen
*/
public class MySQLDBAdapter extends DBAdapter {
private static LogUtil log = LogUtil.getLogger(MySQLDBAdapter.class.getName());
@Override
public String[] getCatalogAndSchema(String connName) {
String[] s2 = new String[2];
s2[0] = getMySQLCatalog(connName);
s2[1] = null;
return s2;
}
protected static String getMySQLCatalog(String connName) {
Properties p = SqlExpressUtil.getConnectionProperties(connName);
String url = p.getProperty(DatabaseConfig.KEY_DB_CONNECTION_URL);
if (url == null || url.indexOf('/') == -1) return null;
int lastSlash = url.lastIndexOf('/');
int q = url.indexOf('?');
return (q == -1)?
url.substring(lastSlash + 1):url.substring(lastSlash + 1, q);
}
/**
* Checks if table name case can be changed.
*
* @return true if table name case can be changed.
*/
@Override
public boolean canChangeTableNameCase() {
return false;
}
/**
* Override the super method because MySQL does not use schema.
*/
@Override
public String[] resolveCatalogAndSchemaAndTableFromTableName(String tableName) {
if (tableName == null)
throw new IllegalArgumentException("tableName cannot be null.");
String[] ss = tableName.split("\\.");
String[] s3 = new String[3];
if (ss.length == 3) {
throw new IllegalArgumentException("'tableName' cannot be of the "
+ "form {catalog}.{schema}.{table} for MySQL.");
} else if (ss.length == 2) {
s3[0] = ss[0];
s3[2] = ss[1];
} else if (ss.length == 1) {
s3[2] = ss[0];
}
return s3;
}
/**
* MySQL does not use <tt>schema</tt>. Therefore it is ignored.
*/
@Override
public String getExpandedTableName(String catalog, String schema, String tableName) {
return super.getExpandedTableName(catalog, IGNORE, tableName);
}
@Override
public String getOneRowSelectSQL(String catalog, String schema, String tableName) {
String selectSQL = "SELECT * FROM ";
selectSQL += getExpandedTableName(catalog, schema, tableName);
selectSQL += " LIMIT 1";
return selectSQL;
}
@Override
public String preparePaginationSql(String selectSql, Map<String, Object> inputs, Map<String, String> outputFilters) {
int offset = Util.getIntValue(inputs, DataProcessor.input_key_records_offset, 0);
boolean hasOffset = (offset > 0)?true:false;
int limit = Util.getIntValue(inputs, DataProcessor.input_key_records_limit, DataProcessor.DEFAULT_PAGINATION_LIMIT);
if (limit == DataProcessor.NO_ROW_LIMIT) limit = DataProcessor.DEFAULT_PAGINATION_LIMIT;
StringBuilder newSelectSqlBF = new StringBuilder(selectSql.length());
newSelectSqlBF.append(selectSql);
newSelectSqlBF.append(" LIMIT ?").append(DataProcessor.input_key_records_limit).append(":INTEGER");
inputs.put(DataProcessor.input_key_records_limit, Integer.valueOf(limit));
if (hasOffset) {
newSelectSqlBF.append(" OFFSET ?").append(DataProcessor.input_key_records_offset).append(":INTEGER");
inputs.put(DataProcessor.input_key_records_offset, Integer.valueOf(offset));
}
return newSelectSqlBF.toString();
}
public Object getObjectFromResultSetByType(ResultSet rs, String javaClassType, int sqlDataType, int index)
throws SQLException {
Object theObj = null;
if ("java.sql.Timestamp".equals(javaClassType) ||
"java.sql.Date".equals(javaClassType) ||
sqlDataType == Types.DATE || sqlDataType == Types.TIMESTAMP) {
try {
theObj = rs.getTimestamp(index);
}
catch(SQLException ex) {
log.warn("Failed to obtain value for SQL data type " +
sqlDataType + " of index " + index + ".", ex);
}
return theObj;
}
return super.getObjectFromResultSetByType(rs, javaClassType, sqlDataType, index);
}
public Object getObjectFromStatementByType(CallableStatement cstmt, String javaClassType, int sqlDataType, int index)
throws SQLException {
Object theObj = null;
if ("java.sql.Timestamp".equals(javaClassType) ||
"java.sql.Date".equals(javaClassType) ||
sqlDataType == Types.DATE || sqlDataType == Types.TIMESTAMP) {
try {
theObj = cstmt.getTimestamp(index);
}
catch(SQLException ex) {
log.warn("Failed to obtain value for SQL data type " +
sqlDataType + " of index " + index + ".", ex);
}
return theObj;
}
return super.getObjectFromStatementByType(cstmt, javaClassType, sqlDataType, index);
}
@Override
public boolean vendorSpecificSetObject(PreparedStatement pstmt, Object obj, Parameter p, Map<String, Object> inputs)
throws Exception {
boolean status = false;
int targetSqlType = p.getSqlDataType();
if (obj != null && (targetSqlType == Types.DATE ||
targetSqlType == Types.TIME ||
targetSqlType == Types.TIMESTAMP)) {
if (obj instanceof String) {
if ("0000-00-00".equals(obj) ||
"0000-00-00 00:00:00".equals(obj)) {
pstmt.setString(p.getIndex(), (String)obj);
status = true;
}
}
}
return status;
}
}