From 856517415d6c668e5dc5b6ed78c0650ce67c8cad Mon Sep 17 00:00:00 2001 From: Heng Sin Low Date: Thu, 23 Nov 2006 03:25:28 +0000 Subject: [PATCH] * Improve startup time * Make validation of application server and database connection on startup optional * Separate the database interface file by database. This will ease concurrent development of multiple database support. --- .../org/compiere/db/AdempiereDatabase.java | 4 + dbPort/src/org/compiere/db/CConnection.java | 50 +- dbPort/src/org/compiere/db/DB_DB2.java | 5 + dbPort/src/org/compiere/db/DB_Oracle.java | 8 + dbPort/src/org/compiere/db/DB_PostgreSQL.java | 24 +- dbPort/src/org/compiere/db/Database.java | 20 + dbPort/src/org/compiere/dbPort/Convert.java | 2052 +---------------- .../org/compiere/dbPort/ConvertDialog.java | 54 +- .../src/org/compiere/dbPort/ConvertMap.java | 260 --- .../org/compiere/dbPort/ConvertMap_DB2.java | 106 + .../org/compiere/dbPort/ConvertMap_Derby.java | 78 + .../dbPort/ConvertMap_PostgreSQL.java | 97 + .../org/compiere/dbPort/Convert_Oracle.java | 21 + .../compiere/dbPort/Convert_PostgreSQL.java | 1672 ++++++++++++++ .../org/compiere/dbPort/Convert_SQL92.java | 382 +++ dbPort/src/org/compiere/util/DB.java | 32 +- 16 files changed, 2531 insertions(+), 2334 deletions(-) delete mode 100644 dbPort/src/org/compiere/dbPort/ConvertMap.java create mode 100644 dbPort/src/org/compiere/dbPort/ConvertMap_DB2.java create mode 100644 dbPort/src/org/compiere/dbPort/ConvertMap_Derby.java create mode 100644 dbPort/src/org/compiere/dbPort/ConvertMap_PostgreSQL.java create mode 100644 dbPort/src/org/compiere/dbPort/Convert_Oracle.java create mode 100644 dbPort/src/org/compiere/dbPort/Convert_PostgreSQL.java create mode 100644 dbPort/src/org/compiere/dbPort/Convert_SQL92.java diff --git a/dbPort/src/org/compiere/db/AdempiereDatabase.java b/dbPort/src/org/compiere/db/AdempiereDatabase.java index 33d7e78daa..0f6a5842c9 100644 --- a/dbPort/src/org/compiere/db/AdempiereDatabase.java +++ b/dbPort/src/org/compiere/db/AdempiereDatabase.java @@ -21,6 +21,8 @@ import java.sql.*; import javax.sql.*; +import org.compiere.dbPort.Convert; + //import org.compiere.util.CPreparedStatement; /** @@ -263,6 +265,8 @@ public interface AdempiereDatabase * Close */ public void close(); + + public Convert getConvert(); /** * Get Data Type diff --git a/dbPort/src/org/compiere/db/CConnection.java b/dbPort/src/org/compiere/db/CConnection.java index a981a17b3a..5ab8cb36da 100644 --- a/dbPort/src/org/compiere/db/CConnection.java +++ b/dbPort/src/org/compiere/db/CConnection.java @@ -209,6 +209,9 @@ public class CConnection implements Serializable private Server m_server = null; /** DB Info */ private String m_dbInfo = null; + + /** Had application server been query **/ + private boolean m_queryAppsServer = false; /************************************************************************* @@ -256,6 +259,7 @@ public class CConnection implements Serializable m_apps_host = apps_host; m_name = toString (); m_okApps = false; + m_queryAppsServer = false; } /** @@ -275,6 +279,7 @@ public class CConnection implements Serializable { m_apps_port = apps_port; m_okApps = false; + m_queryAppsServer = false; } /** @@ -303,9 +308,11 @@ public class CConnection implements Serializable */ public boolean isAppsServerOK (boolean tryContactAgain) { - if (!tryContactAgain) + if (!tryContactAgain && m_queryAppsServer) return m_okApps; + m_queryAppsServer = true; + // Get Context if (m_iContext == null) { @@ -340,8 +347,9 @@ public class CConnection implements Serializable */ public Exception testAppsServer () { - if (queryAppsServerInfo ()) - testDatabase (false); + //if (queryAppsServerInfo ()) + // testDatabase (false); + queryAppsServerInfo (); return getAppsServerException (); } // testAppsServer @@ -966,18 +974,9 @@ public class CConnection implements Serializable Connection.TRANSACTION_READ_COMMITTED); if (conn != null) { - try + try { - DatabaseMetaData dbmd = conn.getMetaData (); - m_info[0] = "Database=" + dbmd.getDatabaseProductName () - + " - " + dbmd.getDatabaseProductVersion (); - m_info[0] = m_info[0].replace ('\n', ' '); - m_info[1] = "Driver =" + dbmd.getDriverName () - + " - " + dbmd.getDriverVersion (); - if (isDataSource()) - m_info[1] += " - via DataSource"; - m_info[1] = m_info[1].replace ('\n', ' '); - log.config(m_info[0] + " - " + m_info[1]); + readInfo(conn); conn.close (); } catch (Exception e) @@ -989,6 +988,18 @@ public class CConnection implements Serializable return m_dbException; // from opening } // testDatabase + public void readInfo(Connection conn) throws SQLException { + DatabaseMetaData dbmd = conn.getMetaData (); + m_info[0] = "Database=" + dbmd.getDatabaseProductName () + + " - " + dbmd.getDatabaseProductVersion (); + m_info[0] = m_info[0].replace ('\n', ' '); + m_info[1] = "Driver =" + dbmd.getDriverName () + + " - " + dbmd.getDriverVersion (); + if (isDataSource()) + m_info[1] += " - via DataSource"; + m_info[1] = m_info[1].replace ('\n', ' '); + log.config(m_info[0] + " - " + m_info[1]); + } /************************************************************************* * Short String representation @@ -1200,15 +1211,7 @@ public class CConnection implements Serializable { try { - for (int i = 0; i < Database.DB_NAMES.length; i++) - { - if (Database.DB_NAMES[i].equals (m_type)) - { - m_db = (AdempiereDatabase)Database.DB_CLASSES[i]. - newInstance (); - break; - } - } + m_db = Database.getDatabase(m_type); } catch (Exception e) { @@ -1491,6 +1494,7 @@ public class CConnection implements Serializable log.finer(getAppsHost()); long start = System.currentTimeMillis(); m_okApps = false; + m_queryAppsServer = true; m_appsException = null; // getInitialContext (false); diff --git a/dbPort/src/org/compiere/db/DB_DB2.java b/dbPort/src/org/compiere/db/DB_DB2.java index 0274d6e464..8bd7c29a36 100644 --- a/dbPort/src/org/compiere/db/DB_DB2.java +++ b/dbPort/src/org/compiere/db/DB_DB2.java @@ -21,6 +21,7 @@ import java.sql.*; import java.util.logging.*; import javax.sql.*; +import org.compiere.dbPort.Convert; import org.compiere.util.*; import com.ibm.db2.jcc.*; @@ -832,5 +833,9 @@ public class DB_DB2 } /** **/ } // main + + public Convert getConvert() { + throw new UnsupportedOperationException("Not implemented."); + } } // DB_DB2 diff --git a/dbPort/src/org/compiere/db/DB_Oracle.java b/dbPort/src/org/compiere/db/DB_Oracle.java index 9f46fad846..53c4b54eb4 100644 --- a/dbPort/src/org/compiere/db/DB_Oracle.java +++ b/dbPort/src/org/compiere/db/DB_Oracle.java @@ -24,6 +24,8 @@ import javax.sql.*; import oracle.jdbc.*; import oracle.jdbc.pool.*; import org.compiere.*; +import org.compiere.dbPort.Convert; +import org.compiere.dbPort.Convert_Oracle; import org.compiere.util.*; /** @@ -77,6 +79,8 @@ public class DB_Oracle implements AdempiereDatabase, OracleConnectionCacheCallba private static final String CACHE_NAME = "AdempiereCCache"; /** Cached User Name */ private String m_userName = null; + + private Convert m_convert = new Convert_Oracle(); /** Logger */ private static CLogger log = CLogger.getCLogger (DB_Oracle.class); @@ -1108,5 +1112,9 @@ public class DB_Oracle implements AdempiereDatabase, OracleConnectionCacheCallba } **/ } // main + + public Convert getConvert() { + return m_convert; + } } // DB_Oracle diff --git a/dbPort/src/org/compiere/db/DB_PostgreSQL.java b/dbPort/src/org/compiere/db/DB_PostgreSQL.java index c4289e3664..4c70c0ae36 100755 --- a/dbPort/src/org/compiere/db/DB_PostgreSQL.java +++ b/dbPort/src/org/compiere/db/DB_PostgreSQL.java @@ -14,13 +14,21 @@ *****************************************************************************/ package org.compiere.db; -import java.math.*; -import java.sql.*; +import java.math.BigDecimal; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.sql.Timestamp; import java.util.logging.Level; -import javax.sql.*; -import org.compiere.dbPort.*; -import org.compiere.util.*; +import javax.sql.ConnectionPoolDataSource; +import javax.sql.DataSource; +import javax.sql.RowSet; + +import org.compiere.dbPort.Convert; +import org.compiere.dbPort.Convert_PostgreSQL; +import org.compiere.util.CLogger; +import org.compiere.util.DisplayType; /** * PostgreSQL Database Port @@ -30,6 +38,10 @@ import org.compiere.util.*; */ public class DB_PostgreSQL implements AdempiereDatabase { + public Convert getConvert() { + return m_convert; + } + /** * PostgreSQL Database */ @@ -47,7 +59,7 @@ public class DB_PostgreSQL implements AdempiereDatabase private org.postgresql.ds.PGPoolingDataSource m_ds = null; /** Statement Converter */ - private Convert m_convert = new Convert(Database.DB_POSTGRESQL); + private Convert_PostgreSQL m_convert = new Convert_PostgreSQL(); /** Connection String */ private String m_connection; /** Cached Database Name */ diff --git a/dbPort/src/org/compiere/db/Database.java b/dbPort/src/org/compiere/db/Database.java index b9f5b285ac..63b0fb9fdd 100644 --- a/dbPort/src/org/compiere/db/Database.java +++ b/dbPort/src/org/compiere/db/Database.java @@ -66,5 +66,25 @@ public class Database /** Connection Timeout in seconds */ public static int CONNECTION_TIMEOUT = 10; + + /** + * Get Database + * @return database + */ + public static AdempiereDatabase getDatabase (String type) + throws Exception + { + AdempiereDatabase db = null; + for (int i = 0; i < Database.DB_NAMES.length; i++) + { + if (Database.DB_NAMES[i].equals (type)) + { + db = (AdempiereDatabase)Database.DB_CLASSES[i]. + newInstance (); + break; + } + } + return db; + } } // Database diff --git a/dbPort/src/org/compiere/dbPort/Convert.java b/dbPort/src/org/compiere/dbPort/Convert.java index 84734dc1a6..967b123214 100644 --- a/dbPort/src/org/compiere/dbPort/Convert.java +++ b/dbPort/src/org/compiere/dbPort/Convert.java @@ -16,12 +16,16 @@ *****************************************************************************/ package org.compiere.dbPort; -import java.sql.*; -import java.util.*; -import java.util.logging.*; -import java.util.regex.*; -import org.compiere.db.*; -import org.compiere.util.*; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.SQLWarning; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.compiere.util.CLogger; +import org.compiere.util.Util; /** * Convert SQL to Target DB @@ -29,47 +33,21 @@ import org.compiere.util.*; * @author Jorg Janke, Victor Perez * @version $Id: Convert.java,v 1.3 2006/07/30 00:55:04 jjanke Exp $ */ -public class Convert +public abstract class Convert { - /** - * Cosntructor - * @param type Database.DB_ - */ - public Convert (String type) - { - if (Database.DB_ORACLE.equals(type)) - m_isOracle = true; - else if (Database.DB_DERBY.equals(type)) - m_map = ConvertMap.getDerbyMap(); - else if (Database.DB_DB2.equals(type)) - m_map = ConvertMap.getDB2Map(); - // begin vpj-cd e-evolution 07 Dic 2005 - else if (Database.DB_POSTGRESQL.equals(type)) - m_map = ConvertMap.getPostgeSQLMap(); -// else if (Database.DB_EDB.equals(type)) -// m_isOracle = true; - // end vpj-cd e-evolution 07 Dic 2005 - else - throw new UnsupportedOperationException ("Unsupported database: " + type); - } // Convert /** RegEx: insensitive and dot to include line end characters */ public static final int REGEX_FLAGS = Pattern.CASE_INSENSITIVE | Pattern.DOTALL; - /** Is Oracle */ - private boolean m_isOracle = false; - /** Used Resorce Bundle */ - private TreeMap m_map; - /** Statement used */ - private Statement m_stmt = null; + protected Statement m_stmt = null; /** Last Conversion Error */ - private String m_conversionError = null; + protected String m_conversionError = null; /** Last Execution Error */ - private Exception m_exception = null; + protected Exception m_exception = null; /** Verbose Messages */ - private boolean m_verbose = true; + protected boolean m_verbose = true; /** Logger */ private static CLogger log = CLogger.getCLogger (Convert.class); @@ -83,16 +61,6 @@ public class Convert m_verbose = verbose; } // setVerbose - /** - * Is Oracle DB - * @return true if connection is Oracle DB - */ - public boolean isOracle() - { - return m_isOracle; - } // isOracle - - /************************************************************************** * Execute SQL Statement (stops at first error). * If an error occured hadError() returns true. @@ -266,7 +234,7 @@ public class Convert * @param sqlStatements * @return array of converted statements */ - private String[] convertIt (String sqlStatements) + protected String[] convertIt (String sqlStatements) { // Need to mask / in SQL Strings ! final char MASK = '\u001F'; // Unit Separator @@ -311,1991 +279,7 @@ public class Convert * @param sqlStatement * @return converted statement */ - private ArrayList convertStatement (String sqlStatement) - { - ArrayList result = new ArrayList(); - if (m_isOracle) - { - result.add(sqlStatement); - return result; - } + protected abstract ArrayList convertStatement (String sqlStatement); - // remove comments - String statement = removeComments (sqlStatement); - // log.info("------------------------------------------------------------"); - // log.info(statement); - // log.info("------------------->"); - - String cmpString = statement.toUpperCase(); - boolean isCreate = cmpString.startsWith("CREATE "); - - // Process - if (isCreate && cmpString.indexOf(" FUNCTION ") != -1) - result.addAll(convertFunction(statement)); - - else if (isCreate && cmpString.indexOf(" TRIGGER ") != -1) - result.addAll(convertTrigger(statement)); - - else if (isCreate && cmpString.indexOf(" PROCEDURE ") != -1) - result.addAll(convertProcedure(statement)); - - else if (isCreate && cmpString.indexOf(" VIEW ") != -1) - result.addAll(convertView(statement)); -//begin vpj-cd e-evolution 02/24/2005 PostgreSQL - else if (cmpString.indexOf("ALTER TABLE") != -1) - { - result.add(convertDDL(statement)); - } - else if (cmpString.indexOf("ROWNUM") != -1) - { - result.add(convertRowNum(convertAlias(converSimpleStatement(statement)))); - } - else if (cmpString.indexOf("DELETE ") != -1 && cmpString.indexOf("DELETE FROM") == -1) - { - - statement = convertDelete(statement); - cmpString = statement; - //System.out.println("-------------cmpString:"+cmpString); - result.add(converSimpleStatement(convertAlias(cmpString))); - } - else if (cmpString.indexOf("DELETE FROM") != -1) - { - - result.add(converSimpleStatement(convertAlias(statement))); - } - else if (cmpString.indexOf("UPDATE") != -1) - { - result.add(converSimpleStatement(convertUpdate(convertAlias(statement)))); - } - else - { - result.add(converSimpleStatement(convertAlias(statement))); - } - // else -// result.add(converSimpleStatement(statement)); - //end vpj-cd e-evolution 02/24/2005 PostgreSQL - // Simple Statement - - // - // log.info("<-------------------"); - // for (int i = 0; i < result.size(); i++) - // log.info(result.get(i)); - // log.info("------------------------------------------------------------"); - - return result; - } // convertStatement - - /** - * Convert simple SQL Statement. - * Based on ConvertMap - * - * @param sqlStatement - * @return converted Statement - */ - private String converSimpleStatement (String sqlStatement) - { - // Error Checks - if (sqlStatement.toUpperCase().indexOf("EXCEPTION WHEN") != -1) - { - String error = "Exception clause needs to be converted: " + sqlStatement; - log.info (error); - m_conversionError = error; - return sqlStatement; - } - - // Standard Statement - String retValue = sqlStatement; - Iterator iter = m_map.keySet().iterator(); - while (iter.hasNext()) - { - //begin e-evolution vpj-cd 26.09.2005 - // search reserved word ie DATE into 'DATE' and remplace for character temporal <--> - Vector retVars = new Vector(); - Pattern p = Pattern.compile("'[[\\w]*[-:,\\(\\)]*[ ]*]*'"); - Matcher m = p.matcher(retValue); - while(m.find()) { - retVars.addElement(new String(retValue.substring(m.start(),m.end())) ); - } - retVars.addElement( new String(m.replaceAll("<-->")) ); - // end e-evolution vpj-cd 26.09.2005*/ - - String regex = (String)iter.next(); - String replacement = (String)m_map.get(regex); - try - { - //begin e-evolution vpj-cd 29.09.2005 - //Pattern p = Pattern.compile(regex, REGEX_FLAGS ); - //Matcher m = p.matcher(retValue); - //retValue = m.replaceAll(replacement); - // remplace reserved work - p = Pattern.compile(regex, REGEX_FLAGS ); - m = p.matcher((String)retVars.get(retVars.size()-1)); - retValue=m.replaceAll(replacement); - - p = Pattern.compile("<-->",REGEX_FLAGS); - m = p.matcher(retValue); - for(int cont=0; cont - * /*ORACLE>*/ - * Oracle Specific Statement - * /*<ORACLE*/ - * /*POSTGRESQL> - * PostgreSQL Specicic Statements - * <POSTGRESQL*/ - * - * @param statement - * @return sql statement - */ - protected String removeComments (String statement) - { - String clean = statement.trim(); - - // Remove /*ORACLE>*/ /*.* - m = Pattern.compile("\\/\\*POSTGRESQL>").matcher(clean); - clean = m.replaceAll(""); - // Remove - * CREATE OR REPLACE FUNCTION AD_Message_Get - * (p_AD_Message IN VARCHAR, p_AD_Language IN VARCHAR) - * RETURN VARCHAR AS - * ... - * END AD_Message_Get; - * => - * CREATE FUNCTION AD_Message_Get - * (VARCHAR, VARCHAR) - * RETURNS VARCHAR AS ' - * DECLARE - * p_AD_Message ALIAS FOR $1; - * p_AD_Language ALIAS FOR $2; - * .... - * END; - * ' LANGUAGE 'plpgsql'; - * - * @param sqlStatement - * @return CREATE and DROP Function statement - */ - private ArrayList convertFunction (String sqlStatement) - { - ArrayList result = new ArrayList(); - // Convert statement - to avoid handling contents of comments - String stmt = converSimpleStatement(sqlStatement); - // Double quotes ' - stmt = Pattern.compile("'").matcher(stmt).replaceAll("''"); - // remove OR REPLACE - int orReplacePos = stmt.toUpperCase().indexOf(" OR REPLACE "); - if (orReplacePos != -1) - stmt = "CREATE" + stmt.substring(orReplacePos+11); - - // Line separators - String match = - "(\\([^\\)]*\\))" // (.) Parameter - + "|(\\bRETURN \\w+ (AS)|(IS))" // RETURN CLAUSE - + "|(;)" // Statement End - // Nice to have - for readability - + "|(\\bBEGIN\\b)" // BEGIN - + "|(\\bTHEN\\b)" - + "|(\\bELSE\\b)" - + "|(\\bELSIF\\b)"; - Matcher m = Pattern.compile(match, Pattern.CASE_INSENSITIVE).matcher(stmt); - - StringBuffer sb = new StringBuffer(); - // First group -> ( ) - // CREATE OR REPLACE FUNCTION AD_Message_Get ( p_AD_Message IN VARCHAR, p_AD_Language IN VARCHAR) - // CREATE FUNCTION AD_Message_Get (VARCHAR, VARCHAR) - m.find(); - m.appendReplacement(sb, ""); - String name = sb.substring(6).trim(); - StringBuffer signature = new StringBuffer(); - // - String group = m.group().trim(); - // log.info("Group: " + group); - StringBuffer alias = new StringBuffer(); - // Parameters - if (group.startsWith("(") && group.endsWith(")")) - { - // Default not supported - if (group.toUpperCase().indexOf(" DEFAULT ") != -1) - { - String error = "DEFAULT in Parameter not supported"; - log.info (error); - m_conversionError = error; - return result; - } - signature.append("("); - if (group.length() > 2) - { - group = group.substring(1,group.length()-1); - // Paraneters are delimited by , - String[] parameters = group.split(","); - for (int i = 0; i < parameters.length; i++) - { - if (i != 0) - signature.append(", "); - // name ALIAS FOR $1 - String p = parameters[i].trim(); - alias.append(p.substring(0,p.indexOf(" "))) - .append(" ALIAS FOR $").append(i+1).append(";\n"); - // Datatape - signature.append(p.substring(p.lastIndexOf(" ")+1)); - } - } - signature.append(")"); - sb.append(signature); - // log.info("Alias: " + alias.toString()); - // log.info("Signature: " + signature.toString()); - } - // No Parameters - else - { - String error = "Missing Parameter ()"; - log.info (error); - m_conversionError = error; - return result; - } - sb.append("\n"); - // Need to create drop statement - if (orReplacePos != -1) - { - String drop = "DROP " + name + signature.toString(); - // log.info(drop); - result.add(drop); - } - // log.info("1>" + sb.toString() + "<1"); - - // Second Group -> RETURN VARCHAR AS - // RETURNS VARCHAR AS - m.find(); - group = m.group(); - m.appendReplacement(sb, ""); - if (group.startsWith("RETURN")) - sb.append("RETURNS").append(group.substring(group.indexOf(" "))); - sb.append(" '\nDECLARE\n") - .append(alias); // add aliases here - // log.info("2>" + sb.toString() + "<2"); - - // remainder statements - while (m.find()) - { - String group2 = m.group(); - if (group2.indexOf('$') != -1) // Group character needs to be escaped - group2 = Util.replace(group2, "$", "\\$"); - m.appendReplacement(sb, group2); - sb.append("\n"); - } - m.appendTail(sb); - - // finish - sb.append("' LANGUAGE 'plpgsql';"); - // log.info(">" + sb.toString() + "<"); - result.add(sb.toString()); - // - return result; - } // convertFunction - - /** - * Convert Procedure. - *
-	 *      CREATE OR REPLACE PROCEDURE AD_Message_X
-	 *      (p_AD_Message IN VARCHAR, p_AD_Language IN VARCHAR)
-	 *      ...
-	 *      END AD_Message_X;
-	 *  =>
-	 *      CREATE FUNCTION AD_Message_X
-	 *      (VARCHAR, VARCHAR)
-	 *      RETURNS VARCHAR AS '
-	 *      DECLARE
-	 *      p_AD_Message ALIAS FOR $1;
-	 *      p_AD_Language ALIAS FOR $2;
-	 *      ....
-	 *      END;
-	 *      ' LANGUAGE 'plpgsql';
-	 *  
- * @param sqlStatement - * @return CREATE and DROP Function statement - */ - private ArrayList convertProcedure (String sqlStatement) - { - ArrayList result = new ArrayList(); - // Convert statement - to avoid handling contents of comments - String stmt = converSimpleStatement(sqlStatement); - // Double quotes ' - stmt = Pattern.compile("'").matcher(stmt).replaceAll("''"); - // remove OR REPLACE - int orReplacePos = stmt.toUpperCase().indexOf(" OR REPLACE "); - if (orReplacePos != -1) - stmt = "CREATE" + stmt.substring(orReplacePos+11); - - // Line separators - String match = - "(\\([^\\)]*\\))" // (.) Parameter - + "|(\\bRETURN \\w+ (AS)|(IS))" // RETURN CLAUSE - + "|(;)" // Statement End - // Nice to have - for readability - + "|(\\bBEGIN\\b)" // BEGIN - + "|(\\bTHEN\\b)" - + "|(\\bELSE\\b)" - + "|(\\bELSIF\\b)"; - Matcher m = Pattern.compile(match, Pattern.CASE_INSENSITIVE).matcher(stmt); - - StringBuffer sb = new StringBuffer(); - // First group -> ( ) - // CREATE OR REPLACE FUNCTION AD_Message_Get ( p_AD_Message IN VARCHAR, p_AD_Language IN VARCHAR) - // CREATE FUNCTION AD_Message_Get (VARCHAR, VARCHAR) - m.find(); - m.appendReplacement(sb, ""); - String name = sb.substring(6).trim(); - StringBuffer signature = new StringBuffer(); - // - String group = m.group().trim(); - // log.info("Group: " + group); - StringBuffer alias = new StringBuffer(); - // Parameters - if (group.startsWith("(") && group.endsWith(")")) - { - // Default not supported - if (group.toUpperCase().indexOf(" DEFAULT ") != -1) - { - String error = "DEFAULT in Parameter not supported"; - log.info (error); - m_conversionError = error; - return result; - } - signature.append("("); - if (group.length() > 2) - { - group = group.substring(1,group.length()-1); - // Paraneters are delimited by , - String[] parameters = group.split(","); - for (int i = 0; i < parameters.length; i++) - { - if (i != 0) - signature.append(", "); - // name ALIAS FOR $1 - String p = parameters[i].trim(); - alias.append(p.substring(0,p.indexOf(" "))) - .append(" ALIAS FOR $").append(i+1).append(";\n"); - // Datatape - signature.append(p.substring(p.lastIndexOf(" ")+1)); - } - } - signature.append(")"); - sb.append(signature); - // log.info("Alias: " + alias.toString()); - // log.info("Signature: " + signature.toString()); - } - // No Parameters - else - { - String error = "Missing Parameter ()"; - log.info (error); - m_conversionError = error; - return result; - } - sb.append("\n"); - // Need to create drop statement - if (orReplacePos != -1) - { - String drop = "DROP " + name + signature.toString(); - // log.info(drop); - result.add(drop); - } - // log.info("1>" + sb.toString() + "<1"); - - // Second Group -> RETURN VARCHAR AS - // RETURNS VARCHAR AS - m.find(); - group = m.group(); - m.appendReplacement(sb, ""); - if (group.startsWith("RETURN")) - sb.append("RETURNS").append(group.substring(group.indexOf(" "))); - sb.append(" '\nDECLARE\n") - .append(alias); // add aliases here - // log.info("2>" + sb.toString() + "<2"); - - // remainder statements - while (m.find()) - { - String group2 = m.group(); - if (group2.indexOf('$') != -1) // Group character needs to be escaped - group2 = Util.replace(group2, "$", "\\$"); - m.appendReplacement(sb, group2); - sb.append("\n"); - } - m.appendTail(sb); - - // finish - sb.append("' LANGUAGE 'plpgsql';"); - // log.info(">" + sb.toString() + "<"); - result.add(sb.toString()); - // - return result; - } // convertProcedure - - /** - * Convert Trigger. - *
-	 *      DROP FUNCTION emp_trgF();
-	 *      CREATE FUNCTION emp_trg () RETURNS OPAQUE AS '....
-	 *          RETURN NEW; ...
-	 *          ' LANGUAGE 'plpgsql';
-	 *      DROP TRIGGER emp_trg ON emp;
-	 *      CREATE TRIGGER emp_trg BEFORE INSERT OR UPDATE ON emp
-	 *      FOR EACH ROW EXECUTE PROCEDURE emp_trgF();
-	 *  
- * @param sqlStatement - * @return CREATE and DROP TRIGGER and associated Function statement - */ - private ArrayList convertTrigger (String sqlStatement) - { - ArrayList result = new ArrayList(); - // Convert statement - to avoid handling contents of comments - String stmt = converSimpleStatement(sqlStatement); - - // Trigger specific replacements - stmt = Pattern.compile("\\bINSERTING\\b").matcher(stmt).replaceAll("TG_OP='INSERT'"); - stmt = Pattern.compile("\\bUPDATING\\b").matcher(stmt).replaceAll("TG_OP='UPDATE'"); - stmt = Pattern.compile("\\bDELETING\\b").matcher(stmt).replaceAll("TG_OP='DELETE'"); - stmt = Pattern.compile(":new.").matcher(stmt).replaceAll("NEW."); - stmt = Pattern.compile(":old.").matcher(stmt).replaceAll("OLD."); - - // Double quotes ' - stmt = Pattern.compile("'").matcher(stmt).replaceAll("''"); - // remove OR REPLACE - int orReplacePos = stmt.toUpperCase().indexOf(" OR REPLACE "); - // trigger Name - int triggerPos = stmt.toUpperCase().indexOf(" TRIGGER ") + 9; - String triggerName = stmt.substring(triggerPos); - triggerName = triggerName.substring(0, triggerName.indexOf(" ")); - // table name - String tableName = stmt.substring(stmt.toUpperCase().indexOf(" ON ")+4); - tableName = tableName.substring(0, tableName.indexOf(" ")); - - // Function Drop - if (orReplacePos != -1) - { - String drop = "DROP FUNCTION " + triggerName + "F()"; - // log.info(drop); - result.add(drop); - } - - // Function & Trigger - int pos = stmt.indexOf("DECLARE "); - if (pos == -1) - pos = stmt.indexOf("BEGIN "); - String functionCode = stmt.substring(pos); - StringBuffer triggerCode = new StringBuffer ("CREATE TRIGGER "); - triggerCode.append(triggerName).append("\n") - .append(stmt.substring(triggerPos+triggerName.length(), pos)) - .append("\nEXECUTE PROCEDURE ").append(triggerName).append("F();"); - - // Add NEW to existing Return --> DELETE Trigger ? - functionCode = Pattern.compile("\\bRETURN;", Pattern.CASE_INSENSITIVE) - .matcher(functionCode) - .replaceAll("RETURN NEW;"); - // Add final return and change name - functionCode = Pattern.compile("\\bEND " + triggerName + ";", Pattern.CASE_INSENSITIVE) - .matcher(functionCode) - .replaceAll("\nRETURN NEW;\nEND " + triggerName + "F;"); - - // Line separators - String match = - "(\\(.*\\))" // (.) Parameter - + "|(;)" // Statement End - // Nice to have - for readability - + "|(\\bBEGIN\\b)" // BEGIN - + "|(\\bTHEN\\b)" - + "|(\\bELSE\\b)" - + "|(\\bELSIF\\b)"; - Matcher m = Pattern.compile(match, Pattern.CASE_INSENSITIVE).matcher(functionCode); - - // Function Header - StringBuffer sb = new StringBuffer("CREATE FUNCTION "); - sb.append(triggerName).append("F() RETURNS OPAQUE AS '\n"); - - // remainder statements - while (m.find()) - { - String group = m.group(); - if (group.indexOf('$') != -1) // Group character needs to be escaped - group = Util.replace(group, "$", "\\$"); - m.appendReplacement(sb, group); - sb.append("\n"); - } - m.appendTail(sb); - - // finish Function - sb.append("' LANGUAGE 'plpgsql';"); - // log.info(">" + sb.toString() + "<"); - result.add(sb.toString()); - - // Trigger Drop - if (orReplacePos != -1) - { - String drop = "DROP TRIGGER " + triggerName.toLowerCase() + " ON " + tableName; - // log.info(drop); - result.add(drop); - } - - // Trigger - // Remove Column references OF ... ON - String trigger = Pattern.compile("\\sOF.*ON\\s") - .matcher(triggerCode) - .replaceAll(" ON "); - // log.info(trigger); - result.add(trigger); - - // - return result; - } // convertTrigger - - /** - * Convert View. - * Handle CREATE OR REPLACE - * @param sqlStatement - * @return converted statement(s) - */ - private ArrayList convertView (String sqlStatement) - { - ArrayList result = new ArrayList(); - String stmt = converSimpleStatement(sqlStatement); - - // remove OR REPLACE - int orReplacePos = stmt.toUpperCase().indexOf(" OR REPLACE "); - if (orReplacePos != -1) - { - int index = stmt.indexOf(" VIEW "); - int space = stmt.indexOf(' ', index+6); - String drop = "DROP VIEW " + stmt.substring(index+6, space); - result.add(drop); - // - String create = "CREATE" + stmt.substring(index); - result.add(create); - } - else // simple statement - result.add(stmt); - return result; - } // convertView - - - /************************************************************************** - * Converts Decode, Outer Join and Sequence. - *
-	 *      DECODE (a, 1, 'one', 2, 'two', 'none')
-	 *       => CASE WHEN a = 1 THEN 'one' WHEN a = 2 THEN 'two' ELSE 'none' END
-	 *
-	 *      AD_Error_Seq.nextval
-	 *       => nextval('AD_Error_Seq')
-	 *
-	 *      RAISE_APPLICATION_ERROR (-20100, 'Table Sequence not found')
-	 *       => RAISE EXCEPTION 'Table Sequence not found'
-	 *
-	 *  
- * @param sqlStatement - * @return converted statement - */ - private String convertComplexStatement(String sqlStatement) - { - String retValue = sqlStatement; - StringBuffer sb = null; - - // Convert all decode parts - while (retValue.indexOf("DECODE") != -1) - retValue = convertDecode(retValue); - - /** - * Sequence Handling -------------------------------------------------- - * AD_Error_Seq.nextval - * => nextval('AD_Error_Seq') - */ - Matcher m = Pattern.compile("\\w+\\.(nextval)|(curval)", Pattern.CASE_INSENSITIVE) - .matcher(retValue); - sb = new StringBuffer(); - while (m.find()) - { - String group = m.group(); - // System.out.print("-> " + group); - int pos = group.indexOf("."); - String seqName = group.substring(0,pos); - String funcName = group.substring(pos+1); - group = funcName + "('" + seqName + "')"; - // log.info(" => " + group); - if (group.indexOf('$') != -1) // Group character needs to be escaped - group = Util.replace(group, "$", "\\$"); - m.appendReplacement(sb, group); - } - m.appendTail(sb); - retValue = sb.toString(); - - /** - * RAISE -------------------------------------------------------------- - * RAISE_APPLICATION_ERROR (-20100, 'Table Sequence not found') - * => RAISE EXCEPTION 'Table Sequence not found' - */ - m = Pattern.compile("RAISE_APPLICATION_ERROR\\s*\\(.+'\\)", Pattern.CASE_INSENSITIVE) - .matcher(retValue); - sb = new StringBuffer(); - while (m.find()) - { - String group = m.group(); - System.out.print("-> " + group); - String result = "RAISE EXCEPTION " + group.substring(group.indexOf('\''), group.lastIndexOf('\'')+1); - log.info(" => " + result); - - if (result.indexOf('$') != -1) // Group character needs to be escaped - result = Util.replace(result, "$", "\\$"); - m.appendReplacement(sb, result); - } - m.appendTail(sb); - retValue = sb.toString(); - - // Truncate Handling ------------------------------------------------- - //begin vpj-cd e-evolution 16/07/2005 - //while (retValue.indexOf("TRUNC") != -1) - if(retValue.indexOf("TRUNC(((TRUNC(") != -1 && DB.isPostgreSQL()) - retValue = Util.replace(retValue,"TRUNC(((TRUNC(","(((TRUNC("); - //end vpj-cd e-evolution 16/07/2005 - - while (retValue.indexOf("TRUNC") != -1) - retValue = convertTrunc (retValue); - - // Outer Join Handling ----------------------------------------------- - int index = retValue.indexOf("SELECT "); - if (index != -1 && retValue.indexOf("(+)", index) != -1) - retValue = convertOuterJoin(retValue); - - return retValue; - } // convertComplexStatement - - - /************************************************************************** - * Converts Decode. - *
-	 *      DECODE (a, 1, 'one', 2, 'two', 'none')
-	 *       => CASE WHEN a = 1 THEN 'one' WHEN a = 2 THEN 'two' ELSE 'none' END
-	 *  
- * @param sqlStatement - * @return converted statement - */ - private String convertDecode(String sqlStatement) - { - // log.info("DECODE<== " + sqlStatement); - String statement = sqlStatement; - StringBuffer sb = new StringBuffer("CASE"); - - int index = statement.indexOf("DECODE"); - String firstPart = statement.substring(0,index); - - // find the opening ( - index = statement.indexOf('(', index); - statement = statement.substring(index+1); - - // find the expression "a" - find first , ignoring () - index = Util.findIndexOf (statement, ','); - String expression = statement.substring(0, index).trim(); - // log.info("Expression=" + expression); - - // Pairs "1, 'one'," - statement = statement.substring(index+1); - index = Util.findIndexOf (statement, ','); - while (index != -1) - { - String first = statement.substring(0, index); - char cc = statement.charAt(index); - statement = statement.substring(index+1); - // log.info("First=" + first + ", Char=" + cc); - // - boolean error = false; - if (cc == ',') - { - index = Util.findIndexOf (statement, ',',')'); - if (index == -1) - error = true; - else - { - String second = statement.substring(0, index); - sb.append(" WHEN ").append(expression).append("=").append(first.trim()) - .append(" THEN ").append(second.trim()); - // log.info(">>" + sb.toString()); - statement = statement.substring(index+1); - index = Util.findIndexOf (statement, ',',')'); - } - } - else if (cc == ')') - { - sb.append(" ELSE ").append(first.trim()).append(" END"); - // log.info(">>" + sb.toString()); - index = -1; - } - else - error = true; - if (error) - { - log.log(Level.SEVERE, "SQL=(" + sqlStatement - + ")\n====Result=(" + sb.toString() - + ")\n====Statement=(" + statement - + ")\n====First=(" + first - + ")\n====Index=" + index); - m_conversionError = "Decode conversion error"; - } - } - sb.append(statement); - sb.insert(0, firstPart); - // log.info("DECODE==> " + sb.toString()); - return sb.toString(); - } // convertDecode - - - /************************************************************************** - * Convert Outer Join. - * Converting joins can ve very complex when multiple tables/keys are involved. - * The main scenarios supported are two tables with multiple key columns - * and multiple tables with single key columns. - *
-	 *      SELECT a.Col1, b.Col2 FROM tableA a, tableB b WHERE a.ID=b.ID(+)
-	 *      => SELECT a.Col1, b.Col2 FROM tableA a LEFT OUTER JOIN tableB b ON (a.ID=b.ID)
-	 *
-	 *      SELECT a.Col1, b.Col2 FROM tableA a, tableB b WHERE a.ID(+)=b.ID
-	 *      => SELECT a.Col1, b.Col2 FROM tableA a RIGHT OUTER JOIN tableB b ON (a.ID=b.ID)
-	 *  Assumptions:
-	 *  - No outer joins in sub queries (ignores sub-queries)
-	 *  - OR condition ignored (not sure what to do, should not happen)
-	 *  Limitations:
-	 *  - Parameters for outer joins must be first - as sequence of parameters changes
-	 *  
- * @param sqlStatement - * @return converted statement - */ - private String convertOuterJoin (String sqlStatement) - { - boolean trace = false; - // - int fromIndex = Util.findIndexOf (sqlStatement.toUpperCase(), " FROM "); - int whereIndex = Util.findIndexOf(sqlStatement.toUpperCase(), " WHERE "); - //begin vpj-cd e-evolution 03/14/2005 PostgreSQL - //int endWhereIndex = Util.findIndexOf(sqlStatement.toUpperCase(), " GRPUP BY "); - int endWhereIndex = Util.findIndexOf(sqlStatement.toUpperCase(), " GROUP BY "); - //end vpj-cd e-evolution 03/14/2005 PostgreSQL - if (endWhereIndex == -1) - endWhereIndex = Util.findIndexOf(sqlStatement.toUpperCase(), " ORDER BY "); - if (endWhereIndex == -1) - endWhereIndex = sqlStatement.length(); - // - if (trace) - { - log.info("OuterJoin<== " + sqlStatement); - // log.info("From=" + fromIndex + ", Where=" + whereIndex + ", End=" + endWhereIndex + ", Length=" + sqlStatement.length()); - } - // - String selectPart = sqlStatement.substring(0, fromIndex); - String fromPart = sqlStatement.substring(fromIndex, whereIndex); - String wherePart = sqlStatement.substring(whereIndex, endWhereIndex); - String rest = sqlStatement.substring(endWhereIndex); - - // find/remove all (+) from WHERE clase ------------------------------ - String newWherePart = wherePart; - ArrayList joins = new ArrayList(); - int pos = newWherePart.indexOf("(+)"); - while (pos != -1) - { - // find starting point - int start = newWherePart.lastIndexOf(" AND ", pos); - int startOffset = 5; - if (start == -1) - { - start = newWherePart.lastIndexOf(" OR ", pos); - startOffset = 4; - } - if (start == -1) - { - start = newWherePart.lastIndexOf("WHERE ", pos); - startOffset = 6; - } - if (start == -1) - { - String error = "Start point not found in clause " + wherePart; - log.severe(error); - m_conversionError = error; - return sqlStatement; - } - // find end point - int end = newWherePart.indexOf(" AND ", pos); - if (end == -1) - end = newWherePart.indexOf(" OR ", pos); - if (end == -1) - end = newWherePart.length(); - // log.info("<= " + newWherePart + " - Start=" + start + "+" + startOffset + ", End=" + end); - - // extract condition - String condition = newWherePart.substring(start+startOffset, end); - joins.add(condition); - if (trace) - log.info("->" + condition); - // new WHERE clause - newWherePart = newWherePart.substring(0, start) + newWherePart.substring(end); - // log.info("=> " + newWherePart); - // - pos = newWherePart.indexOf("(+)"); - } - // correct beginning - newWherePart = newWherePart.trim(); - if (newWherePart.startsWith("AND ")) - newWherePart = "WHERE" + newWherePart.substring(3); - else if (newWherePart.startsWith("OR ")) - newWherePart = "WHERE" + newWherePart.substring(2); - if (trace) - log.info("=> " + newWherePart); - - // Correct FROM clause ----------------------------------------------- - // Disassemble FROM - String[] fromParts = fromPart.trim().substring(4).split(","); - HashMap fromAlias = new HashMap(); // tables to be processed - HashMap fromLookup = new HashMap(); // used tabled - for (int i = 0; i < fromParts.length; i++) - { - String entry = fromParts[i].trim(); - String alias = entry; // no alias - String table = entry; - int aPos = entry.lastIndexOf(' '); - if (aPos != -1) - { - alias = entry.substring(aPos+1); - table = entry.substring(0, entry.indexOf(' ')); // may have AS - } - fromAlias.put(alias, table); - fromLookup.put(alias, table); - if (trace) - log.info("Alias=" + alias + ", Table=" + table); - } - - /** Single column - SELECT t.TableName, w.Name FROM AD_Table t, AD_Window w - WHERE t.AD_Window_ID=w.AD_Window_ID(+) - -- 275 rows - SELECT t.TableName, w.Name FROM AD_Table t - LEFT OUTER JOIN AD_Window w ON (t.AD_Window_ID=w.AD_Window_ID) - - SELECT t.TableName, w.Name FROM AD_Table t, AD_Window w - WHERE t.AD_Window_ID(+)=w.AD_Window_ID - -- 239 rows - SELECT t.TableName, w.Name FROM AD_Table t - RIGHT OUTER JOIN AD_Window w ON (t.AD_Window_ID=w.AD_Window_ID) - - ** Multiple columns - SELECT tn.Node_ID,tn.Parent_ID,tn.SeqNo,tb.IsActive - FROM AD_TreeNode tn, AD_TreeBar tb - WHERE tn.AD_Tree_ID=tb.AD_Tree_ID(+) AND tn.Node_ID=tb.Node_ID(+) - AND tn.AD_Tree_ID=10 - -- 235 rows - SELECT tn.Node_ID,tn.Parent_ID,tn.SeqNo,tb.IsActive - FROM AD_TreeNode tn LEFT OUTER JOIN AD_TreeBar tb - ON (tn.Node_ID=tb.Node_ID AND tn.AD_Tree_ID=tb.AD_Tree_ID AND tb.AD_User_ID=0) - WHERE tn.AD_Tree_ID=10 - - SELECT tn.Node_ID,tn.Parent_ID,tn.SeqNo,tb.IsActive - FROM AD_TreeNode tn, AD_TreeBar tb - WHERE tn.AD_Tree_ID=tb.AD_Tree_ID(+) AND tn.Node_ID=tb.Node_ID(+) - AND tn.AD_Tree_ID=10 AND tb.AD_User_ID(+)=0 - -- 214 rows - SELECT tn.Node_ID,tn.Parent_ID,tn.SeqNo,tb.IsActive - FROM AD_TreeNode tn LEFT OUTER JOIN AD_TreeBar tb - ON (tn.Node_ID=tb.Node_ID AND tn.AD_Tree_ID=tb.AD_Tree_ID AND tb.AD_User_ID=0) - WHERE tn.AD_Tree_ID=10 - - */ - StringBuffer newFrom = new StringBuffer (); - for (int i = 0; i < joins.size(); i++) - { - Join first = new Join ((String)joins.get(i)); - first.setMainTable((String)fromLookup.get(first.getMainAlias())); - fromAlias.remove(first.getMainAlias()); // remove from list - first.setJoinTable((String)fromLookup.get(first.getJoinAlias())); - fromAlias.remove(first.getJoinAlias()); // remove from list - if (trace) - log.info("-First: " + first); - // - if (newFrom.length() == 0) - newFrom.append(" FROM "); - else - newFrom.append(", "); - newFrom.append(first.getMainTable()).append(" ").append(first.getMainAlias()) - .append(first.isLeft() ? " LEFT" : " RIGHT").append(" OUTER JOIN ") - .append(first.getJoinTable()).append(" ").append(first.getJoinAlias()) - .append(" ON (").append(first.getCondition()); - // keep it open - check for other key comparisons - for (int j = i+1; j < joins.size(); j++) - { - Join second = new Join ((String)joins.get(j)); - second.setMainTable((String)fromLookup.get(second.getMainAlias())); - second.setJoinTable((String)fromLookup.get(second.getJoinAlias())); - if ((first.getMainTable().equals(second.getMainTable()) - && first.getJoinTable().equals(second.getJoinTable())) - || second.isConditionOf(first) ) - { - if (trace) - log.info("-Second/key: " + second); - newFrom.append(" AND ").append(second.getCondition()); - joins.remove(j); // remove from join list - fromAlias.remove(first.getJoinAlias()); // remove from table list - //---- - for (int k = i+1; k < joins.size(); k++) - { - Join third = new Join ((String)joins.get(k)); - third.setMainTable((String)fromLookup.get(third.getMainAlias())); - third.setJoinTable((String)fromLookup.get(third.getJoinAlias())); - if (third.isConditionOf(second)) - { - if (trace) - log.info("-Third/key: " + third); - newFrom.append(" AND ").append(third.getCondition()); - joins.remove(k); // remove from join list - fromAlias.remove(third.getJoinAlias()); // remove from table list - } - else if (trace) - log.info("-Third/key-skip: " + third); - } - } - else if (trace) - log.info("-Second/key-skip: " + second); - } - newFrom.append(")"); // close ON - // check dependency on first table - for (int j = i+1; j < joins.size(); j++) - { - Join second = new Join ((String)joins.get(j)); - second.setMainTable((String)fromLookup.get(second.getMainAlias())); - second.setJoinTable((String)fromLookup.get(second.getJoinAlias())); - if (first.getMainTable().equals(second.getMainTable())) - { - if (trace) - log.info("-Second/dep: " + second); - // FROM (AD_Field f LEFT OUTER JOIN AD_Column c ON (f.AD_Column_ID = c.AD_Column_ID)) - // LEFT OUTER JOIN AD_FieldGroup fg ON (f.AD_FieldGroup_ID = fg.AD_FieldGroup_ID), - newFrom.insert(6, '('); // _FROM ... - newFrom.append(')'); // add parantesis on previous relation - // - newFrom.append(second.isLeft() ? " LEFT" : " RIGHT").append(" OUTER JOIN ") - .append(second.getJoinTable()).append(" ").append(second.getJoinAlias()) - .append(" ON (").append(second.getCondition()); - joins.remove(j); // remove from join list - fromAlias.remove(second.getJoinAlias()); // remove from table list - // additional join colums would come here - newFrom.append(")"); // close ON - //---- - for (int k = i+1; k < joins.size(); k++) - { - Join third = new Join ((String)joins.get(k)); - third.setMainTable((String)fromLookup.get(third.getMainAlias())); - third.setJoinTable((String)fromLookup.get(third.getJoinAlias())); - if (second.getJoinTable().equals(third.getMainTable())) - { - if (trace) - log.info("-Third-dep: " + third); - // FROM ((C_BPartner p LEFT OUTER JOIN AD_User c ON (p.C_BPartner_ID=c.C_BPartner_ID)) - // LEFT OUTER JOIN C_BPartner_Location l ON (p.C_BPartner_ID=l.C_BPartner_ID)) - // LEFT OUTER JOIN C_Location a ON (l.C_Location_ID=a.C_Location_ID) - newFrom.insert(6, '('); // _FROM ... - newFrom.append(')'); // add parantesis on previous relation - // - newFrom.append(third.isLeft() ? " LEFT" : " RIGHT").append(" OUTER JOIN ") - .append(third.getJoinTable()).append(" ").append(third.getJoinAlias()) - .append(" ON (").append(third.getCondition()); - joins.remove(k); // remove from join list - fromAlias.remove(third.getJoinAlias()); // remove from table list - // additional join colums would come here - newFrom.append(")"); // close ON - } - else if (trace) - log.info("-Third-skip: " + third); - } - } - else if (trace) - log.info("-Second/dep-skip: " + second); - } // dependency on first table - } - // remaining Tables - Iterator it = fromAlias.keySet().iterator(); - while (it.hasNext()) - { - Object alias = it.next(); - Object table = fromAlias.get(alias); - newFrom.append(", ").append(table); - if (!table.equals(alias)) - newFrom.append(" ").append(alias); - } - if (trace) - log.info(newFrom.toString()); - // - StringBuffer retValue = new StringBuffer (sqlStatement.length()+20); - retValue.append(selectPart) - .append(newFrom).append(" ") - .append(newWherePart).append(rest); - // - if (trace) - log.info("OuterJoin==> " + retValue.toString()); - return retValue.toString(); - } // convertOuterJoin - - /** - * Convert RowNum. - *
-	 *      SELECT Col1 FROM tableA WHERE ROWNUM=1
-	 *      => SELECT Col1 FROM tableA LIMIT 1
-	 *  Assumptions/Limitations:
-	 *  - RowNum not used in SELECT part
-	 *  
- * @param sqlStatement - * @return converted statement - */ - private String convertRowNum (String sqlStatement) - { - log.info("RowNum<== " + sqlStatement); - if(DB.isPostgreSQL()) - { - log.info("RowNum<== " + sqlStatement); - String retValue = null; - - //find into (select from where) - - int s_end = 0; - int s_start = -1; - String select = sqlStatement; - String convert = ""; - while(true) - { - s_end = 0; - s_start = select.indexOf( "(SELECT"); - - if (s_start == -1) - break; - - convert = convert + select.substring(0,s_start); - //System.out.println("convert:" + convert); - int open = -1; - for (int i = s_start; i < select.length(); i++) - { - char c = select.charAt(i); - if (c == '(') - open ++; - - if (c == ')') - open --; - - if (open == -1) - { - s_end = i + 1; - break; - } - } - - String subselect = select.substring(s_start,s_end); - //System.out.println("subselect:" +subselect); - //System.out.println("select:" +select); - - if (subselect.indexOf("AND ROWNUM=1") > 1) - { - subselect = subselect.substring(0 , subselect.length() -1 ) + " LIMIT 1 )"; - //System.out.println("subselect:" +subselect); - convert = convert + Util.replace(subselect,"AND ROWNUM=1",""); - //System.out.println("convert:" + convert); - } - else if (subselect.indexOf(" WHERE ROWNUM=1 AND") > 1) - { - subselect = subselect.substring(0 , subselect.length() -1 ) + " LIMIT 1 )"; - //System.out.println("subselect:" +subselect); - convert = convert + Util.replace(subselect," WHERE ROWNUM=1 AND"," WHERE "); - //System.out.println("convert:" + convert); - } - else - { - convert = convert + subselect; - } - - - select = select.substring(s_end); - retValue = select; - - } - //System.out.println("convert:" + convert); - //System.out.println("select:" + select); - if (retValue==null) - retValue = sqlStatement; - - if (retValue.indexOf("AND ROWNUM=1") > 1) - { - int rownum = retValue.indexOf("AND ROWNUM=1"); - if(retValue.substring(0,rownum).contains("WHERE")) - { - retValue = Util.replace(retValue,"AND ROWNUM=1"," LIMIT 1"); - return convert + retValue ; - } - else - { - retValue = Util.replace(retValue,"AND ROWNUM=1",""); - return convert + retValue + " LIMIT 1"; - } - - } - else if (retValue.indexOf("AND ROWNUM= 1") > 1) - { - int rownum = retValue.indexOf("AND ROWNUM= 1"); - if(retValue.substring(0,rownum).contains("WHERE")) - { - - retValue = Util.replace(retValue,"AND ROWNUM= 1"," LIMIT 1"); - return convert + retValue ; - } - else - { - retValue = Util.replace(retValue,"AND ROWNUM= 1",""); - return convert + retValue + " LIMIT 1"; - } - } - else if (retValue.indexOf("AND ROWNUM = 1") > 1) - { - int rownum = retValue.indexOf("AND ROWNUM = 1"); - if(retValue.substring(0,rownum).contains("WHERE")) - { - - retValue = Util.replace(sqlStatement,"AND ROWNUM = 1"," LIMIT 1"); - return convert + retValue; - } - else - { - retValue = Util.replace(sqlStatement,"AND ROWNUM = 1",""); - return convert + retValue + " LIMIT 1"; - } - } - else if (retValue.indexOf("AND ROWNUM =1") > 1) - { - int rownum = retValue.indexOf("AND ROWNUM =1"); - if(retValue.substring(0,rownum).contains("WHERE")) - { - - retValue = Util.replace(retValue,"AND ROWNUM =1"," LIMIT 1"); - return convert + retValue ; - } - else - { - retValue = Util.replace(retValue,"AND ROWNUM =1",""); - return convert + retValue + " LIMIT 1"; - } - } - else if (retValue.indexOf("ROWNUM=1") > 1) - { - int rownum = retValue.indexOf("ROWNUM=1"); - System.out.println("retValue"+ retValue); - if(retValue.substring(0,rownum).contains("WHERE")) - { - retValue = Util.replace(retValue,"ROWNUM=1 "," LIMIT 1"); - return convert + retValue ; - } - else - { - retValue = Util.replace(retValue,"ROWNUM=1",""); - return convert + retValue + " LIMIT 1"; - } - } - // log.info("RowNum==> " + retValue); - return convert + retValue; - } - else - return sqlStatement; - // - // log.info("RowNum==> " + retValue); - // return retValue; - // end e-evolution PostgreSQL - } // convertRowNum - - /** - * Convert TRUNC. - * Assumed that it is used for date only! - * @param sqlStatement - * @return converted statement - */ - private String convertTrunc (String sqlStatement) - { - //return Util.replace(sqlStatement, "TRUNC(", "convert(date,"); - /** - *
-	 *      TRUNC(myDate)
-	 *      => DATE_Trunc('day',myDate)
-	 *
-	 *      TRUNC(myDate,'oracleFormat')
-	 *      => DATE_Trunc('pgFormat',myDate)
-	 *
-	 *      Oracle          =>  PostgreSQL  (list not complete!)
-	 *          Q               quarter
-	 *          MM              month
-	 *          DD              day
-	 *      Spacial handling of DAY,DY  (Starting dat of the week)
-	 *      => DATE_Trunc('day',($1-DATE_PART('dow',$1)));
-	 *  
- //begin vpj-cd e-evolution 07/12/2005 - */ - if(DB.isPostgreSQL()) - { - //index = sqlStatement.indexOf("TRUNC("); - //beforeStatement = sqlStatement.substring(0, index); - //beforeStatement = sqlStatement.replaceFirst("TRUNC" , "DATE_Trunc"); - int find = -1; - find = sqlStatement.indexOf(",'Q'"); - if (find != -1) - - - - - { - - sqlStatement = sqlStatement.replaceFirst("TRUNC\\(" , "DATE_Trunc('quarter',"); - sqlStatement = sqlStatement.replaceFirst(",'Q'", ""); - return sqlStatement; - } - find = sqlStatement.indexOf(",'Y'"); - if (find != -1) - { - sqlStatement = sqlStatement.replaceFirst("TRUNC\\(" , "DATE_Trunc('year',"); - sqlStatement = sqlStatement.replaceFirst(",'Y'", ""); - return sqlStatement; - } - find = sqlStatement.indexOf(",'MM'"); - if (find != -1) - - - - - - - - { - sqlStatement = sqlStatement.replaceFirst("TRUNC\\(" , "DATE_Trunc('month',"); - sqlStatement = sqlStatement.replaceFirst(",'MM'", ""); - return sqlStatement; - } - find = sqlStatement.indexOf(",'DD'"); - if (find != -1) - { - sqlStatement = sqlStatement.replaceFirst("TRUNC\\(" , "DATE_Trunc('day',"); - sqlStatement = sqlStatement.replaceFirst(",'DD'", ""); - return sqlStatement; - } - find = sqlStatement.indexOf(",'DY'"); - if (find != -1) - { - sqlStatement = sqlStatement.replaceFirst("TRUNC\\(" , "DATE_Trunc('day',"); - sqlStatement = sqlStatement.replaceFirst(",'DY'", ""); - return sqlStatement; - } - if (find == -1) - { - sqlStatement = sqlStatement.replaceFirst("TRUNC\\(" , "DATE_Trunc('day',"); - //sqlStatement = sqlStatement.replaceFirst(",'DY'", ""); - return sqlStatement; - } - System.out.println("SQL=" + sqlStatement); - return sqlStatement; - - } - else - return sqlStatement; - - - - - //end vpj-cd e-evolution 09/02/2005 PostgreSQL - } // convertTrunc -// begin vpj-cd e-evolution 02/24/2005 PostgreSQL - /************************************************************************** - * Converts Decode. - *
-	 *      UPDATE C_Order i SET 
-	 *       => UPDATE C_Order SET
-	 *  
- * @param sqlStatement - * @return converted statement - */ - /* - private String convertUpdate(String sqlStatement) - { - - if(DB.isPostgreSQL()) - { - String sqlUpdate = sqlStatement; - int index = 0; - int begintable = 0; - int begin = 0; - int end = 0; - String alias = null; - - - end = 0; - begin = Util.findIndexOf(sqlUpdate,"SET ("); - if(begin != -1) - { - - if (sqlUpdate.toUpperCase().indexOf("UPDATE ") == 0) - { - index = sqlUpdate.toUpperCase().indexOf("UPDATE "); - //String firstPart = statement.substring(0,index); - - begintable = sqlUpdate.indexOf(' ', 6 ); - - // begin the opening ' ' begin Alias - begin = sqlUpdate.indexOf(' ', 7 ); - //statement = statement.substring(begin); - - // end Alias - - end = sqlUpdate.toUpperCase().indexOf(" SET", 0 ); //statement.indexOf("SET", 0 ) - } - - String table = sqlUpdate.substring(begintable,begin).trim(); - - String select = ""; - - begin = Util.findIndexOf(sqlUpdate," SET ("); - end = sqlUpdate.indexOf(")=("); - if (end != -1) - select = sqlUpdate.substring(end + 2); - else - { - end = sqlUpdate.indexOf(") = ("); - if (end != -1) - select = sqlUpdate.substring(end + 4); - else - { - end = sqlUpdate.indexOf(")= ("); - if (end !=-1) - select = sqlUpdate.substring(end + 3); - else - { - end = sqlUpdate.indexOf(") =("); - if (end !=-1) - select = sqlUpdate.substring(end + 3); - } - - } - } - - - int where_begin = -1; - String rest = ""; - //String select = sqlUpdate.substring(end + 2); - //System.out.println("SELECT ->" + select); - //int s_end = select.indexOf( ")"); - int s_end = 0; - int s_start = select.indexOf( "("); - String where = null; - int open = -1; - for (int i = s_start; i < select.length(); i++) - { - char c = select.charAt(i); - if (c == '(') - open ++; - - if (c == ')') - open --; - - if (open == -1) - { - s_end = i + 1; - break; - } - } - - where = select.substring(s_end); - where = where.substring(where.indexOf(" WHERE ") + 7 ); - - String s = select.substring(s_start,s_end); - - //System.out.println("s:"+ s); - - //System.out.println("s_end"+ s_end); - //System.out.println("rest: " + rest); - String from =s.substring( s.toUpperCase().indexOf(" FROM ") + 6); - //System.out.println("from"+ from); - String tablejoin = from.substring(0,from.toUpperCase().indexOf(" ")); - //System.out.println("tablejoin"+ tablejoin); - String tablealias = from.substring(0,from.toUpperCase().indexOf(" WHERE ")); - //System.out.println("tablealias"+ tablealias); - //System.out.println("------------------select.toUpperCase().substring(s_end)" +select.substring(select.substring(s_end).toUpperCase().indexOf(" WHERE "))); - //String swhere = select.substring(s_end); - //s_end = - //System.out.println(); - ///System.out.println("string end" + swhere); - //String s_where = ""; - //System.out.println("string end" + select.substring(select.substring(s_end).toUpperCase().indexOf(" WHERE ")); - String s_where = s.substring(s.toUpperCase().indexOf(" WHERE ") + 7,s.length() -1); - //System.out.println("Where before join" + where); - //System.out.println("s_where:" + s_where); - //System.out.println("where:" + where); - //System.out.println("FROM:" + from); - //System.out.println("Table Join:" + tablejoin); - //System.out.println("Table Alias:" + tablejoin); - - - String Update = sqlUpdate.substring(0,begin); - Update = Update + " SET "; - int f_begin = begin + 6 ; - int f_beginjoin = 0 ; - //System.out.println(" sqlUpdate"+ sqlUpdate); - String fields = sqlUpdate.substring(f_begin, end); - //System.out.println("------fields" + fields); - int beginfrom = select.toUpperCase().indexOf(" FROM "); - String fieldsjoin = select.substring(select.toUpperCase().indexOf("(SELECT ")+8,beginfrom); - //System.out.println("fields"+fields); - //System.out.println("fields Joint"+fieldsjoin); - int f = fields.length(); - int fj = fieldsjoin.length(); - String field = null; - String fieldjoin = null; - //System.out.println("Update:"+ Update); - - while (f > 0) - { - f = Util.findIndexOf(fields,',');//fields.indexOf(','); - //System.out.println("comman" + c); - if (f < 0) - { - //System.out.print("fields:"+fields); - field = fields; - fieldjoin = fieldsjoin; - if (fieldjoin.indexOf(".") < 0) - { - fieldjoin = tablejoin + "." +fieldjoin; - } - - - //System.out.println("f_begin:" + f_begin + " end :" + end + " field:" + field); - //Update = Update + field.trim() + "=" + tablejoin + "." + field.trim() + rest + " FROM " + tablealias + " WHERE " + where ; // + select.substring(s_end + 8); - Update = Update + field.trim() + "=" + fieldjoin.trim() + rest + " FROM " + tablealias + " WHERE " + s_where ; // + select.substring(s_end + 8); - //System.out.println("Last Update" + Update); - // set alias all field before where - - if (where!=null) - where = " AND " + where; - - else - where = ""; - - - String sqlkey = "AND,OR,FROM,WHERE,JOIN,BY,GROUP,IN,INTO,SELECT,NOT,SET,UPDATE,DELETE,HAVING,IS,NULL,EXISTS" ; - int o = -1; - StringTokenizer st = new StringTokenizer(where); - String result = ""; - String word = ""; - while (true) // make sure there is stuff to get - { - word = st. nextToken(); - //System.out.println("Word:" + word); - if(sqlkey.indexOf(word) == -1) - { - - - for (int i = 0; i < word.length(); i++) - { - char c = word.charAt(i); - if (c == '(') - o ++; - if (c == ')') - o --; - } - if (o == -1 && (!word.contains(")") | !word.contains("("))) - { - - result = result + " " + table + "."+ word; - //System.out.println("Cadena :" + word); - } - else - { - result = result + " " + word; - } - - - } - else - result = result + " " + word; - if(!st.hasMoreElements()) - break; - } - - Update = Update + result ; - //System.out.println("UPDATE"+ Update); - } - else - { - - field = fields.substring(0 ,f); - //System.out.println("Field:"+ field); - //System.out.println("------fieldsjoin"+ fieldsjoin); - fj = Util.findIndexOf(fieldsjoin,',');//fj = fieldsjoin.indexOf(','); - - fieldjoin = fieldsjoin.substring(0 ,fj); - //System.out.println("fields"+ fields); - //System.out.println("fieldsjoin"+ fieldsjoin); - if (fieldjoin.indexOf(".") < 0 != fieldjoin.equals("SysDate")) - { - fieldjoin = tablejoin + "." +fieldjoin; - } - //System.out.println( " -----> fj" + fj + "fieldjoin " + fieldjoin); - //Update = Update + field + "=" + tablejoin + "." + field.trim() + ","; - Update = Update + field.trim() + "=" + fieldjoin.trim()+ ","; - f_beginjoin = fj; - fieldsjoin= fieldsjoin.substring(f_beginjoin + 1); - //System.out.println("fieldsjoin" + fieldsjoin); - f_beginjoin =fj; - } - - f_begin = f; - fields = fields.substring(f_begin + 1); - - //System.out.println("Update" + Update); - } - - sqlUpdate = Update ; - - } - //System.out.println("Convert Update:"+sqlUpdate); - return sqlUpdate; - } - else - return sqlStatement; - - } // convertDecode - **/ - - // Two regex's used in convertUpdate -private static final Pattern aliasPatternInUpdate = -Pattern.compile("(?i)\\s*UPDATE\\s+(\\S+)\\s+(\\S+)\\s+SET\\s.*"); -private static final Pattern tupleUpdatePatternInUpdate = -Pattern.compile("(?i)\\s*UPDATE\\s+(\\S+)\\s+SET\\s+\\(([^\\)]+)\\)\\s*=\\s*\\(\\s*SELECT\\s(.*?)\\s(FROM\\s.*)"); - -private String convertUpdate(String sqlStatement) -{ - String convertedSqlStatement = sqlStatement; - - // 1st step: Remove and replace alias - Matcher aliasMatcher = aliasPatternInUpdate.matcher(sqlStatement); - if (aliasMatcher.matches()) { - // We found an UPDATE-statement with an alias => convert - - // Extract table name and alias - String tableName = aliasMatcher.group(1); - String alias = aliasMatcher.group(2); - - // remove the alias before SET - convertedSqlStatement = sqlStatement.replaceFirst("\\s+" + alias + "\\s+", " "); - - // replace the alias with the real table name in all other places - convertedSqlStatement = convertedSqlStatement.replaceAll("\\b" + alias + "\\.", tableName + "."); - } // End of: Remove and replace alias - - // 2nd: step: Convert tuple updates with inner SELECT - Matcher tupleUpdateMatcher = tupleUpdatePatternInUpdate.matcher(convertedSqlStatement); - if (tupleUpdateMatcher.matches()) { - // We found an UPDATE-statement with a "tuple-update" - // of the form UPDATE a SET (b, c) = (SELECT x, y FROM z WHERE) WHERE ... - - // Extract some important parts of the statement - String tableName = tupleUpdateMatcher.group(1); - String columnsTupleString = tupleUpdateMatcher.group(2); - String innerSelectColumnsTupleString = tupleUpdateMatcher.group(3); - String innerSelectFromUntilEnd = tupleUpdateMatcher.group(4); - - // columnsArray contains the columns to be updated - String[] columnsArray = columnsTupleString.split("\\s*,\\s*"); - // innerSelectColumnsArray contains the corresponding "columns" - // of the inner SELECT statement - String[] innerSelectColumnsArray = new String[columnsArray.length]; - - // split the inner SELECT columns by ',' but not within parenthesis - char[] innerSelectColumnsCharArray = innerSelectColumnsTupleString.toCharArray(); - int openParenthesisCount = 0; - int columnCount = 0; - StringBuffer currentInnerSelectColumnSb = new StringBuffer(); - int innerSelectColumnsCharArrayLength = innerSelectColumnsCharArray.length; - int innerSelectColumnsCharArrayLastIndex= innerSelectColumnsCharArrayLength - 1; - for (int i=0; i 0) { - // If inside of a parenthesis pair simply append the character - currentInnerSelectColumnSb.append(innerSelectColumnsCharArray[i]); - } - else - { - // We're not inside of a parentheses pair - if (innerSelectColumnsCharArray[i] == ',') - { - // A ',' denotes the end of the inner SELECT column - innerSelectColumnsArray[columnCount] = currentInnerSelectColumnSb.toString().trim(); - // Start the next "column" of the inner SELECT - currentInnerSelectColumnSb = new StringBuffer(); - columnCount++; - } - else if (i == innerSelectColumnsCharArrayLastIndex) - { - // End of String reached => append last character and add last column - currentInnerSelectColumnSb.append(innerSelectColumnsCharArray[i]); - innerSelectColumnsArray[columnCount] = currentInnerSelectColumnSb.toString().trim(); - } - else - { - // We did not find a ',' and we did not reach the end of the string - // => this is a "normal" character; append - currentInnerSelectColumnSb.append(innerSelectColumnsCharArray[i]); - } - } - // Take care of opening and closing parenthesis - // to adjust the open parenthesis count - if (innerSelectColumnsCharArray[i] == '(') { - openParenthesisCount++; - } else if (innerSelectColumnsCharArray[i] == ')') { - openParenthesisCount--; - } - } - - // Split the FROM-until-end-part into - // a) the inner SELECT FROM-WHERE-Clause (innerSelectFromWhereClauseSb) - // b) the WHERE-clause of the UPDATE-statement (updateWhereClauseSb) - char[] innerSelectFromUntilEndCharArray = innerSelectFromUntilEnd.toCharArray(); - openParenthesisCount = 0; - int innerSelectFromUntilEndCharArrayLength = innerSelectFromUntilEndCharArray.length; - StringBuffer innerSelectFromWhereClauseSb = new StringBuffer(); - StringBuffer updateWhereClauseSb = new StringBuffer(); - boolean endOfinnerSelectFromWhereClauseReached = false; - for (int i=0; i increment the open parenthesis count - openParenthesisCount++; - innerSelectFromWhereClauseSb.append('('); - } else { - // Append all other characters - innerSelectFromWhereClauseSb.append(innerSelectFromUntilEndCharArray[i]); - - } - } - } - - // assemble the new UPDATE statement - int columnsArrayLength = columnsArray.length; - int columnsArrayLastIndex = columnsArrayLength - 1; - StringBuffer newUpdateStatementSb = new StringBuffer("UPDATE "); - newUpdateStatementSb.append(tableName); - newUpdateStatementSb.append(" SET "); - // We now have: "UPDATE tablename SET " - // Now iterate over all columns to be updated and add - // the SELECT clause - for (int i=0; i - * DELETE C_Order i WHERE - * => DELETE FROM C_Order WHERE - * - * @param sqlStatement - * @return converted statement - */ - private String convertDelete(String sqlStatement) - { - - if (DB.isPostgreSQL()) - { - int index = sqlStatement.toUpperCase().indexOf("DELETE "); - if(index < 7) - { - return "DELETE FROM " + sqlStatement.substring(index+7); - - } - } - - return sqlStatement; - } // convertDelete - - - //begin vpj-cd e-evolution 08/02/2005 - /************************************************************************** - * convertAlias. - * @param sqlStatement - * @return converted statementf - */ - private String convertAlias(String sqlStatement) - { - if(DB.isPostgreSQL()) - { - String statement = sqlStatement; - int index = 0; - int begintable = 0; - int begin = 0; - int end = 0; - String alias = null; - - if (statement.toUpperCase().indexOf("DELETE FROM ") == 0) - { - index = statement.toUpperCase().indexOf("DELETE FROM "); - begintable = statement.indexOf(' ', 11 ); - // begin the opening ' ' begin Alias - begin = statement.indexOf(' ', 12 ); - // end Alias - end = statement.toUpperCase().indexOf("WHERE", 0 ); - } - else if (statement.toUpperCase().indexOf("UPDATE ") == 0) - { - index = statement.toUpperCase().indexOf("UPDATE "); - //String firstPart = statement.substring(0,index); - - begintable = statement.indexOf(' ', 6 ); - - // begin the opening ' ' begin Alias - begin = statement.indexOf(' ', 7 ); - //statement = statement.substring(begin); - - // end Alias - - end = statement.toUpperCase().indexOf(" SET" , 0 ); //statement.indexOf("SET", 0 ); - - } - else - { - return statement; - } - - String sqlAlias = statement ; - if (end > begin) - { - alias = statement.substring(begin,end).trim()+"."; - String table = statement.substring(begintable,begin).trim(); - //System.out.println("Table" + table); - statement = statement.substring(0,begin) + " " + statement.substring(end); - if (!alias.equals(".")) - { - sqlAlias = Util.replace(statement, " " +alias , " " + table + "."); - sqlAlias = Util.replace(sqlAlias, "=" +alias , "=" + table + "."); - sqlAlias = Util.replace(sqlAlias, "(" +alias , "(" + table + "."); - } - } - - //sqlDelete = Util.replace(sqlDelete, "DELETE " , "DELETE FROM "); - //System.out.println("Convertion Alias:" + statement.substring(0, begin ) + " " + statement.substring(end)); - //System.out.println("Statement Convert:" + statement); - //System.out.println("begin Alias:" + begin + " end Alias:" + end ); - //System.out.println("Alias:" + statement.substring(begin, end).trim()); - //System.out.println("SQL Alias:"+sqlAlias); - return sqlAlias; - } - else - return sqlStatement; - } // convertDelete - // end vpj-cd e-evolution 02/24/2005 PostgreSQL - - // begin vpj-cd 08/02/2005 - //ALTER TABLE AD_FieldGroup MODIFY IsTab CHAR(1) DEFAULT N; - //ALTER TABLE AD_FieldGroup ALTER COLUMN IsTab TYPE CHAR(1); ALTER TABLE AD_FieldGroup ALTER COLUMN SET DEFAULT 'N'; - private String convertDDL(String sqlStatement) - { - if(DB.isPostgreSQL()) - { - if (sqlStatement.toUpperCase().indexOf("ALTER TABLE ") == 0) - { - String action = null; - int begin_col = -1; - if (sqlStatement.toUpperCase().indexOf(" MODIFY ") > 0) - { - action = " ALTER "; - begin_col = sqlStatement.toUpperCase().indexOf(" MODIFY ") + action.length() ; - } - else if (sqlStatement.toUpperCase().indexOf(" ADD ") > 0) - { - action = " ADD "; - begin_col = sqlStatement.toUpperCase().indexOf(" ADD ") + action.length() ; - } - - //System.out.println( "MODIFY :" + sqlStatement.toUpperCase().indexOf(" MODIFY ")); - //System.out.println( "ADD :" + sqlStatement.toUpperCase().indexOf(" ADD ")); - //System.out.println( "begincolumn:" + sqlStatement + "begincolumn:" + begin_col ); - - if (begin_col < 0) - return sqlStatement; - - - int end_col = 0; - int begin_default = -1; - int begin_type = -1; - - String column = null; - String type = null; - String defaultvalue = null; - String DDL = null; - - if (begin_col != -1) - { - column = sqlStatement.substring(begin_col); - end_col = begin_col + column.indexOf(" "); - column = sqlStatement.substring(begin_col , end_col); - //System.out.println(" column:" + column + " begincolumn:" + begin_col + "en column:" + end_col ); - //System.out.println(" type " + sqlStatement.substring(end_col + 1)); - type = sqlStatement.substring(end_col + 1) + " "; - //System.out.println(" type 1 :" + type); - type = type.substring(0 , type.indexOf(" ")); - //System.out.println(" type:" + type); - if (action.equals(" ADD ")) - DDL = sqlStatement.substring(0, begin_col - action.length()) + action + "COLUMN " + column + " " + type + "; "; - else if (action.equals(" ALTER ")) - DDL = sqlStatement.substring(0, begin_col - action.length()) + action + "COLUMN " + column + " TYPE " + type + "; "; - - if (sqlStatement.toUpperCase().indexOf(" DEFAULT ") != -1) - { - begin_default = sqlStatement.toUpperCase().indexOf(" DEFAULT ") + 9; - defaultvalue = sqlStatement.substring(begin_default); - String rest = defaultvalue.substring( defaultvalue.indexOf(" ")); - defaultvalue = defaultvalue.substring(0 , defaultvalue.indexOf(" ")); - - DDL += sqlStatement.substring(0 , begin_col - action.length()) + " ALTER COLUMN " + column + " SET DEFAULT '" + defaultvalue + "'; "; - if (rest != null && rest.indexOf(" NOT NULL ") == 0) - DDL += sqlStatement.substring(0 , begin_col ) + " ALTER COLUMN " + column + " SET " + rest + ";"; - //return DDL; - } - - //System.out.println("DDL" + DDL); - return DDL; - } - } - } - - return sqlStatement; - } - - private String convertIgnore(String sqlStatement) - { - String vars[]= new String[20]; - int cont=1; - Pattern p = Pattern.compile("'[[\\w]*[,]*[ ]*]*'",Pattern.CASE_INSENSITIVE); - Matcher m = p.matcher(sqlStatement); - while(m.find()) { - vars[cont++]=sqlStatement.substring(m.start(),m.end()); - } - vars[0]=m.replaceAll("<-->"); - String retVar[]=new String[cont]; - for(int i=0; i"); - m = p.matcher(retVar[0]); - cont=1; - for(cont=1; cont s_derby = new TreeMap(); - /** Tree Map for PostgreSQL */ - private static TreeMap s_db2 = new TreeMap(); - // begin e-evolution PostgreSQL - /** Tree Map for PostgreSQL */ - private static TreeMap s_pg = new TreeMap(); - // end e-evolution PostgreSQL - /** - * Derby Init - */ - static private void initDerby() - { // C:\Sources\db-derby-10.1.2.1-bin\docs\html\ref\index.html - - // Oracle Pattern Replacement - - // Data Types - s_derby.put("\\bNUMBER\\b", "DECIMAL(31,6)"); //jz: changed from decimal to decimal(31,6) - s_derby.put("\\bDATE\\b", "TIMESTAMP"); - s_derby.put("\\bVARCHAR2\\b", "VARCHAR"); - s_derby.put("\\bNVARCHAR2\\b", "VARCHAR"); - s_derby.put("\\bNCHAR\\b", "CHAR"); - - // Storage - s_derby.put("\\bCACHE\\b", ""); - s_derby.put("\\bUSING INDEX\\b", ""); - s_derby.put("\\bTABLESPACE\\s\\w+\\b", ""); - s_derby.put("\\bSTORAGE\\([\\w\\s]+\\)", ""); - // - s_derby.put("\\bBITMAP INDEX\\b", "INDEX"); - - // Select - s_derby.put("\\bFOR UPDATE\\b", ""); - s_derby.put("\\bTRUNC\\(", "convert(date,"); - - // Functions - s_derby.put("\\bSysDate\\b", "CURRENT_TIMESTAMP"); - s_derby.put("\\bSYSDATE\\b", "CURRENT_TIMESTAMP"); - s_derby.put("\\bNVL\\b", "NULLIF"); - s_derby.put("\\bCOALESCE\\b", "NULLIF"); - - s_derby.put("\\bTO_DATE\\b", "TO_TIMESTAMP"); - // - // s_derby.put("\\bDBMS_OUTPUT.PUT_LINE\\b", "RAISE NOTICE"); - - // Temporary - s_derby.put("\\bGLOBAL TEMPORARY\\b", "TEMPORARY"); - s_derby.put("\\bON COMMIT DELETE ROWS\\b", ""); - s_derby.put("\\bON COMMIT PRESERVE ROWS\\b", ""); - - - // DROP TABLE x CASCADE CONSTRAINTS - // s_derby.put("\\bCASCADE CONSTRAINTS\\b", ""); - - // Select - s_derby.put("\\sFROM\\s+DUAL\\b", ""); - - // Statements - s_derby.put("\\bELSIF\\b", "ELSE IF"); - - // Sequences - s_derby.put("\\bSTART WITH\\b", "START"); - s_derby.put("\\bINCREMENT BY\\b", "INCREMENT"); - - } // initDerby - - /** - * DB/2 Init - */ - static private void initDB2() - { - // Oracle Pattern Replacement - - // Data Types - s_db2.put("\\bNUMBER\\b", "NUMERIC"); - s_db2.put("\\bDATE\\b", "TIMESTAMP"); - s_db2.put("\\bVARCHAR2\\b", "VARCHAR"); - s_db2.put("\\bNVARCHAR2\\b", "VARCHAR"); - s_db2.put("\\bNCHAR\\b", "CHAR"); - s_db2.put("\\bBLOB\\b", "OID"); // BLOB not directly supported - s_db2.put("\\bCLOB\\b", "TEXT"); // CLOB not directly supported - - // Storage - s_db2.put("\\bCACHE\\b", ""); - s_db2.put("\\bUSING INDEX\\b", ""); - s_db2.put("\\bTABLESPACE\\s\\w+\\b", ""); - s_db2.put("\\bSTORAGE\\([\\w\\s]+\\)", ""); - // - s_db2.put("\\bBITMAP INDEX\\b", "INDEX"); - - // Functions - s_db2.put("\\bSYSDATE\\b", "CURRENT_TIMESTAMP"); // alternative: NOW() - s_db2.put("\\bNVL\\b", "COALESCE"); - s_db2.put("\\bTO_DATE\\b", "TO_TIMESTAMP"); - // - s_db2.put("\\bDBMS_OUTPUT.PUT_LINE\\b", "RAISE NOTICE"); - - // Temporary - s_db2.put("\\bGLOBAL TEMPORARY\\b", "TEMPORARY"); - s_db2.put("\\bON COMMIT DELETE ROWS\\b", ""); - s_db2.put("\\bON COMMIT PRESERVE ROWS\\b", ""); - - - // DROP TABLE x CASCADE CONSTRAINTS - s_db2.put("\\bCASCADE CONSTRAINTS\\b", ""); - - // Select - s_db2.put("\\sFROM\\s+DUAL\\b", ""); - - // Statements - s_db2.put("\\bELSIF\\b", "ELSE IF"); - - // Sequences - s_db2.put("\\bSTART WITH\\b", "START"); - s_db2.put("\\bINCREMENT BY\\b", "INCREMENT"); - - } // initPostgreSQL - - /** - * PostgreSQL Init - */ - static private void initPostgreSQL() - { - // Oracle Pattern Replacement - - // Data Types - s_pg.put("\\bNUMBER\\b", "NUMERIC"); - s_pg.put("\\bDATE\\b", "TIMESTAMP"); - s_pg.put("\\bVARCHAR2\\b", "VARCHAR"); - s_pg.put("\\bNVARCHAR2\\b", "VARCHAR"); - s_pg.put("\\bNCHAR\\b", "CHAR"); - //begin vpj-cd e-evolution 03/11/2005 PostgreSQL - s_pg.put("\\bBLOB\\b", "BYTEA"); // BLOB not directly supported - s_pg.put("\\bCLOB\\b", "BYTEA"); // CLOB not directly supported - s_pg.put("\\bLIMIT\\b","\"limit\""); - s_pg.put("\\bACTION\\b","\"action\""); - //s_pg.put("\\bBLOB\\b", "OID"); // BLOB not directly supported - //s_pg.put("\\bCLOB\\b", "OID"); // CLOB not directly supported - //end vpj-cd e-evolution 03/11/2005 PostgreSQL - - // Storage - s_pg.put("\\bCACHE\\b", ""); - s_pg.put("\\bUSING INDEX\\b", ""); - s_pg.put("\\bTABLESPACE\\s\\w+\\b", ""); - s_pg.put("\\bSTORAGE\\([\\w\\s]+\\)", ""); - // - s_pg.put("\\bBITMAP INDEX\\b", "INDEX"); - - // Functions - s_pg.put("\\bSYSDATE\\b", "CURRENT_TIMESTAMP"); // alternative: NOW() - //Bug fix, Gunther Hoppe 08.07.2005 e-evolution - //Begin ---------------------------------------------------------------------------------------- - s_pg.put("\\bSysDate\\b", "CURRENT_TIMESTAMP"); - s_pg.put("SysDate", "CURRENT_TIMESTAMP"); - //end ---------------------------------------------------------------------------------------- - //begin vpj-cd e-evolution 03/11/2005 PostgreSQL - s_pg.put("\\bDUMP\\b", "MD5"); - s_pg.put("END CASE", "END"); - s_pg.put("\\bgetDate()\\b", "CURRENT_TIMESTAMP"); // alternative: NOW() - //end vpj-cd e-evolution 03/11/2005 PostgreSQL - s_pg.put("\\bNVL\\b", "COALESCE"); - s_pg.put("\\bTO_DATE\\b", "TO_TIMESTAMP"); - // - s_pg.put("\\bDBMS_OUTPUT.PUT_LINE\\b", "RAISE NOTICE"); - - // Temporary - s_pg.put("\\bGLOBAL TEMPORARY\\b", "TEMPORARY"); - s_pg.put("\\bON COMMIT DELETE ROWS\\b", ""); - s_pg.put("\\bON COMMIT PRESERVE ROWS\\b", ""); - - //DDL - - // begin vpj-cd e-evolution 08/02/2005 PostgreSQL - //s_pg.put("\\bMODIFY\\b","ALTER COLUMN"); - //s_pg.put("\\bDEFAULT\\b","SET DEFAULT"); - // end vpj-cd e-evolution 08/02/2005 PostgreSQL - - // DROP TABLE x CASCADE CONSTRAINTS - s_pg.put("\\bCASCADE CONSTRAINTS\\b", ""); - - // Select - s_pg.put("\\sFROM\\s+DUAL\\b", ""); - - // Statements - s_pg.put("\\bELSIF\\b", "ELSE IF"); - // begin vpj-cd e-evolution 03/11/2005 PostgreSQL - s_pg.put("\\bREC \\b", "AS REC "); - //s_pg.put("\\bAND\\sROWNUM=\\b", "LIMIT "); - // end vpj-cd e-evolution 03/11/2005 PostgreSQL - - // Sequences - s_pg.put("\\bSTART WITH\\b", "START"); - s_pg.put("\\bINCREMENT BY\\b", "INCREMENT"); - - } // initPostgreSQL - -} // ConvertMap diff --git a/dbPort/src/org/compiere/dbPort/ConvertMap_DB2.java b/dbPort/src/org/compiere/dbPort/ConvertMap_DB2.java new file mode 100644 index 0000000000..0b266c8c89 --- /dev/null +++ b/dbPort/src/org/compiere/dbPort/ConvertMap_DB2.java @@ -0,0 +1,106 @@ +/****************************************************************************** + * Product: Adempiere ERP & CRM Smart Business Solution * + * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. This program is distributed in the hope * + * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.dbPort; + +import java.util.*; + +/** + * Database Syntax Conversion Map. + * + * + * @author Jorg Janke & Victor Perez + * @version $Id: ConvertMap.java,v 1.6 2006/09/22 23:35:19 jjanke Exp $ + */ +public class ConvertMap_DB2 +{ + + /** + * Return Map for DB/2 + * @return TreeMap with pattern as key and the replacement as value + */ + public static TreeMap getConvertMap() + { + if (s_db2.size() == 0) + initConvertMap(); + return s_db2; + } // getDB2Map +// begin e-evolution PostgreSQL + +// end e-evolution PostgreSQL + + + /** Tree Map for PostgreSQL */ + private static TreeMap s_db2 = new TreeMap(); + // begin e-evolution PostgreSQL + /** Tree Map for PostgreSQL */ + + // end e-evolution PostgreSQL + + + /** + * DB/2 Init + */ + static private void initConvertMap() + { + // Oracle Pattern Replacement + + // Data Types + s_db2.put("\\bNUMBER\\b", "NUMERIC"); + s_db2.put("\\bDATE\\b", "TIMESTAMP"); + s_db2.put("\\bVARCHAR2\\b", "VARCHAR"); + s_db2.put("\\bNVARCHAR2\\b", "VARCHAR"); + s_db2.put("\\bNCHAR\\b", "CHAR"); + s_db2.put("\\bBLOB\\b", "OID"); // BLOB not directly supported + s_db2.put("\\bCLOB\\b", "TEXT"); // CLOB not directly supported + + // Storage + s_db2.put("\\bCACHE\\b", ""); + s_db2.put("\\bUSING INDEX\\b", ""); + s_db2.put("\\bTABLESPACE\\s\\w+\\b", ""); + s_db2.put("\\bSTORAGE\\([\\w\\s]+\\)", ""); + // + s_db2.put("\\bBITMAP INDEX\\b", "INDEX"); + + // Functions + s_db2.put("\\bSYSDATE\\b", "CURRENT_TIMESTAMP"); // alternative: NOW() + s_db2.put("\\bNVL\\b", "COALESCE"); + s_db2.put("\\bTO_DATE\\b", "TO_TIMESTAMP"); + // + s_db2.put("\\bDBMS_OUTPUT.PUT_LINE\\b", "RAISE NOTICE"); + + // Temporary + s_db2.put("\\bGLOBAL TEMPORARY\\b", "TEMPORARY"); + s_db2.put("\\bON COMMIT DELETE ROWS\\b", ""); + s_db2.put("\\bON COMMIT PRESERVE ROWS\\b", ""); + + + // DROP TABLE x CASCADE CONSTRAINTS + s_db2.put("\\bCASCADE CONSTRAINTS\\b", ""); + + // Select + s_db2.put("\\sFROM\\s+DUAL\\b", ""); + + // Statements + s_db2.put("\\bELSIF\\b", "ELSE IF"); + + // Sequences + s_db2.put("\\bSTART WITH\\b", "START"); + s_db2.put("\\bINCREMENT BY\\b", "INCREMENT"); + + } // initPostgreSQL + +} // ConvertMap diff --git a/dbPort/src/org/compiere/dbPort/ConvertMap_Derby.java b/dbPort/src/org/compiere/dbPort/ConvertMap_Derby.java new file mode 100644 index 0000000000..2a2f7b2292 --- /dev/null +++ b/dbPort/src/org/compiere/dbPort/ConvertMap_Derby.java @@ -0,0 +1,78 @@ +package org.compiere.dbPort; + +import java.util.TreeMap; + +public final class ConvertMap_Derby { + /** Tree Map for Derby */ + private static TreeMap s_derby = new TreeMap(); + + /** + * Return Map for Derby + * @return TreeMap with pattern as key and the replacement as value + */ + public static TreeMap getConvertMap() + { + if (s_derby.size() == 0) + initConvertMap(); + return s_derby; + } // getDerbyMap + + + /** + * Derby Init + */ + static private void initConvertMap() + { // C:\Sources\db-derby-10.1.2.1-bin\docs\html\ref\index.html + + // Oracle Pattern Replacement + + // Data Types + s_derby.put("\\bNUMBER\\b", "DECIMAL(31,6)"); //jz: changed from decimal to decimal(31,6) + s_derby.put("\\bDATE\\b", "TIMESTAMP"); + s_derby.put("\\bVARCHAR2\\b", "VARCHAR"); + s_derby.put("\\bNVARCHAR2\\b", "VARCHAR"); + s_derby.put("\\bNCHAR\\b", "CHAR"); + + // Storage + s_derby.put("\\bCACHE\\b", ""); + s_derby.put("\\bUSING INDEX\\b", ""); + s_derby.put("\\bTABLESPACE\\s\\w+\\b", ""); + s_derby.put("\\bSTORAGE\\([\\w\\s]+\\)", ""); + // + s_derby.put("\\bBITMAP INDEX\\b", "INDEX"); + + // Select + s_derby.put("\\bFOR UPDATE\\b", ""); + s_derby.put("\\bTRUNC\\(", "convert(date,"); + + // Functions + s_derby.put("\\bSysDate\\b", "CURRENT_TIMESTAMP"); + s_derby.put("\\bSYSDATE\\b", "CURRENT_TIMESTAMP"); + s_derby.put("\\bNVL\\b", "NULLIF"); + s_derby.put("\\bCOALESCE\\b", "NULLIF"); + + s_derby.put("\\bTO_DATE\\b", "TO_TIMESTAMP"); + // + // s_derby.put("\\bDBMS_OUTPUT.PUT_LINE\\b", "RAISE NOTICE"); + + // Temporary + s_derby.put("\\bGLOBAL TEMPORARY\\b", "TEMPORARY"); + s_derby.put("\\bON COMMIT DELETE ROWS\\b", ""); + s_derby.put("\\bON COMMIT PRESERVE ROWS\\b", ""); + + + // DROP TABLE x CASCADE CONSTRAINTS + // s_derby.put("\\bCASCADE CONSTRAINTS\\b", ""); + + // Select + s_derby.put("\\sFROM\\s+DUAL\\b", ""); + + // Statements + s_derby.put("\\bELSIF\\b", "ELSE IF"); + + // Sequences + s_derby.put("\\bSTART WITH\\b", "START"); + s_derby.put("\\bINCREMENT BY\\b", "INCREMENT"); + + } // initDerby +} diff --git a/dbPort/src/org/compiere/dbPort/ConvertMap_PostgreSQL.java b/dbPort/src/org/compiere/dbPort/ConvertMap_PostgreSQL.java new file mode 100644 index 0000000000..eddb233608 --- /dev/null +++ b/dbPort/src/org/compiere/dbPort/ConvertMap_PostgreSQL.java @@ -0,0 +1,97 @@ +package org.compiere.dbPort; + +import java.util.TreeMap; + +public final class ConvertMap_PostgreSQL { + private static TreeMap s_pg = new TreeMap(); + + /** + * Return Map for PostgreSQL + * @return TreeMap with pattern as key and the replacement as value + */ + public static TreeMap getConvertMap() + { + if (s_pg.size() == 0) + initConvertMap(); + return s_pg; + } // getConvertMap + + /** + * PostgreSQL Init + */ + static private void initConvertMap() + { + // Oracle Pattern Replacement + + // Data Types + s_pg.put("\\bNUMBER\\b", "NUMERIC"); + s_pg.put("\\bDATE\\b", "TIMESTAMP"); + s_pg.put("\\bVARCHAR2\\b", "VARCHAR"); + s_pg.put("\\bNVARCHAR2\\b", "VARCHAR"); + s_pg.put("\\bNCHAR\\b", "CHAR"); + //begin vpj-cd e-evolution 03/11/2005 PostgreSQL + s_pg.put("\\bBLOB\\b", "BYTEA"); // BLOB not directly supported + s_pg.put("\\bCLOB\\b", "BYTEA"); // CLOB not directly supported + s_pg.put("\\bLIMIT\\b","\"limit\""); + s_pg.put("\\bACTION\\b","\"action\""); + //s_pg.put("\\bBLOB\\b", "OID"); // BLOB not directly supported + //s_pg.put("\\bCLOB\\b", "OID"); // CLOB not directly supported + //end vpj-cd e-evolution 03/11/2005 PostgreSQL + + // Storage + s_pg.put("\\bCACHE\\b", ""); + s_pg.put("\\bUSING INDEX\\b", ""); + s_pg.put("\\bTABLESPACE\\s\\w+\\b", ""); + s_pg.put("\\bSTORAGE\\([\\w\\s]+\\)", ""); + // + s_pg.put("\\bBITMAP INDEX\\b", "INDEX"); + + // Functions + s_pg.put("\\bSYSDATE\\b", "CURRENT_TIMESTAMP"); // alternative: NOW() + //Bug fix, Gunther Hoppe 08.07.2005 e-evolution + //Begin ---------------------------------------------------------------------------------------- + s_pg.put("\\bSysDate\\b", "CURRENT_TIMESTAMP"); + s_pg.put("SysDate", "CURRENT_TIMESTAMP"); + //end ---------------------------------------------------------------------------------------- + //begin vpj-cd e-evolution 03/11/2005 PostgreSQL + s_pg.put("\\bDUMP\\b", "MD5"); + s_pg.put("END CASE", "END"); + s_pg.put("\\bgetDate()\\b", "CURRENT_TIMESTAMP"); // alternative: NOW() + //end vpj-cd e-evolution 03/11/2005 PostgreSQL + s_pg.put("\\bNVL\\b", "COALESCE"); + s_pg.put("\\bTO_DATE\\b", "TO_TIMESTAMP"); + // + s_pg.put("\\bDBMS_OUTPUT.PUT_LINE\\b", "RAISE NOTICE"); + + // Temporary + s_pg.put("\\bGLOBAL TEMPORARY\\b", "TEMPORARY"); + s_pg.put("\\bON COMMIT DELETE ROWS\\b", ""); + s_pg.put("\\bON COMMIT PRESERVE ROWS\\b", ""); + + //DDL + + // begin vpj-cd e-evolution 08/02/2005 PostgreSQL + //s_pg.put("\\bMODIFY\\b","ALTER COLUMN"); + //s_pg.put("\\bDEFAULT\\b","SET DEFAULT"); + // end vpj-cd e-evolution 08/02/2005 PostgreSQL + + // DROP TABLE x CASCADE CONSTRAINTS + s_pg.put("\\bCASCADE CONSTRAINTS\\b", ""); + + // Select + s_pg.put("\\sFROM\\s+DUAL\\b", ""); + + // Statements + s_pg.put("\\bELSIF\\b", "ELSE IF"); + // begin vpj-cd e-evolution 03/11/2005 PostgreSQL + s_pg.put("\\bREC \\b", "AS REC "); + //s_pg.put("\\bAND\\sROWNUM=\\b", "LIMIT "); + // end vpj-cd e-evolution 03/11/2005 PostgreSQL + + // Sequences + s_pg.put("\\bSTART WITH\\b", "START"); + s_pg.put("\\bINCREMENT BY\\b", "INCREMENT"); + + } // initPostgreSQL + +} diff --git a/dbPort/src/org/compiere/dbPort/Convert_Oracle.java b/dbPort/src/org/compiere/dbPort/Convert_Oracle.java new file mode 100644 index 0000000000..25ddc18bd4 --- /dev/null +++ b/dbPort/src/org/compiere/dbPort/Convert_Oracle.java @@ -0,0 +1,21 @@ +package org.compiere.dbPort; + +import java.util.ArrayList; + +public class Convert_Oracle extends Convert { + + public Convert_Oracle() {} + + @Override + protected ArrayList convertStatement(String sqlStatement) { + ArrayList result = new ArrayList(); + result.add(sqlStatement); + return result; + } + + @Override + public boolean isOracle() { + return true; + } + +} diff --git a/dbPort/src/org/compiere/dbPort/Convert_PostgreSQL.java b/dbPort/src/org/compiere/dbPort/Convert_PostgreSQL.java new file mode 100644 index 0000000000..cfeaa8eeab --- /dev/null +++ b/dbPort/src/org/compiere/dbPort/Convert_PostgreSQL.java @@ -0,0 +1,1672 @@ +/****************************************************************************** + * Product: Adempiere ERP & CRM Smart Business Solution * + * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. This program is distributed in the hope * + * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.dbPort; + +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.SQLWarning; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.TreeMap; +import java.util.Vector; +import java.util.logging.Level; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.compiere.util.CLogger; +import org.compiere.util.DB; +import org.compiere.util.Util; + +/** + * Convert SQL to Target DB + * + * @author Jorg Janke, Victor Perez + * @version $Id: Convert.java,v 1.3 2006/07/30 00:55:04 jjanke Exp $ + */ +public class Convert_PostgreSQL extends Convert_SQL92 +{ + /** + * Cosntructor + * @param type Database.DB_ + */ + public Convert_PostgreSQL() + { + m_map = ConvertMap_PostgreSQL.getConvertMap(); + } // Convert + + /** RegEx: insensitive and dot to include line end characters */ + public static final int REGEX_FLAGS = Pattern.CASE_INSENSITIVE | Pattern.DOTALL; + + private TreeMap m_map; + + /** Logger */ + private static CLogger log = CLogger.getCLogger (Convert_PostgreSQL.class); + + /** + * Is Oracle DB + * @return true if connection is Oracle DB + */ + public boolean isOracle() + { + return false; + } // isOracle + + /** + * Convert single Statements. + * - remove comments + * - process FUNCTION/TRIGGER/PROCEDURE + * - process Statement + * @param sqlStatement + * @return converted statement + */ + protected ArrayList convertStatement (String sqlStatement) + { + ArrayList result = new ArrayList(); + + // remove comments + String statement = removeComments (sqlStatement); + // log.info("------------------------------------------------------------"); + // log.info(statement); + // log.info("------------------->"); + + String cmpString = statement.toUpperCase(); + boolean isCreate = cmpString.startsWith("CREATE "); + + // Process + if (isCreate && cmpString.indexOf(" FUNCTION ") != -1) + result.addAll(convertFunction(statement)); + + else if (isCreate && cmpString.indexOf(" TRIGGER ") != -1) + result.addAll(convertTrigger(statement)); + + else if (isCreate && cmpString.indexOf(" PROCEDURE ") != -1) + result.addAll(convertProcedure(statement)); + + else if (isCreate && cmpString.indexOf(" VIEW ") != -1) + result.addAll(convertView(statement)); +//begin vpj-cd e-evolution 02/24/2005 PostgreSQL + else if (cmpString.indexOf("ALTER TABLE") != -1) + { + result.add(convertDDL(statement)); + } + else if (cmpString.indexOf("ROWNUM") != -1) + { + result.add(convertRowNum(convertAlias(converSimpleStatement(statement)))); + } + else if (cmpString.indexOf("DELETE ") != -1 && cmpString.indexOf("DELETE FROM") == -1) + { + + statement = convertDelete(statement); + cmpString = statement; + //System.out.println("-------------cmpString:"+cmpString); + result.add(converSimpleStatement(convertAlias(cmpString))); + } + else if (cmpString.indexOf("DELETE FROM") != -1) + { + + result.add(converSimpleStatement(convertAlias(statement))); + } + else if (cmpString.indexOf("UPDATE") != -1) + { + result.add(converSimpleStatement(convertUpdate(convertAlias(statement)))); + } + else + { + result.add(converSimpleStatement(convertAlias(statement))); + } + // else +// result.add(converSimpleStatement(statement)); + //end vpj-cd e-evolution 02/24/2005 PostgreSQL + // Simple Statement + + // + // log.info("<-------------------"); + // for (int i = 0; i < result.size(); i++) + // log.info(result.get(i)); + // log.info("------------------------------------------------------------"); + + return result; + } // convertStatement + + /** + * Convert simple SQL Statement. + * Based on ConvertMap + * + * @param sqlStatement + * @return converted Statement + */ + private String converSimpleStatement (String sqlStatement) + { + // Error Checks + if (sqlStatement.toUpperCase().indexOf("EXCEPTION WHEN") != -1) + { + String error = "Exception clause needs to be converted: " + sqlStatement; + log.info (error); + m_conversionError = error; + return sqlStatement; + } + + // Standard Statement + String retValue = sqlStatement; + Iterator iter = m_map.keySet().iterator(); + while (iter.hasNext()) + { + //begin e-evolution vpj-cd 26.09.2005 + // search reserved word ie DATE into 'DATE' and remplace for character temporal <--> + Vector retVars = new Vector(); + Pattern p = Pattern.compile("'[[\\w]*[-:,\\(\\)]*[ ]*]*'"); + Matcher m = p.matcher(retValue); + while(m.find()) { + retVars.addElement(new String(retValue.substring(m.start(),m.end())) ); + } + retVars.addElement( new String(m.replaceAll("<-->")) ); + // end e-evolution vpj-cd 26.09.2005*/ + + String regex = (String)iter.next(); + String replacement = (String)m_map.get(regex); + try + { + //begin e-evolution vpj-cd 29.09.2005 + //Pattern p = Pattern.compile(regex, REGEX_FLAGS ); + //Matcher m = p.matcher(retValue); + //retValue = m.replaceAll(replacement); + // remplace reserved work + p = Pattern.compile(regex, REGEX_FLAGS ); + m = p.matcher((String)retVars.get(retVars.size()-1)); + retValue=m.replaceAll(replacement); + + p = Pattern.compile("<-->",REGEX_FLAGS); + m = p.matcher(retValue); + for(int cont=0; cont + * /*ORACLE>*/ + * Oracle Specific Statement + * /*<ORACLE*/ + * /*POSTGRESQL> + * PostgreSQL Specicic Statements + * <POSTGRESQL*/ + * + * @param statement + * @return sql statement + */ + protected String removeComments (String statement) + { + String clean = statement.trim(); + + // Remove /*ORACLE>*/ /*.* + m = Pattern.compile("\\/\\*POSTGRESQL>").matcher(clean); + clean = m.replaceAll(""); + // Remove + * CREATE OR REPLACE FUNCTION AD_Message_Get + * (p_AD_Message IN VARCHAR, p_AD_Language IN VARCHAR) + * RETURN VARCHAR AS + * ... + * END AD_Message_Get; + * => + * CREATE FUNCTION AD_Message_Get + * (VARCHAR, VARCHAR) + * RETURNS VARCHAR AS ' + * DECLARE + * p_AD_Message ALIAS FOR $1; + * p_AD_Language ALIAS FOR $2; + * .... + * END; + * ' LANGUAGE 'plpgsql'; + * + * @param sqlStatement + * @return CREATE and DROP Function statement + */ + private ArrayList convertFunction (String sqlStatement) + { + ArrayList result = new ArrayList(); + // Convert statement - to avoid handling contents of comments + String stmt = converSimpleStatement(sqlStatement); + // Double quotes ' + stmt = Pattern.compile("'").matcher(stmt).replaceAll("''"); + // remove OR REPLACE + int orReplacePos = stmt.toUpperCase().indexOf(" OR REPLACE "); + if (orReplacePos != -1) + stmt = "CREATE" + stmt.substring(orReplacePos+11); + + // Line separators + String match = + "(\\([^\\)]*\\))" // (.) Parameter + + "|(\\bRETURN \\w+ (AS)|(IS))" // RETURN CLAUSE + + "|(;)" // Statement End + // Nice to have - for readability + + "|(\\bBEGIN\\b)" // BEGIN + + "|(\\bTHEN\\b)" + + "|(\\bELSE\\b)" + + "|(\\bELSIF\\b)"; + Matcher m = Pattern.compile(match, Pattern.CASE_INSENSITIVE).matcher(stmt); + + StringBuffer sb = new StringBuffer(); + // First group -> ( ) + // CREATE OR REPLACE FUNCTION AD_Message_Get ( p_AD_Message IN VARCHAR, p_AD_Language IN VARCHAR) + // CREATE FUNCTION AD_Message_Get (VARCHAR, VARCHAR) + m.find(); + m.appendReplacement(sb, ""); + String name = sb.substring(6).trim(); + StringBuffer signature = new StringBuffer(); + // + String group = m.group().trim(); + // log.info("Group: " + group); + StringBuffer alias = new StringBuffer(); + // Parameters + if (group.startsWith("(") && group.endsWith(")")) + { + // Default not supported + if (group.toUpperCase().indexOf(" DEFAULT ") != -1) + { + String error = "DEFAULT in Parameter not supported"; + log.info (error); + m_conversionError = error; + return result; + } + signature.append("("); + if (group.length() > 2) + { + group = group.substring(1,group.length()-1); + // Paraneters are delimited by , + String[] parameters = group.split(","); + for (int i = 0; i < parameters.length; i++) + { + if (i != 0) + signature.append(", "); + // name ALIAS FOR $1 + String p = parameters[i].trim(); + alias.append(p.substring(0,p.indexOf(" "))) + .append(" ALIAS FOR $").append(i+1).append(";\n"); + // Datatape + signature.append(p.substring(p.lastIndexOf(" ")+1)); + } + } + signature.append(")"); + sb.append(signature); + // log.info("Alias: " + alias.toString()); + // log.info("Signature: " + signature.toString()); + } + // No Parameters + else + { + String error = "Missing Parameter ()"; + log.info (error); + m_conversionError = error; + return result; + } + sb.append("\n"); + // Need to create drop statement + if (orReplacePos != -1) + { + String drop = "DROP " + name + signature.toString(); + // log.info(drop); + result.add(drop); + } + // log.info("1>" + sb.toString() + "<1"); + + // Second Group -> RETURN VARCHAR AS + // RETURNS VARCHAR AS + m.find(); + group = m.group(); + m.appendReplacement(sb, ""); + if (group.startsWith("RETURN")) + sb.append("RETURNS").append(group.substring(group.indexOf(" "))); + sb.append(" '\nDECLARE\n") + .append(alias); // add aliases here + // log.info("2>" + sb.toString() + "<2"); + + // remainder statements + while (m.find()) + { + String group2 = m.group(); + if (group2.indexOf('$') != -1) // Group character needs to be escaped + group2 = Util.replace(group2, "$", "\\$"); + m.appendReplacement(sb, group2); + sb.append("\n"); + } + m.appendTail(sb); + + // finish + sb.append("' LANGUAGE 'plpgsql';"); + // log.info(">" + sb.toString() + "<"); + result.add(sb.toString()); + // + return result; + } // convertFunction + + /** + * Convert Procedure. + *
+	 *      CREATE OR REPLACE PROCEDURE AD_Message_X
+	 *      (p_AD_Message IN VARCHAR, p_AD_Language IN VARCHAR)
+	 *      ...
+	 *      END AD_Message_X;
+	 *  =>
+	 *      CREATE FUNCTION AD_Message_X
+	 *      (VARCHAR, VARCHAR)
+	 *      RETURNS VARCHAR AS '
+	 *      DECLARE
+	 *      p_AD_Message ALIAS FOR $1;
+	 *      p_AD_Language ALIAS FOR $2;
+	 *      ....
+	 *      END;
+	 *      ' LANGUAGE 'plpgsql';
+	 *  
+ * @param sqlStatement + * @return CREATE and DROP Function statement + */ + private ArrayList convertProcedure (String sqlStatement) + { + ArrayList result = new ArrayList(); + // Convert statement - to avoid handling contents of comments + String stmt = converSimpleStatement(sqlStatement); + // Double quotes ' + stmt = Pattern.compile("'").matcher(stmt).replaceAll("''"); + // remove OR REPLACE + int orReplacePos = stmt.toUpperCase().indexOf(" OR REPLACE "); + if (orReplacePos != -1) + stmt = "CREATE" + stmt.substring(orReplacePos+11); + + // Line separators + String match = + "(\\([^\\)]*\\))" // (.) Parameter + + "|(\\bRETURN \\w+ (AS)|(IS))" // RETURN CLAUSE + + "|(;)" // Statement End + // Nice to have - for readability + + "|(\\bBEGIN\\b)" // BEGIN + + "|(\\bTHEN\\b)" + + "|(\\bELSE\\b)" + + "|(\\bELSIF\\b)"; + Matcher m = Pattern.compile(match, Pattern.CASE_INSENSITIVE).matcher(stmt); + + StringBuffer sb = new StringBuffer(); + // First group -> ( ) + // CREATE OR REPLACE FUNCTION AD_Message_Get ( p_AD_Message IN VARCHAR, p_AD_Language IN VARCHAR) + // CREATE FUNCTION AD_Message_Get (VARCHAR, VARCHAR) + m.find(); + m.appendReplacement(sb, ""); + String name = sb.substring(6).trim(); + StringBuffer signature = new StringBuffer(); + // + String group = m.group().trim(); + // log.info("Group: " + group); + StringBuffer alias = new StringBuffer(); + // Parameters + if (group.startsWith("(") && group.endsWith(")")) + { + // Default not supported + if (group.toUpperCase().indexOf(" DEFAULT ") != -1) + { + String error = "DEFAULT in Parameter not supported"; + log.info (error); + m_conversionError = error; + return result; + } + signature.append("("); + if (group.length() > 2) + { + group = group.substring(1,group.length()-1); + // Paraneters are delimited by , + String[] parameters = group.split(","); + for (int i = 0; i < parameters.length; i++) + { + if (i != 0) + signature.append(", "); + // name ALIAS FOR $1 + String p = parameters[i].trim(); + alias.append(p.substring(0,p.indexOf(" "))) + .append(" ALIAS FOR $").append(i+1).append(";\n"); + // Datatape + signature.append(p.substring(p.lastIndexOf(" ")+1)); + } + } + signature.append(")"); + sb.append(signature); + // log.info("Alias: " + alias.toString()); + // log.info("Signature: " + signature.toString()); + } + // No Parameters + else + { + String error = "Missing Parameter ()"; + log.info (error); + m_conversionError = error; + return result; + } + sb.append("\n"); + // Need to create drop statement + if (orReplacePos != -1) + { + String drop = "DROP " + name + signature.toString(); + // log.info(drop); + result.add(drop); + } + // log.info("1>" + sb.toString() + "<1"); + + // Second Group -> RETURN VARCHAR AS + // RETURNS VARCHAR AS + m.find(); + group = m.group(); + m.appendReplacement(sb, ""); + if (group.startsWith("RETURN")) + sb.append("RETURNS").append(group.substring(group.indexOf(" "))); + sb.append(" '\nDECLARE\n") + .append(alias); // add aliases here + // log.info("2>" + sb.toString() + "<2"); + + // remainder statements + while (m.find()) + { + String group2 = m.group(); + if (group2.indexOf('$') != -1) // Group character needs to be escaped + group2 = Util.replace(group2, "$", "\\$"); + m.appendReplacement(sb, group2); + sb.append("\n"); + } + m.appendTail(sb); + + // finish + sb.append("' LANGUAGE 'plpgsql';"); + // log.info(">" + sb.toString() + "<"); + result.add(sb.toString()); + // + return result; + } // convertProcedure + + /** + * Convert Trigger. + *
+	 *      DROP FUNCTION emp_trgF();
+	 *      CREATE FUNCTION emp_trg () RETURNS OPAQUE AS '....
+	 *          RETURN NEW; ...
+	 *          ' LANGUAGE 'plpgsql';
+	 *      DROP TRIGGER emp_trg ON emp;
+	 *      CREATE TRIGGER emp_trg BEFORE INSERT OR UPDATE ON emp
+	 *      FOR EACH ROW EXECUTE PROCEDURE emp_trgF();
+	 *  
+ * @param sqlStatement + * @return CREATE and DROP TRIGGER and associated Function statement + */ + private ArrayList convertTrigger (String sqlStatement) + { + ArrayList result = new ArrayList(); + // Convert statement - to avoid handling contents of comments + String stmt = converSimpleStatement(sqlStatement); + + // Trigger specific replacements + stmt = Pattern.compile("\\bINSERTING\\b").matcher(stmt).replaceAll("TG_OP='INSERT'"); + stmt = Pattern.compile("\\bUPDATING\\b").matcher(stmt).replaceAll("TG_OP='UPDATE'"); + stmt = Pattern.compile("\\bDELETING\\b").matcher(stmt).replaceAll("TG_OP='DELETE'"); + stmt = Pattern.compile(":new.").matcher(stmt).replaceAll("NEW."); + stmt = Pattern.compile(":old.").matcher(stmt).replaceAll("OLD."); + + // Double quotes ' + stmt = Pattern.compile("'").matcher(stmt).replaceAll("''"); + // remove OR REPLACE + int orReplacePos = stmt.toUpperCase().indexOf(" OR REPLACE "); + // trigger Name + int triggerPos = stmt.toUpperCase().indexOf(" TRIGGER ") + 9; + String triggerName = stmt.substring(triggerPos); + triggerName = triggerName.substring(0, triggerName.indexOf(" ")); + // table name + String tableName = stmt.substring(stmt.toUpperCase().indexOf(" ON ")+4); + tableName = tableName.substring(0, tableName.indexOf(" ")); + + // Function Drop + if (orReplacePos != -1) + { + String drop = "DROP FUNCTION " + triggerName + "F()"; + // log.info(drop); + result.add(drop); + } + + // Function & Trigger + int pos = stmt.indexOf("DECLARE "); + if (pos == -1) + pos = stmt.indexOf("BEGIN "); + String functionCode = stmt.substring(pos); + StringBuffer triggerCode = new StringBuffer ("CREATE TRIGGER "); + triggerCode.append(triggerName).append("\n") + .append(stmt.substring(triggerPos+triggerName.length(), pos)) + .append("\nEXECUTE PROCEDURE ").append(triggerName).append("F();"); + + // Add NEW to existing Return --> DELETE Trigger ? + functionCode = Pattern.compile("\\bRETURN;", Pattern.CASE_INSENSITIVE) + .matcher(functionCode) + .replaceAll("RETURN NEW;"); + // Add final return and change name + functionCode = Pattern.compile("\\bEND " + triggerName + ";", Pattern.CASE_INSENSITIVE) + .matcher(functionCode) + .replaceAll("\nRETURN NEW;\nEND " + triggerName + "F;"); + + // Line separators + String match = + "(\\(.*\\))" // (.) Parameter + + "|(;)" // Statement End + // Nice to have - for readability + + "|(\\bBEGIN\\b)" // BEGIN + + "|(\\bTHEN\\b)" + + "|(\\bELSE\\b)" + + "|(\\bELSIF\\b)"; + Matcher m = Pattern.compile(match, Pattern.CASE_INSENSITIVE).matcher(functionCode); + + // Function Header + StringBuffer sb = new StringBuffer("CREATE FUNCTION "); + sb.append(triggerName).append("F() RETURNS OPAQUE AS '\n"); + + // remainder statements + while (m.find()) + { + String group = m.group(); + if (group.indexOf('$') != -1) // Group character needs to be escaped + group = Util.replace(group, "$", "\\$"); + m.appendReplacement(sb, group); + sb.append("\n"); + } + m.appendTail(sb); + + // finish Function + sb.append("' LANGUAGE 'plpgsql';"); + // log.info(">" + sb.toString() + "<"); + result.add(sb.toString()); + + // Trigger Drop + if (orReplacePos != -1) + { + String drop = "DROP TRIGGER " + triggerName.toLowerCase() + " ON " + tableName; + // log.info(drop); + result.add(drop); + } + + // Trigger + // Remove Column references OF ... ON + String trigger = Pattern.compile("\\sOF.*ON\\s") + .matcher(triggerCode) + .replaceAll(" ON "); + // log.info(trigger); + result.add(trigger); + + // + return result; + } // convertTrigger + + /** + * Convert View. + * Handle CREATE OR REPLACE + * @param sqlStatement + * @return converted statement(s) + */ + private ArrayList convertView (String sqlStatement) + { + ArrayList result = new ArrayList(); + String stmt = converSimpleStatement(sqlStatement); + + // remove OR REPLACE + int orReplacePos = stmt.toUpperCase().indexOf(" OR REPLACE "); + if (orReplacePos != -1) + { + int index = stmt.indexOf(" VIEW "); + int space = stmt.indexOf(' ', index+6); + String drop = "DROP VIEW " + stmt.substring(index+6, space); + result.add(drop); + // + String create = "CREATE" + stmt.substring(index); + result.add(create); + } + else // simple statement + result.add(stmt); + return result; + } // convertView + + + /************************************************************************** + * Converts Decode, Outer Join and Sequence. + *
+	 *      DECODE (a, 1, 'one', 2, 'two', 'none')
+	 *       => CASE WHEN a = 1 THEN 'one' WHEN a = 2 THEN 'two' ELSE 'none' END
+	 *
+	 *      AD_Error_Seq.nextval
+	 *       => nextval('AD_Error_Seq')
+	 *
+	 *      RAISE_APPLICATION_ERROR (-20100, 'Table Sequence not found')
+	 *       => RAISE EXCEPTION 'Table Sequence not found'
+	 *
+	 *  
+ * @param sqlStatement + * @return converted statement + */ + private String convertComplexStatement(String sqlStatement) + { + String retValue = sqlStatement; + StringBuffer sb = null; + + // Convert all decode parts + while (retValue.indexOf("DECODE") != -1) + retValue = convertDecode(retValue); + + /** + * Sequence Handling -------------------------------------------------- + * AD_Error_Seq.nextval + * => nextval('AD_Error_Seq') + */ + Matcher m = Pattern.compile("\\w+\\.(nextval)|(curval)", Pattern.CASE_INSENSITIVE) + .matcher(retValue); + sb = new StringBuffer(); + while (m.find()) + { + String group = m.group(); + // System.out.print("-> " + group); + int pos = group.indexOf("."); + String seqName = group.substring(0,pos); + String funcName = group.substring(pos+1); + group = funcName + "('" + seqName + "')"; + // log.info(" => " + group); + if (group.indexOf('$') != -1) // Group character needs to be escaped + group = Util.replace(group, "$", "\\$"); + m.appendReplacement(sb, group); + } + m.appendTail(sb); + retValue = sb.toString(); + + /** + * RAISE -------------------------------------------------------------- + * RAISE_APPLICATION_ERROR (-20100, 'Table Sequence not found') + * => RAISE EXCEPTION 'Table Sequence not found' + */ + m = Pattern.compile("RAISE_APPLICATION_ERROR\\s*\\(.+'\\)", Pattern.CASE_INSENSITIVE) + .matcher(retValue); + sb = new StringBuffer(); + while (m.find()) + { + String group = m.group(); + System.out.print("-> " + group); + String result = "RAISE EXCEPTION " + group.substring(group.indexOf('\''), group.lastIndexOf('\'')+1); + log.info(" => " + result); + + if (result.indexOf('$') != -1) // Group character needs to be escaped + result = Util.replace(result, "$", "\\$"); + m.appendReplacement(sb, result); + } + m.appendTail(sb); + retValue = sb.toString(); + + // Truncate Handling ------------------------------------------------- + //begin vpj-cd e-evolution 16/07/2005 + //while (retValue.indexOf("TRUNC") != -1) + if(retValue.indexOf("TRUNC(((TRUNC(") != -1 && DB.isPostgreSQL()) + retValue = Util.replace(retValue,"TRUNC(((TRUNC(","(((TRUNC("); + //end vpj-cd e-evolution 16/07/2005 + + while (retValue.indexOf("TRUNC") != -1) + retValue = convertTrunc (retValue); + + // Outer Join Handling ----------------------------------------------- + int index = retValue.indexOf("SELECT "); + if (index != -1 && retValue.indexOf("(+)", index) != -1) + retValue = convertOuterJoin(retValue); + + return retValue; + } // convertComplexStatement + + + /** + * Convert RowNum. + *
+	 *      SELECT Col1 FROM tableA WHERE ROWNUM=1
+	 *      => SELECT Col1 FROM tableA LIMIT 1
+	 *  Assumptions/Limitations:
+	 *  - RowNum not used in SELECT part
+	 *  
+ * @param sqlStatement + * @return converted statement + */ + private String convertRowNum (String sqlStatement) + { + log.info("RowNum<== " + sqlStatement); + if(DB.isPostgreSQL()) + { + log.info("RowNum<== " + sqlStatement); + String retValue = null; + + //find into (select from where) + + int s_end = 0; + int s_start = -1; + String select = sqlStatement; + String convert = ""; + while(true) + { + s_end = 0; + s_start = select.indexOf( "(SELECT"); + + if (s_start == -1) + break; + + convert = convert + select.substring(0,s_start); + //System.out.println("convert:" + convert); + int open = -1; + for (int i = s_start; i < select.length(); i++) + { + char c = select.charAt(i); + if (c == '(') + open ++; + + if (c == ')') + open --; + + if (open == -1) + { + s_end = i + 1; + break; + } + } + + String subselect = select.substring(s_start,s_end); + //System.out.println("subselect:" +subselect); + //System.out.println("select:" +select); + + if (subselect.indexOf("AND ROWNUM=1") > 1) + { + subselect = subselect.substring(0 , subselect.length() -1 ) + " LIMIT 1 )"; + //System.out.println("subselect:" +subselect); + convert = convert + Util.replace(subselect,"AND ROWNUM=1",""); + //System.out.println("convert:" + convert); + } + else if (subselect.indexOf(" WHERE ROWNUM=1 AND") > 1) + { + subselect = subselect.substring(0 , subselect.length() -1 ) + " LIMIT 1 )"; + //System.out.println("subselect:" +subselect); + convert = convert + Util.replace(subselect," WHERE ROWNUM=1 AND"," WHERE "); + //System.out.println("convert:" + convert); + } + else + { + convert = convert + subselect; + } + + + select = select.substring(s_end); + retValue = select; + + } + //System.out.println("convert:" + convert); + //System.out.println("select:" + select); + if (retValue==null) + retValue = sqlStatement; + + if (retValue.indexOf("AND ROWNUM=1") > 1) + { + int rownum = retValue.indexOf("AND ROWNUM=1"); + if(retValue.substring(0,rownum).contains("WHERE")) + { + retValue = Util.replace(retValue,"AND ROWNUM=1"," LIMIT 1"); + return convert + retValue ; + } + else + { + retValue = Util.replace(retValue,"AND ROWNUM=1",""); + return convert + retValue + " LIMIT 1"; + } + + } + else if (retValue.indexOf("AND ROWNUM= 1") > 1) + { + int rownum = retValue.indexOf("AND ROWNUM= 1"); + if(retValue.substring(0,rownum).contains("WHERE")) + { + + retValue = Util.replace(retValue,"AND ROWNUM= 1"," LIMIT 1"); + return convert + retValue ; + } + else + { + retValue = Util.replace(retValue,"AND ROWNUM= 1",""); + return convert + retValue + " LIMIT 1"; + } + } + else if (retValue.indexOf("AND ROWNUM = 1") > 1) + { + int rownum = retValue.indexOf("AND ROWNUM = 1"); + if(retValue.substring(0,rownum).contains("WHERE")) + { + + retValue = Util.replace(sqlStatement,"AND ROWNUM = 1"," LIMIT 1"); + return convert + retValue; + } + else + { + retValue = Util.replace(sqlStatement,"AND ROWNUM = 1",""); + return convert + retValue + " LIMIT 1"; + } + } + else if (retValue.indexOf("AND ROWNUM =1") > 1) + { + int rownum = retValue.indexOf("AND ROWNUM =1"); + if(retValue.substring(0,rownum).contains("WHERE")) + { + + retValue = Util.replace(retValue,"AND ROWNUM =1"," LIMIT 1"); + return convert + retValue ; + } + else + { + retValue = Util.replace(retValue,"AND ROWNUM =1",""); + return convert + retValue + " LIMIT 1"; + } + } + else if (retValue.indexOf("ROWNUM=1") > 1) + { + int rownum = retValue.indexOf("ROWNUM=1"); + System.out.println("retValue"+ retValue); + if(retValue.substring(0,rownum).contains("WHERE")) + { + retValue = Util.replace(retValue,"ROWNUM=1 "," LIMIT 1"); + return convert + retValue ; + } + else + { + retValue = Util.replace(retValue,"ROWNUM=1",""); + return convert + retValue + " LIMIT 1"; + } + } + // log.info("RowNum==> " + retValue); + return convert + retValue; + } + else + return sqlStatement; + // + // log.info("RowNum==> " + retValue); + // return retValue; + // end e-evolution PostgreSQL + } // convertRowNum + + /** + * Convert TRUNC. + * Assumed that it is used for date only! + * @param sqlStatement + * @return converted statement + */ + private String convertTrunc (String sqlStatement) + { + /** + *
+	 *      TRUNC(myDate)
+	 *      => DATE_Trunc('day',myDate)
+	 *
+	 *      TRUNC(myDate,'oracleFormat')
+	 *      => DATE_Trunc('pgFormat',myDate)
+	 *
+	 *      Oracle          =>  PostgreSQL  (list not complete!)
+	 *          Q               quarter
+	 *          MM              month
+	 *          DD              day
+	 *      Spacial handling of DAY,DY  (Starting dat of the week)
+	 *      => DATE_Trunc('day',($1-DATE_PART('dow',$1)));
+	 *  
+ //begin vpj-cd e-evolution 07/12/2005 + */ + //index = sqlStatement.indexOf("TRUNC("); + //beforeStatement = sqlStatement.substring(0, index); + //beforeStatement = sqlStatement.replaceFirst("TRUNC" , "DATE_Trunc"); + int find = -1; + find = sqlStatement.indexOf(",'Q'"); + if (find != -1) + + + + + { + + sqlStatement = sqlStatement.replaceFirst("TRUNC\\(" , "DATE_Trunc('quarter',"); + sqlStatement = sqlStatement.replaceFirst(",'Q'", ""); + return sqlStatement; + } + find = sqlStatement.indexOf(",'Y'"); + if (find != -1) + { + sqlStatement = sqlStatement.replaceFirst("TRUNC\\(" , "DATE_Trunc('year',"); + sqlStatement = sqlStatement.replaceFirst(",'Y'", ""); + return sqlStatement; + } + find = sqlStatement.indexOf(",'MM'"); + if (find != -1) + + + + + + + + { + sqlStatement = sqlStatement.replaceFirst("TRUNC\\(" , "DATE_Trunc('month',"); + sqlStatement = sqlStatement.replaceFirst(",'MM'", ""); + return sqlStatement; + } + find = sqlStatement.indexOf(",'DD'"); + if (find != -1) + { + sqlStatement = sqlStatement.replaceFirst("TRUNC\\(" , "DATE_Trunc('day',"); + sqlStatement = sqlStatement.replaceFirst(",'DD'", ""); + return sqlStatement; + } + find = sqlStatement.indexOf(",'DY'"); + if (find != -1) + { + sqlStatement = sqlStatement.replaceFirst("TRUNC\\(" , "DATE_Trunc('day',"); + sqlStatement = sqlStatement.replaceFirst(",'DY'", ""); + return sqlStatement; + } + if (find == -1) + { + sqlStatement = sqlStatement.replaceFirst("TRUNC\\(" , "DATE_Trunc('day',"); + //sqlStatement = sqlStatement.replaceFirst(",'DY'", ""); + return sqlStatement; + } + System.out.println("SQL=" + sqlStatement); + return sqlStatement; + + //end vpj-cd e-evolution 09/02/2005 PostgreSQL + } // convertTrunc +// begin vpj-cd e-evolution 02/24/2005 PostgreSQL + /************************************************************************** + * Converts Decode. + *
+	 *      UPDATE C_Order i SET 
+	 *       => UPDATE C_Order SET
+	 *  
+ * @param sqlStatement + * @return converted statement + */ + /* + private String convertUpdate(String sqlStatement) + { + + if(DB.isPostgreSQL()) + { + String sqlUpdate = sqlStatement; + int index = 0; + int begintable = 0; + int begin = 0; + int end = 0; + String alias = null; + + + end = 0; + begin = Util.findIndexOf(sqlUpdate,"SET ("); + if(begin != -1) + { + + if (sqlUpdate.toUpperCase().indexOf("UPDATE ") == 0) + { + index = sqlUpdate.toUpperCase().indexOf("UPDATE "); + //String firstPart = statement.substring(0,index); + + begintable = sqlUpdate.indexOf(' ', 6 ); + + // begin the opening ' ' begin Alias + begin = sqlUpdate.indexOf(' ', 7 ); + //statement = statement.substring(begin); + + // end Alias + + end = sqlUpdate.toUpperCase().indexOf(" SET", 0 ); //statement.indexOf("SET", 0 ) + } + + String table = sqlUpdate.substring(begintable,begin).trim(); + + String select = ""; + + begin = Util.findIndexOf(sqlUpdate," SET ("); + end = sqlUpdate.indexOf(")=("); + if (end != -1) + select = sqlUpdate.substring(end + 2); + else + { + end = sqlUpdate.indexOf(") = ("); + if (end != -1) + select = sqlUpdate.substring(end + 4); + else + { + end = sqlUpdate.indexOf(")= ("); + if (end !=-1) + select = sqlUpdate.substring(end + 3); + else + { + end = sqlUpdate.indexOf(") =("); + if (end !=-1) + select = sqlUpdate.substring(end + 3); + } + + } + } + + + int where_begin = -1; + String rest = ""; + //String select = sqlUpdate.substring(end + 2); + //System.out.println("SELECT ->" + select); + //int s_end = select.indexOf( ")"); + int s_end = 0; + int s_start = select.indexOf( "("); + String where = null; + int open = -1; + for (int i = s_start; i < select.length(); i++) + { + char c = select.charAt(i); + if (c == '(') + open ++; + + if (c == ')') + open --; + + if (open == -1) + { + s_end = i + 1; + break; + } + } + + where = select.substring(s_end); + where = where.substring(where.indexOf(" WHERE ") + 7 ); + + String s = select.substring(s_start,s_end); + + //System.out.println("s:"+ s); + + //System.out.println("s_end"+ s_end); + //System.out.println("rest: " + rest); + String from =s.substring( s.toUpperCase().indexOf(" FROM ") + 6); + //System.out.println("from"+ from); + String tablejoin = from.substring(0,from.toUpperCase().indexOf(" ")); + //System.out.println("tablejoin"+ tablejoin); + String tablealias = from.substring(0,from.toUpperCase().indexOf(" WHERE ")); + //System.out.println("tablealias"+ tablealias); + //System.out.println("------------------select.toUpperCase().substring(s_end)" +select.substring(select.substring(s_end).toUpperCase().indexOf(" WHERE "))); + //String swhere = select.substring(s_end); + //s_end = + //System.out.println(); + ///System.out.println("string end" + swhere); + //String s_where = ""; + //System.out.println("string end" + select.substring(select.substring(s_end).toUpperCase().indexOf(" WHERE ")); + String s_where = s.substring(s.toUpperCase().indexOf(" WHERE ") + 7,s.length() -1); + //System.out.println("Where before join" + where); + //System.out.println("s_where:" + s_where); + //System.out.println("where:" + where); + //System.out.println("FROM:" + from); + //System.out.println("Table Join:" + tablejoin); + //System.out.println("Table Alias:" + tablejoin); + + + String Update = sqlUpdate.substring(0,begin); + Update = Update + " SET "; + int f_begin = begin + 6 ; + int f_beginjoin = 0 ; + //System.out.println(" sqlUpdate"+ sqlUpdate); + String fields = sqlUpdate.substring(f_begin, end); + //System.out.println("------fields" + fields); + int beginfrom = select.toUpperCase().indexOf(" FROM "); + String fieldsjoin = select.substring(select.toUpperCase().indexOf("(SELECT ")+8,beginfrom); + //System.out.println("fields"+fields); + //System.out.println("fields Joint"+fieldsjoin); + int f = fields.length(); + int fj = fieldsjoin.length(); + String field = null; + String fieldjoin = null; + //System.out.println("Update:"+ Update); + + while (f > 0) + { + f = Util.findIndexOf(fields,',');//fields.indexOf(','); + //System.out.println("comman" + c); + if (f < 0) + { + //System.out.print("fields:"+fields); + field = fields; + fieldjoin = fieldsjoin; + if (fieldjoin.indexOf(".") < 0) + { + fieldjoin = tablejoin + "." +fieldjoin; + } + + + //System.out.println("f_begin:" + f_begin + " end :" + end + " field:" + field); + //Update = Update + field.trim() + "=" + tablejoin + "." + field.trim() + rest + " FROM " + tablealias + " WHERE " + where ; // + select.substring(s_end + 8); + Update = Update + field.trim() + "=" + fieldjoin.trim() + rest + " FROM " + tablealias + " WHERE " + s_where ; // + select.substring(s_end + 8); + //System.out.println("Last Update" + Update); + // set alias all field before where + + if (where!=null) + where = " AND " + where; + + else + where = ""; + + + String sqlkey = "AND,OR,FROM,WHERE,JOIN,BY,GROUP,IN,INTO,SELECT,NOT,SET,UPDATE,DELETE,HAVING,IS,NULL,EXISTS" ; + int o = -1; + StringTokenizer st = new StringTokenizer(where); + String result = ""; + String word = ""; + while (true) // make sure there is stuff to get + { + word = st. nextToken(); + //System.out.println("Word:" + word); + if(sqlkey.indexOf(word) == -1) + { + + + for (int i = 0; i < word.length(); i++) + { + char c = word.charAt(i); + if (c == '(') + o ++; + if (c == ')') + o --; + } + if (o == -1 && (!word.contains(")") | !word.contains("("))) + { + + result = result + " " + table + "."+ word; + //System.out.println("Cadena :" + word); + } + else + { + result = result + " " + word; + } + + + } + else + result = result + " " + word; + if(!st.hasMoreElements()) + break; + } + + Update = Update + result ; + //System.out.println("UPDATE"+ Update); + } + else + { + + field = fields.substring(0 ,f); + //System.out.println("Field:"+ field); + //System.out.println("------fieldsjoin"+ fieldsjoin); + fj = Util.findIndexOf(fieldsjoin,',');//fj = fieldsjoin.indexOf(','); + + fieldjoin = fieldsjoin.substring(0 ,fj); + //System.out.println("fields"+ fields); + //System.out.println("fieldsjoin"+ fieldsjoin); + if (fieldjoin.indexOf(".") < 0 != fieldjoin.equals("SysDate")) + { + fieldjoin = tablejoin + "." +fieldjoin; + } + //System.out.println( " -----> fj" + fj + "fieldjoin " + fieldjoin); + //Update = Update + field + "=" + tablejoin + "." + field.trim() + ","; + Update = Update + field.trim() + "=" + fieldjoin.trim()+ ","; + f_beginjoin = fj; + fieldsjoin= fieldsjoin.substring(f_beginjoin + 1); + //System.out.println("fieldsjoin" + fieldsjoin); + f_beginjoin =fj; + } + + f_begin = f; + fields = fields.substring(f_begin + 1); + + //System.out.println("Update" + Update); + } + + sqlUpdate = Update ; + + } + //System.out.println("Convert Update:"+sqlUpdate); + return sqlUpdate; + } + else + return sqlStatement; + + } // convertDecode + **/ + + // Two regex's used in convertUpdate +private static final Pattern aliasPatternInUpdate = +Pattern.compile("(?i)\\s*UPDATE\\s+(\\S+)\\s+(\\S+)\\s+SET\\s.*"); +private static final Pattern tupleUpdatePatternInUpdate = +Pattern.compile("(?i)\\s*UPDATE\\s+(\\S+)\\s+SET\\s+\\(([^\\)]+)\\)\\s*=\\s*\\(\\s*SELECT\\s(.*?)\\s(FROM\\s.*)"); + +private String convertUpdate(String sqlStatement) +{ + String convertedSqlStatement = sqlStatement; + + // 1st step: Remove and replace alias + Matcher aliasMatcher = aliasPatternInUpdate.matcher(sqlStatement); + if (aliasMatcher.matches()) { + // We found an UPDATE-statement with an alias => convert + + // Extract table name and alias + String tableName = aliasMatcher.group(1); + String alias = aliasMatcher.group(2); + + // remove the alias before SET + convertedSqlStatement = sqlStatement.replaceFirst("\\s+" + alias + "\\s+", " "); + + // replace the alias with the real table name in all other places + convertedSqlStatement = convertedSqlStatement.replaceAll("\\b" + alias + "\\.", tableName + "."); + } // End of: Remove and replace alias + + // 2nd: step: Convert tuple updates with inner SELECT + Matcher tupleUpdateMatcher = tupleUpdatePatternInUpdate.matcher(convertedSqlStatement); + if (tupleUpdateMatcher.matches()) { + // We found an UPDATE-statement with a "tuple-update" + // of the form UPDATE a SET (b, c) = (SELECT x, y FROM z WHERE) WHERE ... + + // Extract some important parts of the statement + String tableName = tupleUpdateMatcher.group(1); + String columnsTupleString = tupleUpdateMatcher.group(2); + String innerSelectColumnsTupleString = tupleUpdateMatcher.group(3); + String innerSelectFromUntilEnd = tupleUpdateMatcher.group(4); + + // columnsArray contains the columns to be updated + String[] columnsArray = columnsTupleString.split("\\s*,\\s*"); + // innerSelectColumnsArray contains the corresponding "columns" + // of the inner SELECT statement + String[] innerSelectColumnsArray = new String[columnsArray.length]; + + // split the inner SELECT columns by ',' but not within parenthesis + char[] innerSelectColumnsCharArray = innerSelectColumnsTupleString.toCharArray(); + int openParenthesisCount = 0; + int columnCount = 0; + StringBuffer currentInnerSelectColumnSb = new StringBuffer(); + int innerSelectColumnsCharArrayLength = innerSelectColumnsCharArray.length; + int innerSelectColumnsCharArrayLastIndex= innerSelectColumnsCharArrayLength - 1; + for (int i=0; i 0) { + // If inside of a parenthesis pair simply append the character + currentInnerSelectColumnSb.append(innerSelectColumnsCharArray[i]); + } + else + { + // We're not inside of a parentheses pair + if (innerSelectColumnsCharArray[i] == ',') + { + // A ',' denotes the end of the inner SELECT column + innerSelectColumnsArray[columnCount] = currentInnerSelectColumnSb.toString().trim(); + // Start the next "column" of the inner SELECT + currentInnerSelectColumnSb = new StringBuffer(); + columnCount++; + } + else if (i == innerSelectColumnsCharArrayLastIndex) + { + // End of String reached => append last character and add last column + currentInnerSelectColumnSb.append(innerSelectColumnsCharArray[i]); + innerSelectColumnsArray[columnCount] = currentInnerSelectColumnSb.toString().trim(); + } + else + { + // We did not find a ',' and we did not reach the end of the string + // => this is a "normal" character; append + currentInnerSelectColumnSb.append(innerSelectColumnsCharArray[i]); + } + } + // Take care of opening and closing parenthesis + // to adjust the open parenthesis count + if (innerSelectColumnsCharArray[i] == '(') { + openParenthesisCount++; + } else if (innerSelectColumnsCharArray[i] == ')') { + openParenthesisCount--; + } + } + + // Split the FROM-until-end-part into + // a) the inner SELECT FROM-WHERE-Clause (innerSelectFromWhereClauseSb) + // b) the WHERE-clause of the UPDATE-statement (updateWhereClauseSb) + char[] innerSelectFromUntilEndCharArray = innerSelectFromUntilEnd.toCharArray(); + openParenthesisCount = 0; + int innerSelectFromUntilEndCharArrayLength = innerSelectFromUntilEndCharArray.length; + StringBuffer innerSelectFromWhereClauseSb = new StringBuffer(); + StringBuffer updateWhereClauseSb = new StringBuffer(); + boolean endOfinnerSelectFromWhereClauseReached = false; + for (int i=0; i increment the open parenthesis count + openParenthesisCount++; + innerSelectFromWhereClauseSb.append('('); + } else { + // Append all other characters + innerSelectFromWhereClauseSb.append(innerSelectFromUntilEndCharArray[i]); + + } + } + } + + // assemble the new UPDATE statement + int columnsArrayLength = columnsArray.length; + int columnsArrayLastIndex = columnsArrayLength - 1; + StringBuffer newUpdateStatementSb = new StringBuffer("UPDATE "); + newUpdateStatementSb.append(tableName); + newUpdateStatementSb.append(" SET "); + // We now have: "UPDATE tablename SET " + // Now iterate over all columns to be updated and add + // the SELECT clause + for (int i=0; i + * DELETE C_Order i WHERE + * => DELETE FROM C_Order WHERE + * + * @param sqlStatement + * @return converted statement + */ + private String convertDelete(String sqlStatement) + { + + int index = sqlStatement.toUpperCase().indexOf("DELETE "); + if(index < 7) + { + return "DELETE FROM " + sqlStatement.substring(index+7); + + } + + return sqlStatement; + } // convertDelete + + + //begin vpj-cd e-evolution 08/02/2005 + /************************************************************************** + * convertAlias. + * @param sqlStatement + * @return converted statementf + */ + private String convertAlias(String sqlStatement) + { + String statement = sqlStatement; + int index = 0; + int begintable = 0; + int begin = 0; + int end = 0; + String alias = null; + + if (statement.toUpperCase().indexOf("DELETE FROM ") == 0) + { + index = statement.toUpperCase().indexOf("DELETE FROM "); + begintable = statement.indexOf(' ', 11 ); + // begin the opening ' ' begin Alias + begin = statement.indexOf(' ', 12 ); + // end Alias + end = statement.toUpperCase().indexOf("WHERE", 0 ); + } + else if (statement.toUpperCase().indexOf("UPDATE ") == 0) + { + index = statement.toUpperCase().indexOf("UPDATE "); + //String firstPart = statement.substring(0,index); + + begintable = statement.indexOf(' ', 6 ); + + // begin the opening ' ' begin Alias + begin = statement.indexOf(' ', 7 ); + //statement = statement.substring(begin); + + // end Alias + + end = statement.toUpperCase().indexOf(" SET" , 0 ); //statement.indexOf("SET", 0 ); + + } + else + { + return statement; + } + + String sqlAlias = statement ; + if (end > begin) + { + alias = statement.substring(begin,end).trim()+"."; + String table = statement.substring(begintable,begin).trim(); + //System.out.println("Table" + table); + statement = statement.substring(0,begin) + " " + statement.substring(end); + if (!alias.equals(".")) + { + sqlAlias = Util.replace(statement, " " +alias , " " + table + "."); + sqlAlias = Util.replace(sqlAlias, "=" +alias , "=" + table + "."); + sqlAlias = Util.replace(sqlAlias, "(" +alias , "(" + table + "."); + } + } + + //sqlDelete = Util.replace(sqlDelete, "DELETE " , "DELETE FROM "); + //System.out.println("Convertion Alias:" + statement.substring(0, begin ) + " " + statement.substring(end)); + //System.out.println("Statement Convert:" + statement); + //System.out.println("begin Alias:" + begin + " end Alias:" + end ); + //System.out.println("Alias:" + statement.substring(begin, end).trim()); + //System.out.println("SQL Alias:"+sqlAlias); + return sqlAlias; + } // convertDelete + // end vpj-cd e-evolution 02/24/2005 PostgreSQL + + // begin vpj-cd 08/02/2005 + //ALTER TABLE AD_FieldGroup MODIFY IsTab CHAR(1) DEFAULT N; + //ALTER TABLE AD_FieldGroup ALTER COLUMN IsTab TYPE CHAR(1); ALTER TABLE AD_FieldGroup ALTER COLUMN SET DEFAULT 'N'; + private String convertDDL(String sqlStatement) + { + if (sqlStatement.toUpperCase().indexOf("ALTER TABLE ") == 0) + { + String action = null; + int begin_col = -1; + if (sqlStatement.toUpperCase().indexOf(" MODIFY ") > 0) + { + action = " ALTER "; + begin_col = sqlStatement.toUpperCase().indexOf(" MODIFY ") + action.length() ; + } + else if (sqlStatement.toUpperCase().indexOf(" ADD ") > 0) + { + action = " ADD "; + begin_col = sqlStatement.toUpperCase().indexOf(" ADD ") + action.length() ; + } + + //System.out.println( "MODIFY :" + sqlStatement.toUpperCase().indexOf(" MODIFY ")); + //System.out.println( "ADD :" + sqlStatement.toUpperCase().indexOf(" ADD ")); + //System.out.println( "begincolumn:" + sqlStatement + "begincolumn:" + begin_col ); + + if (begin_col < 0) + return sqlStatement; + + + int end_col = 0; + int begin_default = -1; + int begin_type = -1; + + String column = null; + String type = null; + String defaultvalue = null; + String DDL = null; + + if (begin_col != -1) + { + column = sqlStatement.substring(begin_col); + end_col = begin_col + column.indexOf(" "); + column = sqlStatement.substring(begin_col , end_col); + //System.out.println(" column:" + column + " begincolumn:" + begin_col + "en column:" + end_col ); + //System.out.println(" type " + sqlStatement.substring(end_col + 1)); + type = sqlStatement.substring(end_col + 1) + " "; + //System.out.println(" type 1 :" + type); + type = type.substring(0 , type.indexOf(" ")); + //System.out.println(" type:" + type); + if (action.equals(" ADD ")) + DDL = sqlStatement.substring(0, begin_col - action.length()) + action + "COLUMN " + column + " " + type + "; "; + else if (action.equals(" ALTER ")) + DDL = sqlStatement.substring(0, begin_col - action.length()) + action + "COLUMN " + column + " TYPE " + type + "; "; + + if (sqlStatement.toUpperCase().indexOf(" DEFAULT ") != -1) + { + begin_default = sqlStatement.toUpperCase().indexOf(" DEFAULT ") + 9; + defaultvalue = sqlStatement.substring(begin_default); + String rest = defaultvalue.substring( defaultvalue.indexOf(" ")); + defaultvalue = defaultvalue.substring(0 , defaultvalue.indexOf(" ")); + + DDL += sqlStatement.substring(0 , begin_col - action.length()) + " ALTER COLUMN " + column + " SET DEFAULT '" + defaultvalue + "'; "; + if (rest != null && rest.indexOf(" NOT NULL ") == 0) + DDL += sqlStatement.substring(0 , begin_col ) + " ALTER COLUMN " + column + " SET " + rest + ";"; + //return DDL; + } + + //System.out.println("DDL" + DDL); + return DDL; + } + } + + + return sqlStatement; + } + + private String convertIgnore(String sqlStatement) + { + String vars[]= new String[20]; + int cont=1; + Pattern p = Pattern.compile("'[[\\w]*[,]*[ ]*]*'",Pattern.CASE_INSENSITIVE); + Matcher m = p.matcher(sqlStatement); + while(m.find()) { + vars[cont++]=sqlStatement.substring(m.start(),m.end()); + } + vars[0]=m.replaceAll("<-->"); + String retVar[]=new String[cont]; + for(int i=0; i"); + m = p.matcher(retVar[0]); + cont=1; + for(cont=1; cont + * SELECT a.Col1, b.Col2 FROM tableA a, tableB b WHERE a.ID=b.ID(+) + * => SELECT a.Col1, b.Col2 FROM tableA a LEFT OUTER JOIN tableB b ON (a.ID=b.ID) + * + * SELECT a.Col1, b.Col2 FROM tableA a, tableB b WHERE a.ID(+)=b.ID + * => SELECT a.Col1, b.Col2 FROM tableA a RIGHT OUTER JOIN tableB b ON (a.ID=b.ID) + * Assumptions: + * - No outer joins in sub queries (ignores sub-queries) + * - OR condition ignored (not sure what to do, should not happen) + * Limitations: + * - Parameters for outer joins must be first - as sequence of parameters changes + * + * @param sqlStatement + * @return converted statement + */ + protected String convertOuterJoin (String sqlStatement) + { + boolean trace = false; + // + int fromIndex = Util.findIndexOf (sqlStatement.toUpperCase(), " FROM "); + int whereIndex = Util.findIndexOf(sqlStatement.toUpperCase(), " WHERE "); + //begin vpj-cd e-evolution 03/14/2005 PostgreSQL + //int endWhereIndex = Util.findIndexOf(sqlStatement.toUpperCase(), " GRPUP BY "); + int endWhereIndex = Util.findIndexOf(sqlStatement.toUpperCase(), " GROUP BY "); + //end vpj-cd e-evolution 03/14/2005 PostgreSQL + if (endWhereIndex == -1) + endWhereIndex = Util.findIndexOf(sqlStatement.toUpperCase(), " ORDER BY "); + if (endWhereIndex == -1) + endWhereIndex = sqlStatement.length(); + // + if (trace) + { + log.info("OuterJoin<== " + sqlStatement); + // log.info("From=" + fromIndex + ", Where=" + whereIndex + ", End=" + endWhereIndex + ", Length=" + sqlStatement.length()); + } + // + String selectPart = sqlStatement.substring(0, fromIndex); + String fromPart = sqlStatement.substring(fromIndex, whereIndex); + String wherePart = sqlStatement.substring(whereIndex, endWhereIndex); + String rest = sqlStatement.substring(endWhereIndex); + + // find/remove all (+) from WHERE clase ------------------------------ + String newWherePart = wherePart; + ArrayList joins = new ArrayList(); + int pos = newWherePart.indexOf("(+)"); + while (pos != -1) + { + // find starting point + int start = newWherePart.lastIndexOf(" AND ", pos); + int startOffset = 5; + if (start == -1) + { + start = newWherePart.lastIndexOf(" OR ", pos); + startOffset = 4; + } + if (start == -1) + { + start = newWherePart.lastIndexOf("WHERE ", pos); + startOffset = 6; + } + if (start == -1) + { + String error = "Start point not found in clause " + wherePart; + log.severe(error); + m_conversionError = error; + return sqlStatement; + } + // find end point + int end = newWherePart.indexOf(" AND ", pos); + if (end == -1) + end = newWherePart.indexOf(" OR ", pos); + if (end == -1) + end = newWherePart.length(); + // log.info("<= " + newWherePart + " - Start=" + start + "+" + startOffset + ", End=" + end); + + // extract condition + String condition = newWherePart.substring(start+startOffset, end); + joins.add(condition); + if (trace) + log.info("->" + condition); + // new WHERE clause + newWherePart = newWherePart.substring(0, start) + newWherePart.substring(end); + // log.info("=> " + newWherePart); + // + pos = newWherePart.indexOf("(+)"); + } + // correct beginning + newWherePart = newWherePart.trim(); + if (newWherePart.startsWith("AND ")) + newWherePart = "WHERE" + newWherePart.substring(3); + else if (newWherePart.startsWith("OR ")) + newWherePart = "WHERE" + newWherePart.substring(2); + if (trace) + log.info("=> " + newWherePart); + + // Correct FROM clause ----------------------------------------------- + // Disassemble FROM + String[] fromParts = fromPart.trim().substring(4).split(","); + HashMap fromAlias = new HashMap(); // tables to be processed + HashMap fromLookup = new HashMap(); // used tabled + for (int i = 0; i < fromParts.length; i++) + { + String entry = fromParts[i].trim(); + String alias = entry; // no alias + String table = entry; + int aPos = entry.lastIndexOf(' '); + if (aPos != -1) + { + alias = entry.substring(aPos+1); + table = entry.substring(0, entry.indexOf(' ')); // may have AS + } + fromAlias.put(alias, table); + fromLookup.put(alias, table); + if (trace) + log.info("Alias=" + alias + ", Table=" + table); + } + + /** Single column + SELECT t.TableName, w.Name FROM AD_Table t, AD_Window w + WHERE t.AD_Window_ID=w.AD_Window_ID(+) + -- 275 rows + SELECT t.TableName, w.Name FROM AD_Table t + LEFT OUTER JOIN AD_Window w ON (t.AD_Window_ID=w.AD_Window_ID) + + SELECT t.TableName, w.Name FROM AD_Table t, AD_Window w + WHERE t.AD_Window_ID(+)=w.AD_Window_ID + -- 239 rows + SELECT t.TableName, w.Name FROM AD_Table t + RIGHT OUTER JOIN AD_Window w ON (t.AD_Window_ID=w.AD_Window_ID) + + ** Multiple columns + SELECT tn.Node_ID,tn.Parent_ID,tn.SeqNo,tb.IsActive + FROM AD_TreeNode tn, AD_TreeBar tb + WHERE tn.AD_Tree_ID=tb.AD_Tree_ID(+) AND tn.Node_ID=tb.Node_ID(+) + AND tn.AD_Tree_ID=10 + -- 235 rows + SELECT tn.Node_ID,tn.Parent_ID,tn.SeqNo,tb.IsActive + FROM AD_TreeNode tn LEFT OUTER JOIN AD_TreeBar tb + ON (tn.Node_ID=tb.Node_ID AND tn.AD_Tree_ID=tb.AD_Tree_ID AND tb.AD_User_ID=0) + WHERE tn.AD_Tree_ID=10 + + SELECT tn.Node_ID,tn.Parent_ID,tn.SeqNo,tb.IsActive + FROM AD_TreeNode tn, AD_TreeBar tb + WHERE tn.AD_Tree_ID=tb.AD_Tree_ID(+) AND tn.Node_ID=tb.Node_ID(+) + AND tn.AD_Tree_ID=10 AND tb.AD_User_ID(+)=0 + -- 214 rows + SELECT tn.Node_ID,tn.Parent_ID,tn.SeqNo,tb.IsActive + FROM AD_TreeNode tn LEFT OUTER JOIN AD_TreeBar tb + ON (tn.Node_ID=tb.Node_ID AND tn.AD_Tree_ID=tb.AD_Tree_ID AND tb.AD_User_ID=0) + WHERE tn.AD_Tree_ID=10 + + */ + StringBuffer newFrom = new StringBuffer (); + for (int i = 0; i < joins.size(); i++) + { + Join first = new Join ((String)joins.get(i)); + first.setMainTable((String)fromLookup.get(first.getMainAlias())); + fromAlias.remove(first.getMainAlias()); // remove from list + first.setJoinTable((String)fromLookup.get(first.getJoinAlias())); + fromAlias.remove(first.getJoinAlias()); // remove from list + if (trace) + log.info("-First: " + first); + // + if (newFrom.length() == 0) + newFrom.append(" FROM "); + else + newFrom.append(", "); + newFrom.append(first.getMainTable()).append(" ").append(first.getMainAlias()) + .append(first.isLeft() ? " LEFT" : " RIGHT").append(" OUTER JOIN ") + .append(first.getJoinTable()).append(" ").append(first.getJoinAlias()) + .append(" ON (").append(first.getCondition()); + // keep it open - check for other key comparisons + for (int j = i+1; j < joins.size(); j++) + { + Join second = new Join ((String)joins.get(j)); + second.setMainTable((String)fromLookup.get(second.getMainAlias())); + second.setJoinTable((String)fromLookup.get(second.getJoinAlias())); + if ((first.getMainTable().equals(second.getMainTable()) + && first.getJoinTable().equals(second.getJoinTable())) + || second.isConditionOf(first) ) + { + if (trace) + log.info("-Second/key: " + second); + newFrom.append(" AND ").append(second.getCondition()); + joins.remove(j); // remove from join list + fromAlias.remove(first.getJoinAlias()); // remove from table list + //---- + for (int k = i+1; k < joins.size(); k++) + { + Join third = new Join ((String)joins.get(k)); + third.setMainTable((String)fromLookup.get(third.getMainAlias())); + third.setJoinTable((String)fromLookup.get(third.getJoinAlias())); + if (third.isConditionOf(second)) + { + if (trace) + log.info("-Third/key: " + third); + newFrom.append(" AND ").append(third.getCondition()); + joins.remove(k); // remove from join list + fromAlias.remove(third.getJoinAlias()); // remove from table list + } + else if (trace) + log.info("-Third/key-skip: " + third); + } + } + else if (trace) + log.info("-Second/key-skip: " + second); + } + newFrom.append(")"); // close ON + // check dependency on first table + for (int j = i+1; j < joins.size(); j++) + { + Join second = new Join ((String)joins.get(j)); + second.setMainTable((String)fromLookup.get(second.getMainAlias())); + second.setJoinTable((String)fromLookup.get(second.getJoinAlias())); + if (first.getMainTable().equals(second.getMainTable())) + { + if (trace) + log.info("-Second/dep: " + second); + // FROM (AD_Field f LEFT OUTER JOIN AD_Column c ON (f.AD_Column_ID = c.AD_Column_ID)) + // LEFT OUTER JOIN AD_FieldGroup fg ON (f.AD_FieldGroup_ID = fg.AD_FieldGroup_ID), + newFrom.insert(6, '('); // _FROM ... + newFrom.append(')'); // add parantesis on previous relation + // + newFrom.append(second.isLeft() ? " LEFT" : " RIGHT").append(" OUTER JOIN ") + .append(second.getJoinTable()).append(" ").append(second.getJoinAlias()) + .append(" ON (").append(second.getCondition()); + joins.remove(j); // remove from join list + fromAlias.remove(second.getJoinAlias()); // remove from table list + // additional join colums would come here + newFrom.append(")"); // close ON + //---- + for (int k = i+1; k < joins.size(); k++) + { + Join third = new Join ((String)joins.get(k)); + third.setMainTable((String)fromLookup.get(third.getMainAlias())); + third.setJoinTable((String)fromLookup.get(third.getJoinAlias())); + if (second.getJoinTable().equals(third.getMainTable())) + { + if (trace) + log.info("-Third-dep: " + third); + // FROM ((C_BPartner p LEFT OUTER JOIN AD_User c ON (p.C_BPartner_ID=c.C_BPartner_ID)) + // LEFT OUTER JOIN C_BPartner_Location l ON (p.C_BPartner_ID=l.C_BPartner_ID)) + // LEFT OUTER JOIN C_Location a ON (l.C_Location_ID=a.C_Location_ID) + newFrom.insert(6, '('); // _FROM ... + newFrom.append(')'); // add parantesis on previous relation + // + newFrom.append(third.isLeft() ? " LEFT" : " RIGHT").append(" OUTER JOIN ") + .append(third.getJoinTable()).append(" ").append(third.getJoinAlias()) + .append(" ON (").append(third.getCondition()); + joins.remove(k); // remove from join list + fromAlias.remove(third.getJoinAlias()); // remove from table list + // additional join colums would come here + newFrom.append(")"); // close ON + } + else if (trace) + log.info("-Third-skip: " + third); + } + } + else if (trace) + log.info("-Second/dep-skip: " + second); + } // dependency on first table + } + // remaining Tables + Iterator it = fromAlias.keySet().iterator(); + while (it.hasNext()) + { + Object alias = it.next(); + Object table = fromAlias.get(alias); + newFrom.append(", ").append(table); + if (!table.equals(alias)) + newFrom.append(" ").append(alias); + } + if (trace) + log.info(newFrom.toString()); + // + StringBuffer retValue = new StringBuffer (sqlStatement.length()+20); + retValue.append(selectPart) + .append(newFrom).append(" ") + .append(newWherePart).append(rest); + // + if (trace) + log.info("OuterJoin==> " + retValue.toString()); + return retValue.toString(); + } // convertOuterJoin + + /************************************************************************** + * Converts Decode. + *
+	 *      DECODE (a, 1, 'one', 2, 'two', 'none')
+	 *       => CASE WHEN a = 1 THEN 'one' WHEN a = 2 THEN 'two' ELSE 'none' END
+	 *  
+ * @param sqlStatement + * @return converted statement + */ + protected String convertDecode(String sqlStatement) + { + // log.info("DECODE<== " + sqlStatement); + String statement = sqlStatement; + StringBuffer sb = new StringBuffer("CASE"); + + int index = statement.indexOf("DECODE"); + String firstPart = statement.substring(0,index); + + // find the opening ( + index = statement.indexOf('(', index); + statement = statement.substring(index+1); + + // find the expression "a" - find first , ignoring () + index = Util.findIndexOf (statement, ','); + String expression = statement.substring(0, index).trim(); + // log.info("Expression=" + expression); + + // Pairs "1, 'one'," + statement = statement.substring(index+1); + index = Util.findIndexOf (statement, ','); + while (index != -1) + { + String first = statement.substring(0, index); + char cc = statement.charAt(index); + statement = statement.substring(index+1); + // log.info("First=" + first + ", Char=" + cc); + // + boolean error = false; + if (cc == ',') + { + index = Util.findIndexOf (statement, ',',')'); + if (index == -1) + error = true; + else + { + String second = statement.substring(0, index); + sb.append(" WHEN ").append(expression).append("=").append(first.trim()) + .append(" THEN ").append(second.trim()); + // log.info(">>" + sb.toString()); + statement = statement.substring(index+1); + index = Util.findIndexOf (statement, ',',')'); + } + } + else if (cc == ')') + { + sb.append(" ELSE ").append(first.trim()).append(" END"); + // log.info(">>" + sb.toString()); + index = -1; + } + else + error = true; + if (error) + { + log.log(Level.SEVERE, "SQL=(" + sqlStatement + + ")\n====Result=(" + sb.toString() + + ")\n====Statement=(" + statement + + ")\n====First=(" + first + + ")\n====Index=" + index); + m_conversionError = "Decode conversion error"; + } + } + sb.append(statement); + sb.insert(0, firstPart); + // log.info("DECODE==> " + sb.toString()); + return sb.toString(); + } // convertDecode +} diff --git a/dbPort/src/org/compiere/util/DB.java b/dbPort/src/org/compiere/util/DB.java index 6290b65f45..98462706b9 100644 --- a/dbPort/src/org/compiere/util/DB.java +++ b/dbPort/src/org/compiere/util/DB.java @@ -47,7 +47,7 @@ public final class DB /** Connection Cache r/o */ private static Connection[] s_connections = null; /** Connection Cache Size */ - private static int s_conCacheSize = Ini.isClient() ? 3 : 3; + private static int s_conCacheSize = Ini.isClient() ? 1 : 3; /** Connection counter */ private static int s_conCount = 0; /** Connection r/w */ @@ -231,12 +231,28 @@ public final class DB s_cc = cc; s_connections = null; s_connectionRW = null; + s_connectionID = null; } s_cc.setDataSource(); log.config(s_cc + " - DS=" + s_cc.isDataSource()); // Trace.printStack(); } // setDBTarget + public static boolean connect() { + boolean success =false; + try + { + success = getConnectionRW() != null; + if (success) success = getConnectionRO() != null; + if (success) success = getConnectionID() != null; + s_cc.readInfo(getConnectionRW()); + } catch (Exception e) + { + success = false; + } + return success; + } + /** * Is there a connection to the database ? * @return true, if connected to database @@ -661,6 +677,20 @@ public final class DB log.log(Level.SEVERE, "R/W", e); } s_connectionRW = null; + + //ID Connection + try + { + if (s_connectionID != null) + { + s_connectionID.close(); + } + } catch (SQLException e) + { + log.log(Level.SEVERE, "Id", e); + } + s_connectionID = null; + // CConnection if (s_cc != null) {