/*
* Copyright 1999-2011 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.druid.util;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.StringWriter;
import java.math.BigDecimal;
import java.net.URL;
import java.sql.Connection;
import java.sql.Date;
import java.sql.Driver;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import com.alibaba.druid.logging.Log;
import com.alibaba.druid.logging.LogFactory;
import com.alibaba.druid.mapping.DruidMappingException;
/**
* @author wenshao<szujobs@hotmail.com>
*/
public final class JdbcUtils {
private final static Log LOG = LogFactory.getLog(JdbcUtils.class);
private static final Properties driverUrlMapping = new Properties();
static {
try {
for (Enumeration<URL> e = Thread.currentThread().getContextClassLoader().getResources("META-INF/druid-driver.properties"); e.hasMoreElements();) {
URL url = e.nextElement();
Properties property = new Properties();
InputStream is = null;
try {
is = url.openStream();
property.load(is);
} finally {
JdbcUtils.close(is);
}
driverUrlMapping.putAll(property);
}
} catch (Exception e) {
LOG.error("load druid-driver.properties error", e);
}
}
public final static void close(Connection x) {
if (x != null) {
try {
x.close();
} catch (Exception e) {
LOG.error("close connection error", e);
}
}
}
public final static void close(Statement x) {
if (x != null) {
try {
x.close();
} catch (Exception e) {
LOG.error("close statement error", e);
}
}
}
public final static void close(ResultSet x) {
if (x != null) {
try {
x.close();
} catch (Exception e) {
LOG.error("close resultset error", e);
}
}
}
public final static void close(Closeable x) {
if (x != null) {
try {
x.close();
} catch (Exception e) {
LOG.error("close error", e);
}
}
}
public final static void printResultSet(ResultSet rs) throws SQLException {
printResultSet(rs, System.out);
}
public final static void printResultSet(ResultSet rs, PrintStream out) throws SQLException {
ResultSetMetaData metadata = rs.getMetaData();
int columnCount = metadata.getColumnCount();
for (int columnIndex = 1; columnIndex <= columnCount; ++columnIndex) {
if (columnIndex != 1) {
out.print('\t');
}
out.print(metadata.getColumnName(columnIndex));
}
out.println();
while (rs.next()) {
for (int columnIndex = 1; columnIndex <= columnCount; ++columnIndex) {
if (columnIndex != 1) {
out.print('\t');
}
int type = metadata.getColumnType(columnIndex);
if (type == Types.VARCHAR || type == Types.CHAR || type == Types.NVARCHAR || type == Types.NCHAR) {
out.print(rs.getString(columnIndex));
} else if (type == Types.DATE) {
Date date = rs.getDate(columnIndex);
if (rs.wasNull()) {
out.print("null");
} else {
out.print(date.toString());
}
} else if (type == Types.BIT) {
boolean value = rs.getBoolean(columnIndex);
if (rs.wasNull()) {
out.print("null");
} else {
out.print(Boolean.toString(value));
}
} else if (type == Types.BOOLEAN) {
boolean value = rs.getBoolean(columnIndex);
if (rs.wasNull()) {
out.print("null");
} else {
out.print(Boolean.toString(value));
}
} else if (type == Types.TINYINT) {
byte value = rs.getByte(columnIndex);
if (rs.wasNull()) {
out.print("null");
} else {
out.print(Byte.toString(value));
}
} else if (type == Types.SMALLINT) {
short value = rs.getShort(columnIndex);
if (rs.wasNull()) {
out.print("null");
} else {
out.print(Short.toString(value));
}
} else if (type == Types.INTEGER) {
int value = rs.getInt(columnIndex);
if (rs.wasNull()) {
out.print("null");
} else {
out.print(Integer.toString(value));
}
} else if (type == Types.BIGINT) {
long value = rs.getLong(columnIndex);
if (rs.wasNull()) {
out.print("null");
} else {
out.print(Long.toString(value));
}
} else if (type == Types.TIMESTAMP) {
out.print(String.valueOf(rs.getTimestamp(columnIndex)));
} else if (type == Types.DECIMAL) {
out.print(String.valueOf(rs.getBigDecimal(columnIndex)));
} else if (type == Types.CLOB) {
out.print(String.valueOf(rs.getString(columnIndex)));
} else if (type == Types.JAVA_OBJECT) {
Object objec = rs.getObject(columnIndex);
if (rs.wasNull()) {
out.print("null");
} else {
out.print(String.valueOf(objec));
}
} else if (type == Types.LONGVARCHAR) {
Object objec = rs.getString(columnIndex);
if (rs.wasNull()) {
out.print("null");
} else {
out.print(String.valueOf(objec));
}
} else {
Object objec = rs.getObject(columnIndex);
if (rs.wasNull()) {
out.print("null");
} else {
out.print(String.valueOf(objec));
}
}
}
out.println();
}
}
public static String getTypeName(int sqlType) {
switch (sqlType) {
case Types.ARRAY:
return "ARRAY";
case Types.BIGINT:
return "BIGINT";
case Types.BINARY:
return "BINARY";
case Types.BIT:
return "BIT";
case Types.BLOB:
return "BLOB";
case Types.BOOLEAN:
return "BOOLEAN";
case Types.CHAR:
return "CHAR";
case Types.CLOB:
return "CLOB";
case Types.DATALINK:
return "DATALINK";
case Types.DATE:
return "DATE";
case Types.DECIMAL:
return "DECIMAL";
case Types.DISTINCT:
return "DISTINCT";
case Types.DOUBLE:
return "DOUBLE";
case Types.FLOAT:
return "FLOAT";
case Types.INTEGER:
return "INTEGER";
case Types.JAVA_OBJECT:
return "JAVA_OBJECT";
case Types.LONGNVARCHAR:
return "LONGNVARCHAR";
case Types.LONGVARBINARY:
return "LONGVARBINARY";
case Types.NCHAR:
return "NCHAR";
case Types.NCLOB:
return "NCLOB";
case Types.NULL:
return "NULL";
case Types.NUMERIC:
return "NUMERIC";
case Types.NVARCHAR:
return "NVARCHAR";
case Types.REAL:
return "REAL";
case Types.REF:
return "REF";
case Types.ROWID:
return "ROWID";
case Types.SMALLINT:
return "SMALLINT";
case Types.SQLXML:
return "SQLXML";
case Types.STRUCT:
return "STRUCT";
case Types.TIME:
return "TIME";
case Types.TIMESTAMP:
return "TIMESTAMP";
case Types.TINYINT:
return "TINYINT";
case Types.VARBINARY:
return "VARBINARY";
case Types.VARCHAR:
return "VARCHAR";
default:
return "OTHER";
}
}
public static String read(Reader reader) {
try {
final int DEFAULT_BUFFER_SIZE = 1024 * 4;
StringWriter writer = new StringWriter();
char[] buffer = new char[DEFAULT_BUFFER_SIZE];
int n = 0;
while (-1 != (n = reader.read(buffer))) {
writer.write(buffer, 0, n);
}
return writer.toString();
} catch (IOException ex) {
throw new IllegalStateException("read error", ex);
}
}
public static String read(Reader reader, int length) {
try {
char[] buffer = new char[length];
int offset = 0;
int rest = length;
int len;
while ((len = reader.read(buffer, offset, rest)) != -1) {
rest -= len;
offset += len;
if (rest == 0) {
break;
}
}
return new String(buffer, 0, length - rest);
} catch (IOException ex) {
throw new IllegalStateException("read error", ex);
}
}
public static String getDriverClassName(String rawUrl) throws SQLException {
if (rawUrl.startsWith("jdbc:derby:")) {
return "org.apache.derby.jdbc.EmbeddedDriver";
} else if (rawUrl.startsWith("jdbc:mysql:")) {
return "com.mysql.jdbc.Driver";
} else if (rawUrl.startsWith("jdbc:oracle:")) {
return "oracle.jdbc.driver.OracleDriver";
} else if (rawUrl.startsWith("jdbc:microsoft:")) {
return "com.microsoft.jdbc.sqlserver.SQLServerDriver";
} else if (rawUrl.startsWith("jdbc:sqlserver:")) {
return "com.microsoft.jdbc.sqlserver.SQLServerDriver";
} else if (rawUrl.startsWith("jdbc:sybase:Tds:")) {
return "com.sybase.jdbc2.jdbc.SybDriver";
} else if (rawUrl.startsWith("jdbc:jtds:")) {
return "net.sourceforge.jtds.jdbc.Driver";
} else if (rawUrl.startsWith("jdbc:fake:") || rawUrl.startsWith("jdbc:mock:")) {
return "com.alibaba.druid.mock.MockDriver";
} else if (rawUrl.startsWith("jdbc:postgresql:")) {
return "org.postgresql.Driver";
} else if (rawUrl.startsWith("jdbc:hsqldb:")) {
return "org.hsqldb.jdbcDriver";
} else if (rawUrl.startsWith("jdbc:db2:")) {
return "COM.ibm.db2.jdbc.app.DB2Driver";
} else if (rawUrl.startsWith("jdbc:sqlite:")) {
return "org.sqlite.JDBC";
} else if (rawUrl.startsWith("jdbc:ingres:")) {
return "com.ingres.jdbc.IngresDriver";
} else if (rawUrl.startsWith("jdbc:h2:")) {
return "org.h2.Driver";
} else if (rawUrl.startsWith("jdbc:mckoi:")) {
return "com.mckoi.JDBCDriver";
} else if (rawUrl.startsWith("jdbc:cloudscape:")) {
return "COM.cloudscape.core.JDBCDriver";
} else if (rawUrl.startsWith("jdbc:informix-sqli:")) {
return "com.informix.jdbc.IfxDriver";
} else if (rawUrl.startsWith("jdbc:timesten:")) {
return "com.timesten.jdbc.TimesTenDriver";
} else if (rawUrl.startsWith("jdbc:as400:")) {
return "com.ibm.as400.access.AS400JDBCDriver";
} else if (rawUrl.startsWith("jdbc:sapdb:")) {
return "com.sap.dbtech.jdbc.DriverSapDB";
} else if (rawUrl.startsWith("jdbc:JSQLConnect:")) {
return "com.jnetdirect.jsql.JSQLDriver";
} else if (rawUrl.startsWith("jdbc:JTurbo:")) {
return "com.newatlanta.jturbo.driver.Driver";
} else if (rawUrl.startsWith("jdbc:firebirdsql:")) {
return "org.firebirdsql.jdbc.FBDriver";
} else if (rawUrl.startsWith("jdbc:interbase:")) {
return "interbase.interclient.Driver";
} else if (rawUrl.startsWith("jdbc:pointbase:")) {
return "com.pointbase.jdbc.jdbcUniversalDriver";
} else if (rawUrl.startsWith("jdbc:edbc:")) {
return "ca.edbc.jdbc.EdbcDriver";
} else if (rawUrl.startsWith("jdbc:mimer:multi1:")) {
return "com.mimer.jdbc.Driver";
} else {
throw new SQLException("unkow jdbc driver : " + rawUrl);
}
}
public static String getDbType(String rawUrl, String driverClassName) {
if (rawUrl == null) {
return null;
}
if (rawUrl.startsWith("jdbc:derby:")) {
return "derby";
} else if (rawUrl.startsWith("jdbc:mysql:")) {
return "mysql";
} else if (rawUrl.startsWith("jdbc:oracle:")) {
return "oracle";
} else if (rawUrl.startsWith("jdbc:microsoft:")) {
return "sqlserver";
} else if (rawUrl.startsWith("jdbc:sybase:Tds:")) {
return "sybase";
} else if (rawUrl.startsWith("jdbc:jtds:")) {
return "jtds";
} else if (rawUrl.startsWith("jdbc:fake:") || rawUrl.startsWith("jdbc:mock:")) {
return "mock";
} else if (rawUrl.startsWith("jdbc:postgresql:")) {
return "postgresql";
} else if (rawUrl.startsWith("jdbc:hsqldb:")) {
return "hsql";
} else if (rawUrl.startsWith("jdbc:db2:")) {
return "db2";
} else if (rawUrl.startsWith("jdbc:sqlite:")) {
return "sqlite";
} else if (rawUrl.startsWith("jdbc:ingres:")) {
return "ingres";
} else if (rawUrl.startsWith("jdbc:h2:")) {
return "h2";
} else if (rawUrl.startsWith("jdbc:mckoi:")) {
return "mckoi";
} else if (rawUrl.startsWith("jdbc:cloudscape:")) {
return "cloudscape";
} else if (rawUrl.startsWith("jdbc:informix-sqli:")) {
return "informix";
} else if (rawUrl.startsWith("jdbc:timesten:")) {
return "timesten";
} else if (rawUrl.startsWith("jdbc:as400:")) {
return "as400";
} else if (rawUrl.startsWith("jdbc:sapdb:")) {
return "sapdb";
} else if (rawUrl.startsWith("jdbc:JSQLConnect:")) {
return "JSQLConnect";
} else if (rawUrl.startsWith("jdbc:JTurbo:")) {
return "JTurbo";
} else if (rawUrl.startsWith("jdbc:firebirdsql:")) {
return "firebirdsql";
} else if (rawUrl.startsWith("jdbc:interbase:")) {
return "interbase";
} else if (rawUrl.startsWith("jdbc:pointbase:")) {
return "pointbase";
} else if (rawUrl.startsWith("jdbc:edbc:")) {
return "edbc";
} else if (rawUrl.startsWith("jdbc:mimer:multi1:")) {
return "mimer";
} else {
return null;
}
}
public static String getStackTrace(Throwable ex) {
StringWriter buf = new StringWriter();
ex.printStackTrace(new PrintWriter(buf));
return buf.toString();
}
public static String toString(java.util.Date date) {
if (date == null) {
return null;
}
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return format.format(date);
}
public static Driver createDriver(String driverClassName) throws SQLException {
try {
return (Driver) Class.forName(driverClassName).newInstance();
} catch (IllegalAccessException e) {
throw new SQLException(e.getMessage(), e);
} catch (InstantiationException e) {
throw new SQLException(e.getMessage(), e);
} catch (ClassNotFoundException e) {
throw new SQLException(e.getMessage(), e);
}
}
public static int executeUpdate(Connection conn, String sql, List<Object> parameters) throws SQLException {
PreparedStatement stmt = null;
int updateCount;
try {
stmt = conn.prepareStatement(sql);
setParameters(stmt, parameters);
updateCount = stmt.executeUpdate();
} finally {
JdbcUtils.close(stmt);
}
return updateCount;
}
public static void execute(Connection conn, String sql, List<Object> parameters) throws SQLException {
PreparedStatement stmt = null;
try {
stmt = conn.prepareStatement(sql);
setParameters(stmt, parameters);
stmt.executeUpdate();
} finally {
JdbcUtils.close(stmt);
}
}
public static List<Map<String, Object>> executeQuery(Connection conn, String sql, List<Object> parameters)
throws SQLException {
List<Map<String, Object>> rows = new ArrayList<Map<String, Object>>();
PreparedStatement stmt = null;
ResultSet rs = null;
try {
stmt = conn.prepareStatement(sql);
setParameters(stmt, parameters);
rs = stmt.executeQuery();
ResultSetMetaData rsMeta = rs.getMetaData();
while (rs.next()) {
Map<String, Object> row = new LinkedHashMap<String, Object>();
for (int i = 0, size = rsMeta.getColumnCount(); i < size; ++i) {
String columName = rsMeta.getColumnName(i + 1);
Object value = rs.getObject(i + 1);
row.put(columName, value);
}
rows.add(row);
}
} finally {
JdbcUtils.close(rs);
JdbcUtils.close(stmt);
}
return rows;
}
private static void setParameters(PreparedStatement stmt, List<Object> parameters) throws SQLException {
for (int i = 0, size = parameters.size(); i < size; ++i) {
Object val = parameters.get(i);
int paramIndex = i + 1;
if (val == null) {
stmt.setNull(paramIndex, Types.VARCHAR);
} else if (val instanceof BigDecimal) {
stmt.setBigDecimal(paramIndex, (BigDecimal) val);
} else if (val instanceof String) {
stmt.setString(paramIndex, (String) val);
} else if (val instanceof Date) {
long time = ((Date) val).getTime();
stmt.setTimestamp(paramIndex, new java.sql.Timestamp(time));
} else if (val instanceof Byte) {
stmt.setByte(paramIndex, (Byte) val);
} else if (val instanceof Short) {
stmt.setShort(paramIndex, (Short) val);
} else if (val instanceof Integer) {
stmt.setInt(paramIndex, (Integer) val);
} else if (val instanceof Long) {
stmt.setLong(paramIndex, (Long) val);
} else if (val instanceof Float) {
stmt.setFloat(paramIndex, (Float) val);
} else if (val instanceof Double) {
stmt.setDouble(paramIndex, (Double) val);
} else {
throw new DruidMappingException("not support parameters : " + val);
}
}
}
public static String toString(StackTraceElement[] stackTrace) {
StringBuilder buf = new StringBuilder();
for (StackTraceElement item : stackTrace) {
buf.append(item.toString());
buf.append("\n");
}
return buf.toString();
}
}