package com.chenyang.druid.util;

import com.chenyang.druid.DbType;
import com.chenyang.druid.sql.SQLUtils;
import com.chenyang.druid.sql.ast.statement.SQLCreateTableStatement;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.nio.charset.Charset;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.sql.Statement;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.TimeZone;
import javax.sql.XAConnection;

public class MySqlUtils {
   static Class<?> utilClass;
   static boolean utilClassError = false;
   static boolean utilClass_isJdbc4 = false;
   static Class<?> class_5_connection = null;
   static Method method_5_getPinGlobalTxToPhysicalConnection = null;
   static Class<?> class_5_suspendableXAConnection = null;
   static Constructor<?> constructor_5_suspendableXAConnection = null;
   static Class<?> class_5_JDBC4SuspendableXAConnection = null;
   static Constructor<?> constructor_5_JDBC4SuspendableXAConnection = null;
   static Class<?> class_5_MysqlXAConnection = null;
   static Constructor<?> constructor_5_MysqlXAConnection = null;
   static Class<?> class_ConnectionImpl = null;
   static Method method_getId = null;
   static boolean method_getId_error = false;
   static Class<?> class_6_ConnectionImpl = null;
   static Method method_6_getId = null;
   static volatile Class<?> class_6_connection = null;
   static volatile Method method_6_getPropertySet = null;
   static volatile Method method_6_getBooleanReadableProperty = null;
   static volatile Method method_6_getValue = null;
   static volatile boolean method_6_getValue_error = false;
   static volatile Class<?> class_6_suspendableXAConnection = null;
   static volatile Method method_6_getInstance = null;
   static volatile boolean method_6_getInstance_error = false;
   static volatile Method method_6_getInstanceXA = null;
   static volatile boolean method_6_getInstanceXA_error = false;
   static volatile Class<?> class_6_JDBC4SuspendableXAConnection = null;
   private static Set<String> keywords;
   private static Set<String> builtinDataTypes;
   private static transient Class class_connectionImpl = null;
   private static transient boolean class_connectionImpl_Error = false;
   private static transient Method method_getIO = null;
   private static transient boolean method_getIO_error = false;
   private static transient Class class_MysqlIO = null;
   private static transient boolean class_MysqlIO_Error = false;
   private static transient Method method_getLastPacketReceivedTimeMs = null;
   private static transient boolean method_getLastPacketReceivedTimeMs_error = false;
   private static volatile boolean mysqlJdbcVersion6 = false;
   private static transient Class classJdbc = null;
   private static transient Method getIdleFor = null;
   private static transient boolean getIdleForError = false;
   static Class<?> class_5_CommunicationsException = null;
   static Class<?> class_6_CommunicationsException = null;
   public static final Charset GBK = Charset.forName("GBK");
   public static final Charset BIG5 = Charset.forName("BIG5");
   public static final Charset UTF8 = Charset.forName("UTF-8");
   public static final Charset UTF16 = Charset.forName("UTF-16");
   public static final Charset UTF32 = Charset.forName("UTF-32");
   public static final Charset ASCII = Charset.forName("ASCII");
   private static BigInteger[] MAX_INT = new BigInteger[]{new BigInteger("9"), new BigInteger("99"), new BigInteger("999"), new BigInteger("9999"), new BigInteger("99999"), new BigInteger("999999"), new BigInteger("9999999"), new BigInteger("99999999"), new BigInteger("999999999"), new BigInteger("9999999999"), new BigInteger("99999999999"), new BigInteger("999999999999"), new BigInteger("9999999999999"), new BigInteger("99999999999999"), new BigInteger("999999999999999"), new BigInteger("9999999999999999"), new BigInteger("99999999999999999"), new BigInteger("999999999999999999"), new BigInteger("9999999999999999999"), new BigInteger("99999999999999999999"), new BigInteger("999999999999999999999"), new BigInteger("9999999999999999999999"), new BigInteger("99999999999999999999999"), new BigInteger("999999999999999999999999"), new BigInteger("9999999999999999999999999"), new BigInteger("99999999999999999999999999"), new BigInteger("999999999999999999999999999"), new BigInteger("9999999999999999999999999999"), new BigInteger("99999999999999999999999999999"), new BigInteger("999999999999999999999999999999"), new BigInteger("9999999999999999999999999999999"), new BigInteger("99999999999999999999999999999999"), new BigInteger("999999999999999999999999999999999"), new BigInteger("9999999999999999999999999999999999"), new BigInteger("99999999999999999999999999999999999"), new BigInteger("999999999999999999999999999999999999"), new BigInteger("9999999999999999999999999999999999999"), new BigInteger("99999999999999999999999999999999999999")};
   private static BigInteger[] MIN_INT = new BigInteger[]{new BigInteger("-9"), new BigInteger("-99"), new BigInteger("-999"), new BigInteger("-9999"), new BigInteger("-99999"), new BigInteger("-999999"), new BigInteger("-9999999"), new BigInteger("-99999999"), new BigInteger("-999999999"), new BigInteger("-9999999999"), new BigInteger("-99999999999"), new BigInteger("-999999999999"), new BigInteger("-9999999999999"), new BigInteger("-99999999999999"), new BigInteger("-999999999999999"), new BigInteger("-9999999999999999"), new BigInteger("-99999999999999999"), new BigInteger("-999999999999999999"), new BigInteger("-9999999999999999999"), new BigInteger("-99999999999999999999"), new BigInteger("-999999999999999999999"), new BigInteger("-9999999999999999999999"), new BigInteger("-99999999999999999999999"), new BigInteger("-999999999999999999999999"), new BigInteger("-9999999999999999999999999"), new BigInteger("-99999999999999999999999999"), new BigInteger("-999999999999999999999999999"), new BigInteger("-9999999999999999999999999999"), new BigInteger("-99999999999999999999999999999"), new BigInteger("-999999999999999999999999999999"), new BigInteger("-9999999999999999999999999999999"), new BigInteger("-99999999999999999999999999999999"), new BigInteger("-999999999999999999999999999999999"), new BigInteger("-9999999999999999999999999999999999"), new BigInteger("-99999999999999999999999999999999999"), new BigInteger("-999999999999999999999999999999999999"), new BigInteger("-9999999999999999999999999999999999999"), new BigInteger("-99999999999999999999999999999999999999")};
   private static BigDecimal[] MAX_DEC_1 = new BigDecimal[]{new BigDecimal("0.9"), new BigDecimal("9.9"), new BigDecimal("99.9"), new BigDecimal("999.9"), new BigDecimal("9999.9"), new BigDecimal("99999.9"), new BigDecimal("999999.9"), new BigDecimal("9999999.9"), new BigDecimal("99999999.9"), new BigDecimal("999999999.9"), new BigDecimal("9999999999.9"), new BigDecimal("99999999999.9"), new BigDecimal("999999999999.9"), new BigDecimal("9999999999999.9"), new BigDecimal("99999999999999.9"), new BigDecimal("999999999999999.9"), new BigDecimal("9999999999999999.9"), new BigDecimal("99999999999999999.9"), new BigDecimal("999999999999999999.9"), new BigDecimal("9999999999999999999.9"), new BigDecimal("99999999999999999999.9"), new BigDecimal("999999999999999999999.9"), new BigDecimal("9999999999999999999999.9"), new BigDecimal("99999999999999999999999.9"), new BigDecimal("999999999999999999999999.9"), new BigDecimal("9999999999999999999999999.9"), new BigDecimal("99999999999999999999999999.9"), new BigDecimal("999999999999999999999999999.9"), new BigDecimal("9999999999999999999999999999.9"), new BigDecimal("99999999999999999999999999999.9"), new BigDecimal("999999999999999999999999999999.9"), new BigDecimal("9999999999999999999999999999999.9"), new BigDecimal("99999999999999999999999999999999.9"), new BigDecimal("999999999999999999999999999999999.9"), new BigDecimal("9999999999999999999999999999999999.9"), new BigDecimal("99999999999999999999999999999999999.9"), new BigDecimal("999999999999999999999999999999999999.9"), new BigDecimal("9999999999999999999999999999999999999.9")};
   private static BigDecimal[] MIN_DEC_1 = new BigDecimal[]{new BigDecimal("-0.9"), new BigDecimal("-9.9"), new BigDecimal("-99.9"), new BigDecimal("-999.9"), new BigDecimal("-9999.9"), new BigDecimal("-99999.9"), new BigDecimal("-999999.9"), new BigDecimal("-9999999.9"), new BigDecimal("-99999999.9"), new BigDecimal("-999999999.9"), new BigDecimal("-9999999999.9"), new BigDecimal("-99999999999.9"), new BigDecimal("-999999999999.9"), new BigDecimal("-9999999999999.9"), new BigDecimal("-99999999999999.9"), new BigDecimal("-999999999999999.9"), new BigDecimal("-9999999999999999.9"), new BigDecimal("-99999999999999999.9"), new BigDecimal("-999999999999999999.9"), new BigDecimal("-9999999999999999999.9"), new BigDecimal("-99999999999999999999.9"), new BigDecimal("-999999999999999999999.9"), new BigDecimal("-9999999999999999999999.9"), new BigDecimal("-99999999999999999999999.9"), new BigDecimal("-999999999999999999999999.9"), new BigDecimal("-9999999999999999999999999.9"), new BigDecimal("-99999999999999999999999999.9"), new BigDecimal("-999999999999999999999999999.9"), new BigDecimal("-9999999999999999999999999999.9"), new BigDecimal("-99999999999999999999999999999.9"), new BigDecimal("-999999999999999999999999999999.9"), new BigDecimal("-9999999999999999999999999999999.9"), new BigDecimal("-99999999999999999999999999999999.9"), new BigDecimal("-999999999999999999999999999999999.9"), new BigDecimal("-9999999999999999999999999999999999.9"), new BigDecimal("-99999999999999999999999999999999999.9"), new BigDecimal("-999999999999999999999999999999999999.9"), new BigDecimal("-9999999999999999999999999999999999999.9")};
   private static BigDecimal[] MAX_DEC_2 = new BigDecimal[]{new BigDecimal("0.99"), new BigDecimal("9.99"), new BigDecimal("99.99"), new BigDecimal("999.99"), new BigDecimal("9999.99"), new BigDecimal("99999.99"), new BigDecimal("999999.99"), new BigDecimal("9999999.99"), new BigDecimal("99999999.99"), new BigDecimal("999999999.99"), new BigDecimal("9999999999.99"), new BigDecimal("99999999999.99"), new BigDecimal("999999999999.99"), new BigDecimal("9999999999999.99"), new BigDecimal("99999999999999.99"), new BigDecimal("999999999999999.99"), new BigDecimal("9999999999999999.99"), new BigDecimal("99999999999999999.99"), new BigDecimal("999999999999999999.99"), new BigDecimal("9999999999999999999.99"), new BigDecimal("99999999999999999999.99"), new BigDecimal("999999999999999999999.99"), new BigDecimal("9999999999999999999999.99"), new BigDecimal("99999999999999999999999.99"), new BigDecimal("999999999999999999999999.99"), new BigDecimal("9999999999999999999999999.99"), new BigDecimal("99999999999999999999999999.99"), new BigDecimal("999999999999999999999999999.99"), new BigDecimal("9999999999999999999999999999.99"), new BigDecimal("99999999999999999999999999999.99"), new BigDecimal("999999999999999999999999999999.99"), new BigDecimal("9999999999999999999999999999999.99"), new BigDecimal("99999999999999999999999999999999.99"), new BigDecimal("999999999999999999999999999999999.99"), new BigDecimal("9999999999999999999999999999999999.99"), new BigDecimal("99999999999999999999999999999999999.99"), new BigDecimal("999999999999999999999999999999999999.99"), new BigDecimal("9999999999999999999999999999999999999.99")};
   private static BigDecimal[] MIN_DEC_2 = new BigDecimal[]{new BigDecimal("-0.99"), new BigDecimal("-9.99"), new BigDecimal("-99.99"), new BigDecimal("-999.99"), new BigDecimal("-9999.99"), new BigDecimal("-99999.99"), new BigDecimal("-999999.99"), new BigDecimal("-9999999.99"), new BigDecimal("-99999999.99"), new BigDecimal("-999999999.99"), new BigDecimal("-9999999999.99"), new BigDecimal("-99999999999.99"), new BigDecimal("-999999999999.99"), new BigDecimal("-9999999999999.99"), new BigDecimal("-99999999999999.99"), new BigDecimal("-999999999999999.99"), new BigDecimal("-9999999999999999.99"), new BigDecimal("-99999999999999999.99"), new BigDecimal("-999999999999999999.99"), new BigDecimal("-9999999999999999999.99"), new BigDecimal("-99999999999999999999.99"), new BigDecimal("-999999999999999999999.99"), new BigDecimal("-9999999999999999999999.99"), new BigDecimal("-99999999999999999999999.99"), new BigDecimal("-999999999999999999999999.99"), new BigDecimal("-9999999999999999999999999.99"), new BigDecimal("-99999999999999999999999999.99"), new BigDecimal("-999999999999999999999999999.99"), new BigDecimal("-9999999999999999999999999999.99"), new BigDecimal("-99999999999999999999999999999.99"), new BigDecimal("-999999999999999999999999999999.99"), new BigDecimal("-9999999999999999999999999999999.99"), new BigDecimal("-99999999999999999999999999999999.99"), new BigDecimal("-999999999999999999999999999999999.99"), new BigDecimal("-9999999999999999999999999999999999.99"), new BigDecimal("-99999999999999999999999999999999999.99"), new BigDecimal("-999999999999999999999999999999999999.99"), new BigDecimal("-9999999999999999999999999999999999999.99")};
   private static final String[] parseFormats = new String[]{"HH:mm:ss", "yyyyMMdd", "yyyyMMddHHmmss", "yyyy-M-d", "yyyy-M-d H:m:s", "yyyy-M-d H:m:s.S", "yyyy-M-d'T'H:m:s", "yyyy-M-d'T'H:m:s.S", "yyyy-MM-d", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm:ss.SSS", "yyyy-MM-dd'T'HH:mm:ss", "yyyy-MM-dd'T'HH:mm:ss.SSS"};
   private static final long[] parseFormatCodes;

   public static XAConnection createXAConnection(Driver driver, Connection physicalConn) throws SQLException {
      int major = driver.getMajorVersion();
      if (major == 5) {
         if (utilClass == null && !utilClassError) {
            try {
               utilClass = Class.forName("com.mysql.jdbc.Util");
               Method method = utilClass.getMethod("isJdbc4");
               utilClass_isJdbc4 = (Boolean)method.invoke(null);
               class_5_connection = Class.forName("com.mysql.jdbc.Connection");
               method_5_getPinGlobalTxToPhysicalConnection = class_5_connection.getMethod("getPinGlobalTxToPhysicalConnection");
               class_5_suspendableXAConnection = Class.forName("com.mysql.jdbc.jdbc2.optional.SuspendableXAConnection");
               constructor_5_suspendableXAConnection = class_5_suspendableXAConnection.getConstructor(class_5_connection);
               class_5_JDBC4SuspendableXAConnection = Class.forName("com.mysql.jdbc.jdbc2.optional.JDBC4SuspendableXAConnection");
               constructor_5_JDBC4SuspendableXAConnection = class_5_JDBC4SuspendableXAConnection.getConstructor(class_5_connection);
               class_5_MysqlXAConnection = Class.forName("com.mysql.jdbc.jdbc2.optional.MysqlXAConnection");
               constructor_5_MysqlXAConnection = class_5_MysqlXAConnection.getConstructor(class_5_connection, Boolean.TYPE);
            } catch (Exception ex) {
               ex.printStackTrace();
               utilClassError = true;
            }
         }

         try {
            boolean pinGlobTx = (Boolean)method_5_getPinGlobalTxToPhysicalConnection.invoke(physicalConn);
            if (pinGlobTx) {
               if (!utilClass_isJdbc4) {
                  return (XAConnection)constructor_5_suspendableXAConnection.newInstance(physicalConn);
               }

               return (XAConnection)constructor_5_JDBC4SuspendableXAConnection.newInstance(physicalConn);
            }

            return (XAConnection)constructor_5_MysqlXAConnection.newInstance(physicalConn, Boolean.FALSE);
         } catch (Exception e) {
            e.printStackTrace();
         }
      } else if (major == 6 || major == 8) {
         if (method_6_getValue == null && !method_6_getValue_error) {
            try {
               class_6_connection = Class.forName("com.mysql.cj.api.jdbc.JdbcConnection");
            } catch (Throwable var11) {
            }

            try {
               if (class_6_connection == null) {
                  class_6_connection = Class.forName("com.mysql.cj.jdbc.JdbcConnection");
                  method_6_getPropertySet = class_6_connection.getMethod("getPropertySet");
                  Class<?> propertySetClass = Class.forName("com.mysql.cj.conf.PropertySet");
                  NoSuchMethodException noSuchMethodException = null;

                  try {
                     method_6_getBooleanReadableProperty = propertySetClass.getMethod("getBooleanReadableProperty", String.class);
                     method_6_getValue = Class.forName("com.mysql.cj.conf.ReadableProperty").getMethod("getValue");
                  } catch (NoSuchMethodException var9) {
                  }

                  if (method_6_getBooleanReadableProperty == null) {
                     method_6_getBooleanReadableProperty = propertySetClass.getMethod("getBooleanProperty", String.class);
                     method_6_getValue = Class.forName("com.mysql.cj.conf.RuntimeProperty").getMethod("getValue");
                  }
               } else {
                  method_6_getPropertySet = class_6_connection.getMethod("getPropertySet");
                  method_6_getBooleanReadableProperty = Class.forName("com.mysql.cj.api.conf.PropertySet").getMethod("getBooleanReadableProperty", String.class);
                  method_6_getValue = Class.forName("com.mysql.cj.api.conf.ReadableProperty").getMethod("getValue");
               }
            } catch (Exception ex) {
               ex.printStackTrace();
               method_6_getValue_error = true;
            }
         }

         try {
            Boolean pinGlobTx = (Boolean)method_6_getValue.invoke(method_6_getBooleanReadableProperty.invoke(method_6_getPropertySet.invoke(physicalConn), "pinGlobalTxToPhysicalConnection"));
            if (pinGlobTx != null && pinGlobTx) {
               try {
                  if (method_6_getInstance == null && !method_6_getInstance_error) {
                     class_6_suspendableXAConnection = Class.forName("com.mysql.cj.jdbc.SuspendableXAConnection");
                     method_6_getInstance = class_6_suspendableXAConnection.getDeclaredMethod("getInstance", class_6_connection);
                     method_6_getInstance.setAccessible(true);
                  }
               } catch (Throwable ex) {
                  ex.printStackTrace();
                  method_6_getInstance_error = true;
               }

               return (XAConnection)method_6_getInstance.invoke(null, physicalConn);
            }

            try {
               if (method_6_getInstanceXA == null && !method_6_getInstanceXA_error) {
                  class_6_JDBC4SuspendableXAConnection = Class.forName("com.mysql.cj.jdbc.MysqlXAConnection");
                  method_6_getInstanceXA = class_6_JDBC4SuspendableXAConnection.getDeclaredMethod("getInstance", class_6_connection, Boolean.TYPE);
                  method_6_getInstanceXA.setAccessible(true);
               }
            } catch (Throwable ex) {
               ex.printStackTrace();
               method_6_getInstanceXA_error = true;
            }

            return (XAConnection)method_6_getInstanceXA.invoke(null, physicalConn, Boolean.FALSE);
         } catch (InvocationTargetException e) {
            Throwable cause = e.getCause();
            if (cause instanceof RuntimeException) {
               throw (RuntimeException)cause;
            }
         } catch (Exception e) {
            e.printStackTrace();
            method_6_getInstance_error = true;
         }
      }

      throw new SQLFeatureNotSupportedException();
   }

   public static String buildKillQuerySql(Connection connection, SQLException error) throws SQLException {
      Long threadId = getId(connection);
      return threadId == null ? null : "KILL QUERY " + threadId;
   }

   public static boolean isKeyword(String name) {
      if (name == null) {
         return false;
      } else {
         String name_lower = name.toLowerCase();
         Set<String> words = keywords;
         if (words == null) {
            words = new HashSet();
            Utils.loadFromFile("META-INF/druid/parser/mysql/keywords", words);
            keywords = words;
         }

         return words.contains(name_lower);
      }
   }

   public static boolean isBuiltinDataType(String dataType) {
      if (dataType == null) {
         return false;
      } else {
         String table_lower = dataType.toLowerCase();
         Set<String> dataTypes = builtinDataTypes;
         if (dataTypes == null) {
            dataTypes = new HashSet();
            Utils.loadFromFile("META-INF/druid/parser/mysql/builtin_datatypes", dataTypes);
            builtinDataTypes = dataTypes;
         }

         return dataTypes.contains(table_lower);
      }
   }

   public static List<String> showTables(Connection conn) throws SQLException {
      List<String> tables = new ArrayList();
      Statement stmt = null;
      ResultSet rs = null;

      try {
         stmt = conn.createStatement();
         rs = stmt.executeQuery("show tables");

         while(rs.next()) {
            String tableName = rs.getString(1);
            tables.add(tableName);
         }
      } finally {
         JdbcUtils.close(rs);
         JdbcUtils.close(stmt);
      }

      return tables;
   }

   public static List<String> getTableDDL(Connection conn, List<String> tables) throws SQLException {
      List<String> ddlList = new ArrayList();
      Statement stmt = null;

      try {
         for(String table : tables) {
            if (stmt == null) {
               stmt = conn.createStatement();
            }

            if (isKeyword(table)) {
               table = "`" + table + "`";
            }

            ResultSet rs = null;

            try {
               rs = stmt.executeQuery("show create table " + table);
               if (rs.next()) {
                  String ddl = rs.getString(2);
                  ddlList.add(ddl);
               }
            } finally {
               JdbcUtils.close(rs);
            }
         }
      } finally {
         JdbcUtils.close(stmt);
      }

      return ddlList;
   }

   public static String getCreateTableScript(Connection conn) throws SQLException {
      return getCreateTableScript(conn, true, true);
   }

   public static String getCreateTableScript(Connection conn, boolean sorted, boolean simplify) throws SQLException {
      List<String> tables = showTables(conn);
      List<String> ddlList = getTableDDL(conn, tables);
      StringBuilder buf = new StringBuilder();

      for(String ddl : ddlList) {
         buf.append(ddl);
         buf.append(';');
      }

      String ddlScript = buf.toString();
      if (!sorted && !simplify) {
         return ddlScript;
      } else {
         List stmtList = SQLUtils.parseStatements(ddlScript, DbType.mysql);
         if (simplify) {
            for(Object o : stmtList) {
               if (o instanceof SQLCreateTableStatement) {
                  SQLCreateTableStatement createTableStmt = (SQLCreateTableStatement)o;
                  createTableStmt.simplify();
               }
            }
         }

         if (sorted) {
            SQLCreateTableStatement.sort(stmtList);
         }

         return SQLUtils.toSQLString(stmtList, DbType.mysql);
      }
   }

   public static Long getId(Object conn) {
      if (conn == null) {
         return null;
      } else {
         Class<?> clazz = conn.getClass();
         if (class_ConnectionImpl == null) {
            if (clazz.getName().equals("com.mysql.jdbc.ConnectionImpl")) {
               class_ConnectionImpl = clazz;
            } else if (clazz.getName().equals("com.mysql.jdbc.Connection")) {
               class_ConnectionImpl = clazz;
            } else if (clazz.getName().equals("com.mysql.cj.jdbc.ConnectionImpl")) {
               class_ConnectionImpl = clazz;
            } else if (clazz.getSuperclass().getName().equals("com.mysql.jdbc.ConnectionImpl")) {
               class_ConnectionImpl = clazz.getSuperclass();
            }
         }

         if (class_ConnectionImpl == clazz || class_ConnectionImpl == clazz.getSuperclass()) {
            try {
               if (method_getId == null && !method_getId_error) {
                  Method method = class_ConnectionImpl.getDeclaredMethod("getId");
                  method.setAccessible(true);
                  method_getId = method;
               }

               return (Long)method_getId.invoke(conn);
            } catch (Throwable var3) {
               method_getId_error = true;
            }
         }

         return null;
      }
   }

   public static long getLastPacketReceivedTimeMs(Connection conn) throws SQLException {
      if (class_connectionImpl == null && !class_connectionImpl_Error) {
         try {
            class_connectionImpl = Utils.loadClass("com.mysql.jdbc.MySQLConnection");
            if (class_connectionImpl == null) {
               class_connectionImpl = Utils.loadClass("com.mysql.cj.MysqlConnection");
               if (class_connectionImpl != null) {
                  mysqlJdbcVersion6 = true;
               }
            }
         } catch (Throwable var9) {
            class_connectionImpl_Error = true;
         }
      }

      if (class_connectionImpl == null) {
         return -1L;
      } else if (mysqlJdbcVersion6) {
         if (classJdbc == null) {
            classJdbc = Utils.loadClass("com.mysql.cj.jdbc.JdbcConnection");
         }

         if (classJdbc == null) {
            return -1L;
         } else {
            if (getIdleFor == null && !getIdleForError) {
               try {
                  getIdleFor = classJdbc.getMethod("getIdleFor");
                  getIdleFor.setAccessible(true);
               } catch (Throwable var4) {
                  getIdleForError = true;
               }
            }

            if (getIdleFor == null) {
               return -1L;
            } else {
               try {
                  Object connImpl = conn.unwrap(class_connectionImpl);
                  return connImpl == null ? -1L : System.currentTimeMillis() - (Long)getIdleFor.invoke(connImpl);
               } catch (Exception e) {
                  throw new SQLException("getIdleFor error", e);
               }
            }
         }
      } else {
         if (method_getIO == null && !method_getIO_error) {
            try {
               method_getIO = class_connectionImpl.getMethod("getIO");
            } catch (Throwable var8) {
               method_getIO_error = true;
            }
         }

         if (method_getIO == null) {
            return -1L;
         } else {
            if (class_MysqlIO == null && !class_MysqlIO_Error) {
               try {
                  class_MysqlIO = Utils.loadClass("com.mysql.jdbc.MysqlIO");
               } catch (Throwable var7) {
                  class_MysqlIO_Error = true;
               }
            }

            if (class_MysqlIO == null) {
               return -1L;
            } else {
               if (method_getLastPacketReceivedTimeMs == null && !method_getLastPacketReceivedTimeMs_error) {
                  try {
                     Method method = class_MysqlIO.getDeclaredMethod("getLastPacketReceivedTimeMs");
                     method.setAccessible(true);
                     method_getLastPacketReceivedTimeMs = method;
                  } catch (Throwable var6) {
                     method_getLastPacketReceivedTimeMs_error = true;
                  }
               }

               if (method_getLastPacketReceivedTimeMs == null) {
                  return -1L;
               } else {
                  try {
                     Object connImpl = conn.unwrap(class_connectionImpl);
                     if (connImpl == null) {
                        return -1L;
                     } else {
                        Object mysqlio = method_getIO.invoke(connImpl);
                        return (Long)method_getLastPacketReceivedTimeMs.invoke(mysqlio);
                     }
                  } catch (Exception e) {
                     throw new SQLException("getLastPacketReceivedTimeMs error", e);
                  }
               }
            }
         }
      }
   }

   public static Class getCommunicationsExceptionClass() {
      if (class_5_CommunicationsException != null) {
         return class_5_CommunicationsException;
      } else if (class_6_CommunicationsException != null) {
         return class_6_CommunicationsException;
      } else {
         class_5_CommunicationsException = Utils.loadClass("com.mysql.jdbc.CommunicationsException");
         if (class_5_CommunicationsException != null) {
            return class_5_CommunicationsException;
         } else {
            class_6_CommunicationsException = Utils.loadClass("com.mysql.cj.jdbc.exceptions.CommunicationsException");
            return class_6_CommunicationsException != null ? class_6_CommunicationsException : null;
         }
      }
   }

   public static void loadDataTypes(Set<String> dataTypes) {
      Utils.loadFromFile("META-INF/druid/parser/mysql/builtin_datatypes", dataTypes);
   }

   public static BigDecimal decimal(BigDecimal value, int precision, int scale) {
      int v_scale = value.scale();
      int v_precision;
      if (v_scale > scale) {
         value = value.setScale(scale, 4);
         v_precision = value.precision();
      } else {
         v_precision = value.precision();
      }

      int v_ints = v_precision - v_scale;
      int ints = precision - scale;
      if (v_precision <= precision && v_ints <= ints) {
         return value;
      } else {
         boolean sign = value.signum() > 0;
         if (scale == 1) {
            return sign ? MAX_DEC_1[ints] : MIN_DEC_1[ints];
         } else if (scale == 2) {
            return sign ? MAX_DEC_2[ints] : MIN_DEC_2[ints];
         } else {
            return new BigDecimal(sign ? MAX_INT[precision - 1] : MIN_INT[precision - 1], scale);
         }
      }
   }

   public static boolean isNumber(String str) {
      if (str != null && str.length() != 0) {
         char c0 = str.charAt(0);
         boolean dot = false;
         boolean expr = false;
         int i = 0;
         if (c0 == '+' || c0 == '-') {
            ++i;
         }

         for(; i < str.length(); ++i) {
            char ch = str.charAt(i);
            if (ch == '.') {
               if (dot || expr) {
                  return false;
               }

               dot = true;
            } else if (ch != 'e' && ch != 'E') {
               if (ch < '0' || ch > '9') {
                  return false;
               }
            } else {
               if (expr) {
                  return false;
               }

               expr = true;
               if (i >= str.length() - 1) {
                  return false;
               }

               char next = str.charAt(i + 1);
               if (next == '+' || next == '-') {
                  ++i;
               }
            }
         }

         return true;
      } else {
         return false;
      }
   }

   public static DateFormat toJavaFormat(String fmt, TimeZone timeZone) {
      DateFormat dateFormat = toJavaFormat(fmt);
      if (dateFormat == null) {
         return null;
      } else {
         if (timeZone != null) {
            dateFormat.setTimeZone(timeZone);
         }

         return dateFormat;
      }
   }

   public static DateFormat toJavaFormat(String fmt) {
      if (fmt == null) {
         return null;
      } else {
         StringBuffer buf = new StringBuffer();
         int i = 0;

         for(int len = fmt.length(); i < len; ++i) {
            char ch = fmt.charAt(i);
            if (ch == '%') {
               if (i + 1 == len) {
                  return null;
               }

               ++i;
               char next_ch = fmt.charAt(i);
               switch (next_ch) {
                  case 'H':
                  case 'k':
                     buf.append("HH");
                     break;
                  case 'I':
                  case 'h':
                  case 'l':
                     buf.append("hh");
                     break;
                  case 'J':
                  case 'K':
                  case 'L':
                  case 'N':
                  case 'O':
                  case 'P':
                  case 'Q':
                  case 'R':
                  case 'U':
                  case 'V':
                  case 'X':
                  case 'Z':
                  case '[':
                  case '\\':
                  case ']':
                  case '^':
                  case '_':
                  case '`':
                  case 'g':
                  case 'j':
                  case 'n':
                  case 'o':
                  case 'q':
                  case 't':
                  case 'u':
                  case 'v':
                  case 'x':
                  default:
                     return null;
                  case 'M':
                     buf.append("MMMMM");
                     break;
                  case 'S':
                  case 's':
                     buf.append("ss");
                     break;
                  case 'T':
                     buf.append("HH:mm:ss");
                     break;
                  case 'W':
                     buf.append("EEEEE");
                     break;
                  case 'Y':
                     buf.append("yyyy");
                     break;
                  case 'a':
                     buf.append("EEE");
                     break;
                  case 'b':
                     buf.append("MMM");
                     break;
                  case 'c':
                     buf.append("M");
                     break;
                  case 'd':
                     buf.append("dd");
                     break;
                  case 'e':
                     buf.append("d");
                     break;
                  case 'f':
                     buf.append("SSS000");
                     break;
                  case 'i':
                     buf.append("mm");
                     break;
                  case 'm':
                     buf.append("MM");
                     break;
                  case 'p':
                     buf.append('a');
                     break;
                  case 'r':
                     buf.append("hh:mm:ss a");
                     break;
                  case 'w':
                     buf.append("u");
                     break;
                  case 'y':
                     buf.append("yy");
               }
            } else {
               buf.append(ch);
            }
         }

         try {
            return new SimpleDateFormat(buf.toString(), Locale.ENGLISH);
         } catch (IllegalArgumentException var6) {
            return null;
         }
      }
   }

   public static Date parseDate(String str, TimeZone timeZone) {
      if (str == null) {
         return null;
      } else {
         int length = str.length();
         if (length < 8) {
            return null;
         } else {
            Date date = null;

            try {
               switch (length) {
                  case 10:
                     SimpleDateFormat sdf10 = new SimpleDateFormat("yyyy-MM-dd");
                     sdf10.setTimeZone(timeZone);
                     date = sdf10.parse(str);
                     break;
                  case 16:
                     SimpleDateFormat sdf16 = new SimpleDateFormat("yyyy-MM-dd HH:mm");
                     sdf16.setTimeZone(timeZone);
                     date = sdf16.parse(str);
                     break;
                  case 19:
                     SimpleDateFormat sdf19 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                     sdf19.setTimeZone(timeZone);
                     date = sdf19.parse(str);
                     break;
                  default:
                     date = new Date(str);
               }

               return date;
            } catch (ParseException e) {
               e.printStackTrace();
               return date;
            } finally {
               ;
            }
         }
      }
   }

   public static boolean isSupportParseDateformat(String str) {
      if (str == null) {
         return false;
      } else {
         return Arrays.binarySearch(parseFormatCodes, FnvHash.fnv1a_64(str)) >= 0;
      }
   }

   public static TimeZone parseTimeZone(String str) {
      return "SYSTEM".equalsIgnoreCase(str) ? TimeZone.getDefault() : TimeZone.getTimeZone(str);
   }

   public static String utf32(String hex) {
      byte[] bytes = HexBin.decode(hex);
      return bytes.length == 2 ? new String(bytes, UTF16) : new String(bytes, UTF32);
   }

   public static String utf16(String hex) {
      if (hex.length() % 2 == 1) {
         char[] chars = new char[hex.length() + 1];
         chars[0] = '0';
         hex.getChars(0, hex.length(), chars, 1);
         hex = new String(chars);
      }

      byte[] bytes = HexBin.decode(hex);
      return bytes == null ? null : new String(bytes, UTF16);
   }

   public static String utf8(String hex) {
      byte[] bytes = HexBin.decode(hex);
      return new String(bytes, UTF8);
   }

   public static String gbk(String hex) {
      byte[] bytes = HexBin.decode(hex);
      return new String(bytes, GBK);
   }

   public static String big5(String hex) {
      byte[] bytes = HexBin.decode(hex);
      return new String(bytes, BIG5);
   }

   static {
      long[] codes = new long[parseFormats.length];

      for(int i = 0; i < parseFormats.length; ++i) {
         codes[i] = FnvHash.fnv1a_64(parseFormats[i]);
      }

      Arrays.sort(codes);
      parseFormatCodes = codes;
   }
}
