// Path: src/main/java/com/elong/pb/newdda/client/constants/DatabaseType.java
// public enum DatabaseType {
// 
//     H2, MySQL, Oracle, SQLServer, DB2;
// 
//     public static DatabaseType valueFrom(final String databaseName) {
//         try {
//             return DatabaseType.valueOf(databaseName);
//         } catch (final IllegalArgumentException ex) {
//             throw new DatabaseTypeUnsupportedException(databaseName);
//         }
//     }
// 
// }
// 
// Path: src/main/java/com/elong/pb/newdda/client/exception/SqlParserException.java
// public class SqlParserException extends ShardingJdbcException {
// 
//     private static final long serialVersionUID = -1498980479829506655L;
// 
//     public SqlParserException(final String message, final Object... args) {
//         super(String.format(message, args));
//     }
// 
// }
// 
// Path: src/main/java/com/elong/pb/newdda/client/router/parser/visitor/VisitorLogProxy.java
// public final class VisitorLogProxy {
// 
//     private final static Logger logger = LoggerFactory.getLogger(VisitorLogProxy.class);
// 
//     public static <T> T enhance(final Class<T> target) {
//         try {
//             return target.newInstance();
//         } catch (InstantiationException ex) {
//             logger.error("create Visitor exception: {}", ex);
//             throw new ShardingJdbcException(ex);
//         } catch (IllegalAccessException e) {
//             logger.error("create Visitor exception: {}", e);
//             throw new ShardingJdbcException(e);
//         }
//     }
// 
// }


import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement;
import com.alibaba.druid.sql.ast.statement.SQLInsertStatement;
import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement;
import com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;
import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser;
import com.alibaba.druid.sql.dialect.sqlserver.parser.SQLServerStatementParser;
import com.alibaba.druid.sql.parser.SQLStatementParser;
import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;
import com.elong.pb.newdda.client.constants.DatabaseType;
import com.elong.pb.newdda.client.exception.SqlParserException;
import com.elong.pb.newdda.client.router.parser.visitor.VisitorLogProxy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
    public static SqlParserEngine createParserEngine(final DatabaseType databaseType, final String sql, final List<Object> parameters) throws SqlParserException {
        if (logger.isDebugEnabled()) {
            logger.debug("Logic SQL: {}", sql);
        }
        SQLStatementParser sqlStatementParser = getSQLStatementParser(databaseType, sql);
        SQLStatement sqlStatement = sqlStatementParser.parseStatement();
        if (logger.isDebugEnabled()) {
            logger.debug("Get {} SQL Statement", sqlStatement.getClass().getName());
        }
        SQLASTOutputVisitor sqlastOutputVisitor = getSQLVisitor(databaseType, sqlStatement);
        SqlParserEngine sqlParserEngine = new SqlParserEngine(sqlStatement, parameters, sqlastOutputVisitor);
        return sqlParserEngine;
    }

    private static SQLStatementParser getSQLStatementParser(final DatabaseType databaseType, final String sql) {
        switch (databaseType) {
            case H2:
            case MySQL:
                return new MySqlStatementParser(sql);
            case Oracle:
                return new OracleStatementParser(sql);
            case SQLServer:
                return new SQLServerStatementParser(sql);
            case DB2:
                return new DB2StatementParser(sql);
            default:
                throw new UnsupportedOperationException(String.format("Cannot support database type [%s]", databaseType));
        }
    }

// Path: src/main/java/com/elong/pb/newdda/client/constants/DatabaseType.java
// public enum DatabaseType {
// 
//     H2, MySQL, Oracle, SQLServer, DB2;
// 
//     public static DatabaseType valueFrom(final String databaseName) {
//         try {
//             return DatabaseType.valueOf(databaseName);
//         } catch (final IllegalArgumentException ex) {
//             throw new DatabaseTypeUnsupportedException(databaseName);
//         }
//     }
// 
// }
// 
// Path: src/main/java/com/elong/pb/newdda/client/exception/SqlParserException.java
// public class SqlParserException extends ShardingJdbcException {
// 
//     private static final long serialVersionUID = -1498980479829506655L;
// 
//     public SqlParserException(final String message, final Object... args) {
//         super(String.format(message, args));
//     }
// 
// }
// 
// Path: src/main/java/com/elong/pb/newdda/client/router/parser/visitor/VisitorLogProxy.java
// public final class VisitorLogProxy {
// 
//     private final static Logger logger = LoggerFactory.getLogger(VisitorLogProxy.class);
// 
//     public static <T> T enhance(final Class<T> target) {
//         try {
//             return target.newInstance();
//         } catch (InstantiationException ex) {
//             logger.error("create Visitor exception: {}", ex);
//             throw new ShardingJdbcException(ex);
//         } catch (IllegalAccessException e) {
//             logger.error("create Visitor exception: {}", e);
//             throw new ShardingJdbcException(e);
//         }
//     }
// 
// }


// Path: src/main/java/com/elong/pb/newdda/client/router/parser/SqlParserFactory.java
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement;
import com.alibaba.druid.sql.ast.statement.SQLInsertStatement;
import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement;
import com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;
import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser;
import com.alibaba.druid.sql.dialect.sqlserver.parser.SQLServerStatementParser;
import com.alibaba.druid.sql.parser.SQLStatementParser;
import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;
import com.elong.pb.newdda.client.constants.DatabaseType;
import com.elong.pb.newdda.client.exception.SqlParserException;
import com.elong.pb.newdda.client.router.parser.visitor.VisitorLogProxy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;

    public static SqlParserEngine createParserEngine(final DatabaseType databaseType, final String sql, final List<Object> parameters) throws SqlParserException {
        if (logger.isDebugEnabled()) {
            logger.debug("Logic SQL: {}", sql);
        }
        SQLStatementParser sqlStatementParser = getSQLStatementParser(databaseType, sql);
        SQLStatement sqlStatement = sqlStatementParser.parseStatement();
        if (logger.isDebugEnabled()) {
            logger.debug("Get {} SQL Statement", sqlStatement.getClass().getName());
        }
        SQLASTOutputVisitor sqlastOutputVisitor = getSQLVisitor(databaseType, sqlStatement);
        SqlParserEngine sqlParserEngine = new SqlParserEngine(sqlStatement, parameters, sqlastOutputVisitor);
        return sqlParserEngine;
    }

    private static SQLStatementParser getSQLStatementParser(final DatabaseType databaseType, final String sql) {
        switch (databaseType) {
            case H2:
            case MySQL:
                return new MySqlStatementParser(sql);
            case Oracle:
                return new OracleStatementParser(sql);
            case SQLServer:
                return new SQLServerStatementParser(sql);
            case DB2:
                return new DB2StatementParser(sql);
            default:
                throw new UnsupportedOperationException(String.format("Cannot support database type [%s]", databaseType));
        }
    }

    private static SQLASTOutputVisitor getSQLVisitor(final DatabaseType databaseType, final SQLStatement sqlStatement) {