@@ -7,17 +7,8 @@ import java.util.Locale
77
88private val logger = KotlinLogging .logger {}
99
10- private const val UNSUPPORTED_H2_MODE_MESSAGE =
11- " Unsupported H2 MODE: %s. Supported: MySQL, PostgreSQL, MSSQLServer, MariaDB, REGULAR/H2-Regular (or omit MODE)."
12-
13- private const val H2_MODE_QUERY = " SELECT SETTING_VALUE FROM INFORMATION_SCHEMA.SETTINGS WHERE SETTING_NAME = 'MODE'"
14-
15- private val H2_MODE_URL_PATTERN = " MODE=([^;:&]+)" .toRegex(RegexOption .IGNORE_CASE )
16-
1710/* *
1811 * Extracts the database type from the given connection.
19- * For H2, fetches the actual MODE from the active connection settings.
20- * For other databases, extracts type from URL.
2112 *
2213 * @param [connection] the database connection.
2314 * @return the corresponding [DbType].
@@ -30,81 +21,78 @@ public fun extractDBTypeFromConnection(connection: Connection): DbType {
3021 ? : throw IllegalStateException (" URL information is missing in connection meta data!" )
3122 logger.info { " Processing DB type extraction for connection url: $url " }
3223
33- // First, determine the base database type from URL
34- val baseDbType = extractDBTypeFromUrl(url)
35-
36- // For H2, refine the mode by querying the active connection settings
37- // This handles cases where MODE is not specified in URL, but H2 returns "Regular" from settings
38- return if (baseDbType is H2 ) {
39- val mode = fetchH2ModeFromConnection(connection)
40- parseH2ModeOrThrow(mode)
41- } else {
42- logger.info { " Identified DB type as $baseDbType from url: $url " }
43- baseDbType
44- }
45- }
46-
47- /* *
48- * Fetches H2 database mode from an active connection.
49- * Works only for H2 version 2.
50- *
51- * @param [connection] the database connection.
52- * @return the mode string or null if not set.
53- */
54- private fun fetchH2ModeFromConnection (connection : Connection ): String? {
55- var mode: String? = null
56- connection.prepareStatement(H2_MODE_QUERY ).use { st ->
57- st.executeQuery().use { rs ->
58- if (rs.next()) {
59- mode = rs.getString(" SETTING_VALUE" )
60- logger.debug { " Fetched H2 DB mode: $mode " }
24+ return if (url.contains(H2 ().dbTypeInJdbcUrl)) {
25+ // works only for H2 version 2
26+ val modeQuery = " SELECT SETTING_VALUE FROM INFORMATION_SCHEMA.SETTINGS WHERE SETTING_NAME = 'MODE'"
27+ var mode = " "
28+ connection.prepareStatement(modeQuery).use { st ->
29+ st.executeQuery().use { rs ->
30+ if (rs.next()) {
31+ mode = rs.getString(" SETTING_VALUE" )
32+ logger.debug { " Fetched H2 DB mode: $mode " }
33+ } else {
34+ throw IllegalStateException (" The information about H2 mode is not found in the H2 meta-data!" )
35+ }
6136 }
6237 }
63- }
6438
65- return mode?.trim()?.takeIf { it.isNotEmpty() }
66- }
39+ // H2 doesn't support MariaDB and SQLite
40+ when (mode.lowercase(Locale .getDefault())) {
41+ H2 .MODE_MYSQL .lowercase(Locale .getDefault()) -> H2 (MySql )
6742
68- /* *
69- * Parses H2 mode string and returns the corresponding H2 DbType instance.
70- *
71- * @param [mode] the mode string (maybe null or empty for Regular mode).
72- * @return H2 instance with the appropriate mode.
73- * @throws [IllegalArgumentException] if the mode is not supported.
74- */
75- private fun parseH2ModeOrThrow (mode : String? ): H2 {
76- if (mode.isNullOrEmpty()) {
77- return H2 (H2 .Mode .Regular )
78- }
79- return H2 .Mode .fromValue(mode)?.let { H2 (it) }
80- ? : throw IllegalArgumentException (UNSUPPORTED_H2_MODE_MESSAGE .format(mode)).also {
81- logger.error { it.message }
43+ H2 .MODE_MSSQLSERVER .lowercase(Locale .getDefault()) -> H2 (MsSql )
44+
45+ H2 .MODE_POSTGRESQL .lowercase(Locale .getDefault()) -> H2 (PostgreSql )
46+
47+ H2 .MODE_MARIADB .lowercase(Locale .getDefault()) -> H2 (MariaDb )
48+
49+ else -> {
50+ val message = " Unsupported database type in the url: $url . " +
51+ " Only MySQL, MariaDB, MSSQL and PostgreSQL are supported!"
52+ logger.error { message }
53+
54+ throw IllegalArgumentException (message)
55+ }
8256 }
57+ } else {
58+ val dbType = extractDBTypeFromUrl(url)
59+ logger.info { " Identified DB type as $dbType from url: $url " }
60+ dbType
61+ }
8362}
8463
8564/* *
8665 * Extracts the database type from the given JDBC URL.
8766 *
8867 * @param [url] the JDBC URL.
8968 * @return the corresponding [DbType].
90- * @throws [SQLException] if the url is null.
91- * @throws [IllegalArgumentException] if the URL specifies an unsupported database type.
69+ * @throws [RuntimeException] if the url is null.
9270 */
9371public fun extractDBTypeFromUrl (url : String? ): DbType {
94- url ? : throw SQLException (" Database URL could not be null." )
95-
96- return when {
97- H2 ().dbTypeInJdbcUrl in url -> createH2Instance(url)
98- MariaDb .dbTypeInJdbcUrl in url -> MariaDb
99- MySql .dbTypeInJdbcUrl in url -> MySql
100- Sqlite .dbTypeInJdbcUrl in url -> Sqlite
101- PostgreSql .dbTypeInJdbcUrl in url -> PostgreSql
102- MsSql .dbTypeInJdbcUrl in url -> MsSql
103- DuckDb .dbTypeInJdbcUrl in url -> DuckDb
104- else -> throw IllegalArgumentException (
105- " Unsupported database type in the url: $url . " +
72+ if (url != null ) {
73+ val helperH2Instance = H2 ()
74+ return when {
75+ helperH2Instance.dbTypeInJdbcUrl in url -> createH2Instance(url)
76+
77+ MariaDb .dbTypeInJdbcUrl in url -> MariaDb
78+
79+ MySql .dbTypeInJdbcUrl in url -> MySql
80+
81+ Sqlite .dbTypeInJdbcUrl in url -> Sqlite
82+
83+ PostgreSql .dbTypeInJdbcUrl in url -> PostgreSql
84+
85+ MsSql .dbTypeInJdbcUrl in url -> MsSql
86+
87+ DuckDb .dbTypeInJdbcUrl in url -> DuckDb
88+
89+ else -> throw IllegalArgumentException (
90+ " Unsupported database type in the url: $url . " +
10691 " Only H2, MariaDB, MySQL, MSSQL, SQLite, PostgreSQL, and DuckDB are supported!" ,
107- )
92+ )
93+ }
94+ } else {
95+ throw SQLException (" Database URL could not be null. The existing value is $url " )
10896 }
10997}
11098
@@ -116,8 +104,30 @@ public fun extractDBTypeFromUrl(url: String?): DbType {
116104 * @throws [IllegalArgumentException] if the provided URL does not contain a valid mode.
117105 */
118106private fun createH2Instance (url : String ): DbType {
119- val mode = H2_MODE_URL_PATTERN .find(url)?.groupValues?.getOrNull(1 )
120- return parseH2ModeOrThrow(mode?.takeIf { it.isNotBlank() })
107+ val modePattern = " MODE=(.*?);" .toRegex()
108+ val matchResult = modePattern.find(url)
109+
110+ val mode: String = if (matchResult != null && matchResult.groupValues.size == 2 ) {
111+ matchResult.groupValues[1 ]
112+ } else {
113+ throw IllegalArgumentException (" The provided URL `$url ` does not contain a valid mode." )
114+ }
115+
116+ // H2 doesn't support MariaDB and SQLite
117+ return when (mode.lowercase(Locale .getDefault())) {
118+ H2 .MODE_MYSQL .lowercase(Locale .getDefault()) -> H2 (MySql )
119+
120+ H2 .MODE_MSSQLSERVER .lowercase(Locale .getDefault()) -> H2 (MsSql )
121+
122+ H2 .MODE_POSTGRESQL .lowercase(Locale .getDefault()) -> H2 (PostgreSql )
123+
124+ H2 .MODE_MARIADB .lowercase(Locale .getDefault()) -> H2 (MariaDb )
125+
126+ else -> throw IllegalArgumentException (
127+ " Unsupported database mode: $mode . " +
128+ " Only MySQL, MariaDB, MSSQL, PostgreSQL modes are supported!" ,
129+ )
130+ }
121131}
122132
123133/* *
0 commit comments