/**
* Copyright (c) 2004-2011 Wang Jinbao(Julian Wong), http://www.ralasafe.com
* Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
*/
package org.ralasafe.util;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.ralasafe.RalasafeException;
import org.ralasafe.db.Column;
import org.ralasafe.db.DBPower;
import org.ralasafe.db.Table;
public class DBUtil {
private static Log log=LogFactory.getLog( DBUtil.class );
public static final String DB2 = "DB2";
public static final String ORACLE = "ORACLE";
public static final String MYSQL = "MYSQL";
public static final String SQLSERVER = "SQL SERVER";
public static final String OTHER_DATABASE = "OTHER";
public static boolean supportsLimit(Connection conn) {
String dataBase = getDatabaseProductName(conn);
if (dataBase.equals(DB2) || dataBase.equals(ORACLE)
|| dataBase.equals(MYSQL)) {
return true;
} else {
return false;
}
}
public static void close(Connection conn) {
if (conn != null) {
try {
if (!conn.isClosed()) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
conn = null;
}
}
}
public static void close(Statement stmt) {
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
} finally {
stmt = null;
}
}
}
public static void close(ResultSet rs) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
} finally {
rs = null;
}
}
}
public static void close(Statement stmt, Connection conn) {
close(stmt);
close(conn);
}
public static void close(ResultSet rs, Statement stmt, Connection conn) {
close(rs);
close(stmt);
close(conn);
}
public static String insertSql(String tableName, String[] columnNames) {
StringBuffer buff = new StringBuffer();
buff.append("INSERT INTO ");
buff.append(tableName);
buff.append(" (");
StringUtil.append(buff, columnNames);
buff.append(") VALUES(");
StringUtil.append(buff, columnNames, false, "?", ",");
buff.append(")");
return buff.toString();
}
public static String selectSql(String tableName, String[] columnNames) {
StringBuffer buff = new StringBuffer();
buff.append("SELECT ");
StringUtil.append(buff, columnNames);
buff.append(" FROM ");
buff.append(tableName);
return buff.toString();
}
public static String selectSql(Table table) {
String tableAlias = " t" + table.getId();
StringBuffer buff = new StringBuffer();
buff.append("SELECT ");
buff.append(columnsString(table.getColumns(), tableAlias));
buff.append(" FROM ");
buff.append(table.getName() + tableAlias);
return buff.toString();
}
private static StringBuffer columnsString(Column[] columns,
String tableAlias) {
StringBuffer buff = new StringBuffer();
buff.append(columnString(columns[0], tableAlias));
for (int i = 1; i < columns.length; i++) {
buff.append(",").append(columnString(columns[i], tableAlias));
}
return buff;
}
private static String columnString(Column column, String tableAlias) {
if (column.getFunction() == null || column.getFunction().equals(""))
return tableAlias + "." + column.getName();
else
return column.getFunction() + "(" + tableAlias + "."
+ column.getName() + ")";
}
public static String updateSql(String tableName, String[] idColumnNames,
String[] exceptIdColumnNames) {
StringBuffer buff = new StringBuffer();
buff.append("UPDATE ");
buff.append(tableName);
buff.append(" SET ");
StringUtil.append(buff, exceptIdColumnNames, true, "=?", ",");
buff.append(" WHERE ");
StringUtil.append(buff, idColumnNames, true, "=?", " AND ");
return buff.toString();
}
public static String deleteSql(String name, String[] idColumnNames) {
StringBuffer buff = new StringBuffer();
buff.append("DELETE FROM ");
buff.append(name);
buff.append(" WHERE ");
StringUtil.append(buff, idColumnNames, true, "=?", " AND ");
return buff.toString();
}
public static String createTableSql(String name, String[] columnNames,
String[] columnSqlTypes) {
StringBuffer buff = new StringBuffer();
buff.append("CREATE TABLE ");
buff.append(name.toLowerCase());
buff.append("(");
for (int i = 0; i < columnNames.length; i++) {
if (i > 0) {
buff.append(",");
}
buff.append(columnNames[i]);
buff.append(" ");
buff.append(columnSqlTypes[i]);
}
buff.append(")");
return buff.toString();
}
public static void exec(Connection conn, String sql) throws SQLException {
PreparedStatement pstmt = null;
try {
pstmt = conn.prepareStatement(sql);
pstmt.execute();
} finally {
close(pstmt);
}
}
public static int getMax(Table table, String columnName)
throws SQLException {
Connection conn = DBPower.getConnection(table.getId());
Statement stmt = null;
ResultSet rs = null;
try {
int max = 0;
String sql = "select MAX( " + columnName + " ) from "
+ table.getName();
stmt = conn.createStatement();
rs = stmt.executeQuery(sql);
if (rs.next()) {
max = rs.getInt(1);
} else {
max = 0;
}
return max;
} finally {
DBUtil.close(rs, stmt, conn);
}
}
// Sequence table name(save sequence value in table)
private static final String RALASAFE_SEQUNCE = "ralasafe_sequence";
/**
* Get next value of certain column of table. For example: user table's id column.
*
* @param table
* @param columnName
* @return
* @throws SQLException
*/
public static int getSequenceNextVal(Table table, String columnName)
throws SQLException {
Integer currentValue=readSequenceCurrentValFromDatabase(table, columnName);
int nextValue=currentValue.intValue()+1;
synchronizeIntoDatabase( table, columnName, nextValue );
return nextValue;
}
private static void synchronizeIntoDatabase(Table table, String columnName,
int synValue) throws SQLException {
Connection conn = null;
PreparedStatement pstmt = null;
try {
conn = DBPower.getConnection(table.getId());
pstmt = conn.prepareStatement("update " + RALASAFE_SEQUNCE
+ " set currentValue=? where name=?");
String name = table.getName() + "_" + columnName;
pstmt.setInt(1, synValue);
pstmt.setString(2, name);
pstmt.executeUpdate();
} finally {
DBUtil.close(pstmt, conn);
}
}
private static Integer readSequenceCurrentValFromDatabase(Table table,
String columnName) throws SQLException {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
conn = DBPower.getConnection(table.getId());
Integer currentValue = null;
pstmt = conn.prepareStatement("select currentValue from "
+ RALASAFE_SEQUNCE + " where name=?");
String name = table.getName() + "_" + columnName;
pstmt.setString(1, name);
rs = pstmt.executeQuery();
if (rs.next()) {
currentValue = new Integer(rs.getInt(1));
}
if (currentValue == null) {
// there's no record in sequence table, then create a record
int max = getMax(table, columnName);
if( max<0 ) {
max=0;
}
DBUtil.exec(conn, "insert into " + RALASAFE_SEQUNCE
+ "(currentValue,name) values(" + max + ",'"
+ name + "')");
return new Integer(max);
}
return currentValue;
} finally {
DBUtil.close(rs, pstmt, conn);
}
}
public static String roleTableCreateSql(String appName) {
String sqlRole = " CREATE TABLE "
+ appName.toLowerCase()
+ "_role ( id integer NOT NULL, name varchar(100) NOT NULL UNIQUE, "
+ "description varchar(500), PRIMARY KEY(id) ) ";
return sqlRole;
}
public static String rolePrivilegeTableCreateSql(String appName) {
String sqlRolePrivilege = " CREATE TABLE "
+ appName.toLowerCase()
+ "_roleprivilege ( roleid integer NOT NULL, privilegeid integer NOT NULL, "
+ "PRIMARY KEY(roleid, privilegeid), FOREIGN KEY(roleid) REFERENCES "
+ appName + "_role (id), FOREIGN KEY(privilegeid) REFERENCES "
+ appName + "_privilege (id)) ";
return sqlRolePrivilege;
}
public static String privilegeTableCreateSql(String appName) {
String sqlPrivilege = " CREATE TABLE "
+ appName.toLowerCase()
+ "_privilege ( id integer NOT NULL, pid integer, "
+ "description varchar(500), name varchar(100) NOT NULL UNIQUE, "
+ "isLeaf integer, display integer, decisionPolicyCombAlg integer, "
+ "queryPolicyCombAlg integer, type integer, constantName varchar(40), "
+ "url varchar(100), target varchar(20), orderNum integer, PRIMARY KEY(id) ) ";
return sqlPrivilege;
}
public static String userRoleTableCreateSql(String appName,
String userTypeName, String idColumnName, String idColumnType) {
String tableName = appName + "_" + userTypeName + "_userrole";
String sqlUserRole = "CREATE TABLE "
+ tableName.toLowerCase()
+ " ( userid "
+ idColumnType
+ " NOT NULL, roleid integer NOT NULL, PRIMARY KEY(userid, roleid), "
+ "FOREIGN KEY(roleid) REFERENCES " + appName + "_role (id)) ";
return sqlUserRole;
}
public static String roleTableDropSql(String appName) {
String sqlRole = " DROP TABLE " + appName + "_role";
return sqlRole;
}
public static String rolePrivilegeTableDropSql(String appName) {
String sqlRolePrivilege = " DROP TABLE " + appName + "_roleprivilege";
return sqlRolePrivilege;
}
public static String privilegeTableDropSql(String appName) {
String sqlPrivilege = " DROP TABLE " + appName + "_privilege";
return sqlPrivilege;
}
public static String userRoleTableDropSql(String appName,
String userTypeName) {
String tableName = appName + "_" + userTypeName + "_userrole";
String sqlUserRole = "DROP TABLE " + tableName;
return sqlUserRole;
}
public static String tableQueryCreateSql(String appName) {
return "CREATE TABLE " + appName.toLowerCase()
+ "_query ( id int NOT NULL,name varchar(100) NOT NULL UNIQUE, "
+ "description varchar(500)," + "installDate date, "
+ "fileName varchar(40),pid int, isLeaf int,"
+ "PRIMARY KEY(id) ) ";
}
public static String tableQueryDropSql(String appName) {
return "DROP TABLE " + appName + "_query";
}
public static String tableUserCategoryCreateSql(String appName) {
return "CREATE TABLE "
+ appName.toLowerCase()
+ "_usercategory ( id int NOT NULL, name varchar(100) NOT NULL UNIQUE, "
+ "description varchar(500), " + "installDate date, "
+ "fileName varchar(40),pid int, isLeaf int,"
+ "PRIMARY KEY(id) ) ";
}
public static String tableUserCategoryDropSql(String appName) {
return "DROP TABLE " + appName + "_usercategory";
}
public static String tableDecisionEntitlementCreateSql(String appName) {
return "create table " + appName.toLowerCase() + "_decision_entitlement("
+ "id int NOT NULL," + "privilegeId int,"
+ "userCategoryId int," + "businessDataId int,"
+ "effect varchar(100)," + "denyReason varchar(1000),"
+ "PRIMARY KEY(id) )";
}
public static String tableDecisionEntitlementDropSql(String appName) {
return "DROP TABLE " + appName + "_decision_entitlement";
}
public static String tableQueryEntitlementCreateSql(String appName) {
return "create table " + appName.toLowerCase() + "_query_entitlement("
+ "id int NOT NULL," + "privilegeId int,"
+ "userCategoryId int," + "queryId int,"
+ "description varchar(500)," + "PRIMARY KEY(id) )";
}
public static String tableQueryEntitlementDropSql(String appName) {
return "DROP TABLE " + appName + "_query_entitlement";
}
public static String tableBusinessDataCreateSql(String appName) {
return "CREATE TABLE "
+ appName.toLowerCase()
+ "_businessdata ( id int NOT NULL,name varchar(100) NOT NULL UNIQUE, "
+ "description varchar(500)," + "installDate date, "
+ "fileName varchar(40),pid int, isLeaf int, "
+ "PRIMARY KEY(id) ) ";
}
public static String tableBusinessDataDropSql(String appName) {
return "DROP TABLE " + appName + "_businessdata";
}
public static String tableBackUpCreateSql(String appName) {
return "CREATE TABLE "
+ appName.toLowerCase()
+ "_backup ( id int NOT NULL,createTime timestamp, "
+ "description varchar(500),content blob,"
+ "PRIMARY KEY(id) ) ";
}
public static String tableBackupDropSql(String appName) {
return "DROP TABLE " + appName + "_backup";
}
public static String getLimitString(Connection conn, String sql, int first,
int max) {
String dataBase = getDatabaseProductName(conn);
String result=sql;
if (dataBase.equals(DB2)) {
result=getDB2LimitString(sql, first, max);
} else if (dataBase.equals(ORACLE)) {
result=getOracleLimitString(sql, first, max);
} else if (dataBase.equals(MYSQL)) {
result=getMySQLLimitString(sql, first, max);
}
if( log.isDebugEnabled() ) {
log.debug( "\n"+result );
}
return result;
}
private static String getMySQLLimitString(String sql, int first, int max) {
return new StringBuffer(sql.length() + 20).append(sql).append(
" limit " + first + ", " + max).toString();
}
private static String getOracleLimitString(String sql, int first, int max) {
sql = sql.trim();
boolean isForUpdate = false;
if (sql.toLowerCase().endsWith(" for update")) {
sql = sql.substring(0, sql.length() - 11);
isForUpdate = true;
}
StringBuffer pagingSelect = new StringBuffer(sql.length() + 100);
pagingSelect
.append("select * from ( select row_.*, rownum rownum_ from ( ");
pagingSelect.append(sql);
// hibernate style
// pagingSelect.append(" ) row_ ) where rownum_ <= " + (first + max)
// + " and rownum_ > " + first);
// better style
pagingSelect.append(" ) row_ where rownum <= " + (first + max)
+ ") where " + " rownum_ >= " + (first + 1));
if (isForUpdate) {
pagingSelect.append(" for update");
}
return pagingSelect.toString();
}
private static String getDB2LimitString(String sql, int first, int max) {
int startOfSelect = sql.toLowerCase().indexOf("select");
StringBuffer pagingSelect = new StringBuffer(sql.length() + 100)
.append(sql.substring(0, startOfSelect)) // add the comment
.append("select * from ( select ") // nest the main query in an
// outer select
.append(getRowNumber(sql)); // add the rownnumber bit into the
// outer query select list
if (hasDistinct(sql)) {
pagingSelect.append(" row_.* from ( ") // add another (inner) nested
// select
.append(sql.substring(startOfSelect)) // add the main query
.append(" ) as row_"); // close off the inner nested select
} else {
pagingSelect.append(sql.substring(startOfSelect + 6)); // add the
// main
// query
}
pagingSelect.append(" ) as temp_ where rownumber_ ");
// add the restriction to the outer select
pagingSelect.append("between " + (first + 1) + " and " + (first + max));
return pagingSelect.toString();
}
private static boolean hasDistinct(String sql) {
return sql.toLowerCase().indexOf("select distinct") >= 0;
}
/**
* Render the <tt>rownumber() over ( .... ) as rownumber_,</tt> bit, that
* goes in the select list
*/
private static String getRowNumber(String sql) {
StringBuffer rownumber = new StringBuffer(50)
.append("rownumber() over(");
int orderByIndex = sql.toLowerCase().indexOf("order by");
if (orderByIndex > 0 && !hasDistinct(sql)) {
rownumber.append(sql.substring(orderByIndex));
}
rownumber.append(") as rownumber_,");
return rownumber.toString();
}
public static String getDatabaseProductName(Connection conn) {
String dataBase;
try {
dataBase = conn.getMetaData().getDatabaseProductName();
dataBase = dataBase.toUpperCase();
} catch (SQLException e) {
throw new RalasafeException(e);
}
if (dataBase.indexOf(DB2) >= 0) {
return DB2;
} else if (dataBase.indexOf(ORACLE) >= 0) {
return ORACLE;
} else if (dataBase.indexOf(MYSQL) >= 0) {
return MYSQL;
} else if (dataBase.indexOf(SQLSERVER) >= 0) {
return SQLSERVER;
} else {
return OTHER_DATABASE;
}
}
public static String getDefaultSchema(Connection conn) throws SQLException {
String productName = getDatabaseProductName(conn);
if (productName.equals(MYSQL) || productName.equals(SQLSERVER)) {
return conn.getCatalog();
} else {
DatabaseMetaData metaData = conn.getMetaData();
return metaData.getUserName();
}
}
public static void setCommitMode(Connection conn, boolean autoCommit) {
if (conn != null) {
try {
conn.setAutoCommit(autoCommit);
} catch (SQLException e) {
}
}
}
public static void rollback(Connection conn) {
if (conn != null) {
try {
conn.rollback();
} catch (SQLException e) {
}
}
}
}