Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
babyfish-ct committed Dec 2, 2024
1 parent bf86e3e commit a641c25
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ protected JSqlClient.Builder createBuilder() {
DatabaseNamingStrategy databaseNamingStrategy = getOptionalBean(DatabaseNamingStrategy.class);
MetaStringResolver metaStringResolver = getOptionalBean(MetaStringResolver.class);
Dialect dialect = getOptionalBean(Dialect.class);
DialectDetector dialectDetector = getOptionalBean(DialectDetector.class);
Executor executor = getOptionalBean(Executor.class);
SqlFormatter sqlFormatter = getOptionalBean(SqlFormatter.class);
CacheFactory cacheFactory = getOptionalBean(CacheFactory.class);
Expand Down Expand Up @@ -205,11 +206,14 @@ protected JSqlClient.Builder createBuilder() {
builder.setConnectionManager(connectionManager);

if (((JSqlClientImplementor.Builder) builder).getDialect().getClass() == DefaultDialect.class) {
DialectDetector finalDetector = dialectDetector != null ?
dialectDetector :
DialectDetector.INSTANCE;
builder.setDialect(
optionalFirstNonNullOf(
() -> dialect,
properties::getDialect,
() -> connectionManager.execute(DialectDetector::detectDialect)
() -> connectionManager.execute(finalDetector::detectDialect)
)
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,60 +15,79 @@
import java.sql.DatabaseMetaData;
import java.sql.SQLException;

public class DialectDetector {

private static final Logger LOGGER = LoggerFactory.getLogger(DialectDetector.class);
/**
* When dialect is not specified explicitly,
* the default instance {@link #INSTANCE} of
* this interface will be used to guess dialect
* by JDBC connection.
*
* <p>You can define your customized
* `DialectDetector` and register it into
* spring context to override the default
* dialect guessing behavior.</p>
*/
public interface DialectDetector {

@Nullable
public static Dialect detectDialect(@NotNull Connection con) {
try {
String productName = JdbcUtils.commonDatabaseName(
extractDatabaseMetaData(con, DatabaseMetaData::getDatabaseProductName));
DatabaseDriver driver = DatabaseDriver.fromProductName(productName);
return getDialectOrNullForDriver(driver);
} catch (MetaDataAccessException e) {
LOGGER.warn("Failed to autodetect jimmer dialect", e);
return null;
Dialect detectDialect(@NotNull Connection con);

DialectDetector INSTANCE = new Impl();

class Impl implements DialectDetector {

private static final Logger LOGGER = LoggerFactory.getLogger(DialectDetector.class);

@Nullable
@Override
public Dialect detectDialect(@NotNull Connection con) {
try {
String productName = JdbcUtils.commonDatabaseName(
extractDatabaseMetaData(con, DatabaseMetaData::getDatabaseProductName));
DatabaseDriver driver = DatabaseDriver.fromProductName(productName);
return getDialectOrNullForDriver(driver);
} catch (MetaDataAccessException e) {
LOGGER.warn("Failed to autodetect jimmer dialect", e);
return null;
}
}
}

@Nullable
private static <T> T extractDatabaseMetaData(
@NotNull Connection con,
@NotNull DatabaseMetaDataCallback<T> action
) throws MetaDataAccessException {
try {
DatabaseMetaData metaData = con.getMetaData();
if (metaData == null) {
// should only happen in test environments
throw new MetaDataAccessException("DatabaseMetaData returned by Connection [" + con + "] was null");
private static <T> T extractDatabaseMetaData(
@NotNull Connection con,
@NotNull DatabaseMetaDataCallback<T> action
) throws MetaDataAccessException {
try {
DatabaseMetaData metaData = con.getMetaData();
if (metaData == null) {
// should only happen in test environments
throw new MetaDataAccessException("DatabaseMetaData returned by Connection [" + con + "] was null");
}
return action.processMetaData(metaData);
} catch (CannotGetJdbcConnectionException ex) {
throw new MetaDataAccessException("Could not get Connection for extracting meta-data", ex);
} catch (SQLException ex) {
throw new MetaDataAccessException("Error while extracting DatabaseMetaData", ex);
} catch (AbstractMethodError err) {
throw new MetaDataAccessException(
"JDBC DatabaseMetaData method not implemented by JDBC driver - upgrade your driver", err);
}
return action.processMetaData(metaData);
} catch (CannotGetJdbcConnectionException ex) {
throw new MetaDataAccessException("Could not get Connection for extracting meta-data", ex);
} catch (SQLException ex) {
throw new MetaDataAccessException("Error while extracting DatabaseMetaData", ex);
} catch (AbstractMethodError err) {
throw new MetaDataAccessException(
"JDBC DatabaseMetaData method not implemented by JDBC driver - upgrade your driver", err);
}
}

@Nullable
private static Dialect getDialectOrNullForDriver(@NotNull DatabaseDriver driver) {
switch (driver) {
case POSTGRESQL:
return new PostgresDialect();
case ORACLE:
return new OracleDialect();
case MYSQL:
return new MySqlDialect();
case SQLSERVER:
return new SqlServerDialect();
case H2:
return new H2Dialect();
default:
return null;
@Nullable
private static Dialect getDialectOrNullForDriver(@NotNull DatabaseDriver driver) {
switch (driver) {
case POSTGRESQL:
return new PostgresDialect();
case ORACLE:
return new OracleDialect();
case MYSQL:
return new MySqlDialect();
case SQLSERVER:
return new SqlServerDialect();
case H2:
return new H2Dialect();
default:
return null;
}
}
}
}
}

0 comments on commit a641c25

Please sign in to comment.