/******************************************************************************* * Copyright (c) 2015 hangum. * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Lesser Public License v2.1 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html * * Contributors: * hangum - initial API and implementation ******************************************************************************/ package com.hangum.tadpole.engine.sql.util; import java.io.StringWriter; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.apache.commons.dbutils.QueryRunner; import org.apache.commons.dbutils.ResultSetHandler; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.w3c.dom.Document; import org.w3c.dom.Element; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.hangum.tadpole.commons.util.JSONUtil; import com.hangum.tadpole.commons.util.ResultSetToHTMLUtil; import com.hangum.tadpole.engine.define.DBGroupDefine; import com.hangum.tadpole.engine.manager.TadpoleSQLManager; import com.hangum.tadpole.engine.query.dao.system.UserDBDAO; import com.hangum.tadpole.engine.sql.util.resultset.QueryExecuteResultDTO; import com.ibatis.sqlmap.client.SqlMapClient; import au.com.bytecode.opencsv.CSVWriter; /** * Query utils * * @author hangum * */ public class QueryUtils { private static final Logger logger = Logger.getLogger(QueryUtils.class); /** SUPPORT RESULT TYPE */ public static enum RESULT_TYPE {JSON, CSV, XML, HTML_TABLE}; /** * columnname to index * * @param mapColumnLableName * @return */ public static Map<String, Integer> columnNameToIndex(Map<Integer, String> mapColumnLableName) { Map<String, Integer> _reverseColumnName = new HashMap<String, Integer>(); for(int i=0; i<mapColumnLableName.size(); i++) { _reverseColumnName.put(mapColumnLableName.get(i).toUpperCase(), i); } return _reverseColumnName; } /** * select문 이외의 쿼리를 실행합니다 * * @param reqQuery * @exception */ public static Object runSQLOther( final UserDBDAO userDB, String strQuery, final List<Object> listParam ) throws SQLException, Exception { // is tajo if(DBGroupDefine.TAJO_GROUP == userDB.getDBGroup()) { logger.error("Not support TAJO."); } else { java.sql.Connection javaConn = null; PreparedStatement prepareStatement = null; try { javaConn = TadpoleSQLManager.getConnection(userDB); prepareStatement = javaConn.prepareStatement(strQuery); // TODO mysql일 경우 https://github.com/hangum/TadpoleForDBTools/issues/3 와 같은 문제가 있어 create table 테이블명 다음의 '(' 다음에 공백을 넣어주도록 합니다. if(DBGroupDefine.MYSQL_GROUP == userDB.getDBGroup()) { final String checkSQL = strQuery.trim().toUpperCase(); if(StringUtils.startsWithIgnoreCase(checkSQL, "CREATE TABLE")) { //$NON-NLS-1$ strQuery = StringUtils.replaceOnce(strQuery, "(", " ("); //$NON-NLS-1$ //$NON-NLS-2$ } } // // hive는 executeUpdate()를 지원하지 않아서. 13.08.19-hangum // if(userDB.getDBDefine() == DBDefine.HIVE_DEFAULT | // userDB.getDBDefine() == DBDefine.HIVE2_DEFAULT // ) { // return prepareStatement.execute(strQuery); // } else { for(int i=0; i<listParam.size(); i++) { Object objParam = listParam.get(i); prepareStatement.setObject(i+1, objParam); } return prepareStatement.executeUpdate(); } finally { try { if(prepareStatement != null) prepareStatement.close();} catch(Exception e) {} try { if(javaConn != null) javaConn.close();} catch(Exception e) {} } } // end which db return false; } /** * execute query * * @param userDB * @param strQuery * @param intStartCnt * @param intSelectLimitCnt * @return * @throws Exception */ public static QueryExecuteResultDTO executeQuery(final UserDBDAO userDB, String strSQL, final int intStartCnt, final int intSelectLimitCnt) throws Exception { ResultSet resultSet = null; java.sql.Connection javaConn = null; Statement statement = null; strSQL = SQLUtil.makeExecutableSQL(userDB, strSQL); try { javaConn = TadpoleSQLManager.getConnection(userDB); statement = javaConn.createStatement(); if(intStartCnt == 0) { statement.execute(strSQL); resultSet = statement.getResultSet(); } else { strSQL = PartQueryUtil.makeSelect(userDB, strSQL, intStartCnt, intSelectLimitCnt); if(logger.isDebugEnabled()) logger.debug("part sql called : " + strSQL); statement.execute(strSQL); resultSet = statement.getResultSet(); } return new QueryExecuteResultDTO(userDB, strSQL, false, resultSet, intSelectLimitCnt, intStartCnt); } catch(Exception e) { logger.error(String.format("execute query %s", e.getMessage())); throw e; } finally { if(statement != null) statement.close(); if(resultSet != null) resultSet.close(); if(javaConn != null) javaConn.close(); } } /** * execute DML * * @param userDB * @param strQuery * @param listParam * @param resultType * @throws Exception */ public static String executeDML(final UserDBDAO userDB, final String strQuery, final List<Object> listParam, final String resultType) throws Exception { SqlMapClient client = TadpoleSQLManager.getInstance(userDB); Object effectObject = runSQLOther(userDB, strQuery, listParam); String strReturn = ""; if(resultType.equals(RESULT_TYPE.CSV.name())) { final StringWriter stWriter = new StringWriter(); CSVWriter csvWriter = new CSVWriter(stWriter, ','); String[] arryString = new String[2]; arryString[0] = "effectrow"; arryString[1] = String.valueOf(effectObject); csvWriter.writeNext(arryString); strReturn = stWriter.toString(); } else if(resultType.equals(RESULT_TYPE.JSON.name())) { final JsonArray jsonArry = new JsonArray(); JsonObject jsonObj = new JsonObject(); jsonObj.addProperty("effectrow", String.valueOf(effectObject)); jsonArry.add(jsonObj); strReturn = JSONUtil.getPretty(jsonArry.toString()); } else {//if(resultType.equals(RESULT_TYPE.XML.name())) { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); final Document doc = builder.newDocument(); final Element results = doc.createElement("Results"); doc.appendChild(results); Element row = doc.createElement("Row"); results.appendChild(row); Element node = doc.createElement("effectrow"); node.appendChild(doc.createTextNode(String.valueOf(effectObject))); row.appendChild(node); DOMSource domSource = new DOMSource(doc); TransformerFactory tf = TransformerFactory.newInstance(); tf.setAttribute("indent-number", 4); Transformer transformer = tf.newTransformer(); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); transformer.setOutputProperty(OutputKeys.METHOD, "xml"); transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); final StringWriter stWriter = new StringWriter(); StreamResult sr = new StreamResult(stWriter); transformer.transform(domSource, sr); strReturn = stWriter.toString(); } return strReturn; } /** * query to csv * * @param userDB * @param strQuery * @param isAddHead * @param strDelimiter * @return * @throws Exception */ public static String selectToCSV(final UserDBDAO userDB, final String strQuery, final boolean isAddHead, final String strDelimiter) throws Exception { return selectToCSV(userDB, strQuery, new ArrayList(), isAddHead, strDelimiter); } /** * query to csv * * @param userDB * @param strQuery * @param listParam * @param isAddHead is true add head title * @param strDelimiter if delimite is null default comma(,) */ @SuppressWarnings("deprecation") public static String selectToCSV(final UserDBDAO userDB, final String strQuery, final List<Object> listParam, final boolean isAddHead, final String strDelimiter) throws Exception { final StringWriter stWriter = new StringWriter(); SqlMapClient client = TadpoleSQLManager.getInstance(userDB); QueryRunner qr = new QueryRunner(client.getDataSource()); qr.query(strQuery, listParam.toArray(), new ResultSetHandler<Object>() { @Override public Object handle(ResultSet rs) throws SQLException { ResultSetMetaData metaData = rs.getMetaData(); char strDel; if("".equals(strDelimiter)) { strDel = ','; } else if(StringUtils.equalsIgnoreCase("\t", strDelimiter)) { strDel = (char)9; } else { strDel = strDelimiter.charAt(0); } CSVWriter csvWriter = new CSVWriter(stWriter, strDel); if(isAddHead) { String[] arryString = new String[metaData.getColumnCount()]; for (int i = 1; i <= metaData.getColumnCount(); i++) { arryString[i-1] = metaData.getColumnLabel(i); } csvWriter.writeNext(arryString); } while (rs.next()) { String[] arryString = new String[metaData.getColumnCount()]; for (int i = 1; i <= metaData.getColumnCount(); i++) { arryString[i-1] = rs.getString(i); } csvWriter.writeNext(arryString); } return stWriter.toString(); } }); return stWriter.toString(); } /** * query to json * * @param userDB * @param strQuery * @return * @throws Exception */ public static JsonArray selectToJson(final UserDBDAO userDB, final String strQuery) throws Exception { return selectToJson(userDB, strQuery, new ArrayList()); } /** * query to json * * @param userDB * @param strQuery * @param listParam */ @SuppressWarnings("deprecation") public static JsonArray selectToJson(final UserDBDAO userDB, final String strQuery, final List<Object> listParam) throws Exception { final JsonArray jsonArry = new JsonArray(); SqlMapClient client = TadpoleSQLManager.getInstance(userDB); QueryRunner qr = new QueryRunner(client.getDataSource()); qr.query(strQuery, listParam.toArray(), new ResultSetHandler<Object>() { @Override public Object handle(ResultSet rs) throws SQLException { ResultSetMetaData metaData = rs.getMetaData(); while (rs.next()) { JsonObject jsonObj = new JsonObject(); for (int i = 1; i <= metaData.getColumnCount(); i++) { String columnName = metaData.getColumnLabel(i); String value = rs.getString(i) == null ? "" : rs.getString(i); jsonObj.addProperty(columnName.toLowerCase(), value); } jsonArry.add(jsonObj); } return jsonArry; } }); return jsonArry; } /** * query to xml * * @param userDB * @param strQuery * @return * @throws Exception */ public static String selectToXML(final UserDBDAO userDB, final String strQuery) throws Exception { return selectToXML(userDB, strQuery, new ArrayList()); } /** * query to xml * * @param userDB * @param strQuery * @param listParam */ @SuppressWarnings("deprecation") public static String selectToXML(final UserDBDAO userDB, final String strQuery, final List<Object> listParam) throws Exception { final StringWriter stWriter = new StringWriter(); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); final Document doc = builder.newDocument(); final Element results = doc.createElement("Results"); doc.appendChild(results); SqlMapClient client = TadpoleSQLManager.getInstance(userDB); QueryRunner qr = new QueryRunner(client.getDataSource()); qr.query(strQuery, listParam.toArray(), new ResultSetHandler<Object>() { @Override public Object handle(ResultSet rs) throws SQLException { ResultSetMetaData metaData = rs.getMetaData(); while (rs.next()) { Element row = doc.createElement("Row"); results.appendChild(row); for (int i = 1; i <= metaData.getColumnCount(); i++) { String columnName = metaData.getColumnName(i); Object value = rs.getObject(i) == null?"":rs.getObject(i); Element node = doc.createElement(columnName); node.appendChild(doc.createTextNode(value.toString())); row.appendChild(node); } } return stWriter.toString(); } }); DOMSource domSource = new DOMSource(doc); TransformerFactory tf = TransformerFactory.newInstance(); tf.setAttribute("indent-number", 4); Transformer transformer = tf.newTransformer(); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); transformer.setOutputProperty(OutputKeys.METHOD, "xml"); transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");//"ISO-8859-1"); StreamResult sr = new StreamResult(stWriter); transformer.transform(domSource, sr); return stWriter.toString(); } /** * result to html_table * * @param userDB * @param strQuery * @param listParam * @return * @throws Exception */ public static String selectToHTML_TABLE(final UserDBDAO userDB, final String strQuery, final List<Object> listParam) throws Exception { SqlMapClient client = TadpoleSQLManager.getInstance(userDB); QueryRunner qr = new QueryRunner(client.getDataSource()); Object strHTMLTable = qr.query(strQuery, listParam.toArray(), new ResultSetHandler<Object>() { @Override public Object handle(ResultSet rs) throws SQLException { try { return ResultSetToHTMLUtil.makeResultSetTOHTML(rs, 1000); } catch(Exception e) { return e.getMessage(); } } }); return strHTMLTable.toString(); } }