@Override
  protected Dialect resolveDialectInternal(DatabaseMetaData metaData) throws SQLException {
    String databaseName = metaData.getDatabaseProductName();
    int databaseMajorVersion = metaData.getDatabaseMajorVersion();

    if ("CUBRID".equalsIgnoreCase(databaseName)) {
      return new CUBRIDDialect();
    }

    if ("HSQL Database Engine".equals(databaseName)) {
      return new HSQLDialect();
    }

    if ("H2".equals(databaseName)) {
      return new H2Dialect();
    }

    if ("MySQL".equals(databaseName)) {
      return new MySQLDialect();
    }

    if ("PostgreSQL".equals(databaseName)) {
      final int databaseMinorVersion = metaData.getDatabaseMinorVersion();
      if (databaseMajorVersion >= 8 && databaseMinorVersion >= 2) {
        return new PostgreSQL82Dialect();
      }
      return new PostgreSQL81Dialect();
    }

    if ("Apache Derby".equals(databaseName)) {
      final int databaseMinorVersion = metaData.getDatabaseMinorVersion();
      if (databaseMajorVersion > 10 || (databaseMajorVersion == 10 && databaseMinorVersion >= 7)) {
        return new DerbyTenSevenDialect();
      } else if (databaseMajorVersion == 10 && databaseMinorVersion == 6) {
        return new DerbyTenSixDialect();
      } else if (databaseMajorVersion == 10 && databaseMinorVersion == 5) {
        return new DerbyTenFiveDialect();
      } else {
        return new DerbyDialect();
      }
    }

    if ("ingres".equalsIgnoreCase(databaseName)) {
      switch (databaseMajorVersion) {
        case 9:
          int databaseMinorVersion = metaData.getDatabaseMinorVersion();
          if (databaseMinorVersion > 2) {
            return new Ingres9Dialect();
          }
          return new IngresDialect();
        case 10:
          return new Ingres10Dialect();
        default:
          LOG.unknownIngresVersion(databaseMajorVersion);
      }
      return new IngresDialect();
    }

    if (databaseName.startsWith("Microsoft SQL Server")) {
      switch (databaseMajorVersion) {
        case 8:
          return new SQLServerDialect();
        case 9:
          return new SQLServer2005Dialect();
        case 10:
          return new SQLServer2008Dialect();
        default:
          LOG.unknownSqlServerVersion(databaseMajorVersion);
      }
      return new SQLServerDialect();
    }

    if ("Sybase SQL Server".equals(databaseName)
        || "Adaptive Server Enterprise".equals(databaseName)) {
      return new SybaseASE15Dialect();
    }

    if (databaseName.startsWith("Adaptive Server Anywhere")) {
      return new SybaseAnywhereDialect();
    }

    if ("Informix Dynamic Server".equals(databaseName)) {
      return new InformixDialect();
    }

    if (databaseName.equals("DB2 UDB for AS/400")) {
      return new DB2400Dialect();
    }

    if (databaseName.startsWith("DB2/")) {
      return new DB2Dialect();
    }

    if ("Oracle".equals(databaseName)) {
      switch (databaseMajorVersion) {
        case 11:
          return new Oracle10gDialect();
        case 10:
          return new Oracle10gDialect();
        case 9:
          return new Oracle9iDialect();
        case 8:
          return new Oracle8iDialect();
        default:
          LOG.unknownOracleVersion(databaseMajorVersion);
      }
    }

    return null;
  }