1
16 package org.flywaydb.core.internal.jdbc;
17
18 import org.flywaydb.core.api.FlywayException;
19
20 import java.sql.Connection;
21 import java.sql.DatabaseMetaData;
22 import java.sql.PreparedStatement;
23 import java.sql.ResultSet;
24 import java.sql.SQLException;
25 import java.sql.Types;
26
27
30 @SuppressWarnings("SqlDialectInspection")
31 public enum DatabaseType {
32 COCKROACHDB("CockroachDB", Types.NULL, false),
33 DB2("DB2", Types.VARCHAR, true),
34
35
36
37 DERBY("Derby", Types.VARCHAR, true),
38 FIREBIRD("Firebird", Types.NULL, true),
39 H2("H2", Types.VARCHAR, true),
40 HSQLDB("HSQLDB", Types.VARCHAR, true),
41 INFORMIX("Informix", Types.VARCHAR, true),
42 MARIADB("MariaDB", Types.VARCHAR, true),
43 MYSQL("MySQL", Types.VARCHAR, true),
44 ORACLE("Oracle", Types.VARCHAR, true),
45 POSTGRESQL("PostgreSQL", Types.NULL, true),
46 REDSHIFT("Redshift", Types.VARCHAR, true),
47 SQLITE("SQLite", Types.VARCHAR, false),
48 SQLSERVER("SQL Server", Types.VARCHAR, true),
49 SYBASEASE_JTDS("Sybase ASE", Types.NULL, true),
50 SYBASEASE_JCONNECT("Sybase ASE", Types.VARCHAR, true),
51 SAPHANA("SAP HANA", Types.VARCHAR, true),
52 SNOWFLAKE("Snowflake", Types.VARCHAR, false);
53
54 private final String name;
55
56 private final int nullType;
57
58 private final boolean supportsReadOnlyTransactions;
59
60 DatabaseType(String name, int nullType, boolean supportsReadOnlyTransactions) {
61 this.name = name;
62 this.nullType = nullType;
63 this.supportsReadOnlyTransactions = supportsReadOnlyTransactions;
64 }
65
66 public static DatabaseType fromJdbcConnection(Connection connection) {
67 DatabaseMetaData databaseMetaData = JdbcUtils.getDatabaseMetaData(connection);
68 String databaseProductName = JdbcUtils.getDatabaseProductName(databaseMetaData);
69 String databaseProductVersion = JdbcUtils.getDatabaseProductVersion(databaseMetaData);
70
71 return fromDatabaseProductNameAndVersion(databaseProductName, databaseProductVersion, connection);
72 }
73
74 private static DatabaseType fromDatabaseProductNameAndVersion(String databaseProductName,
75 String databaseProductVersion,
76 Connection connection) {
77 if (databaseProductName.startsWith("Apache Derby")) {
78 return DERBY;
79 }
80 if (databaseProductName.startsWith("SQLite")) {
81 return SQLITE;
82 }
83 if (databaseProductName.startsWith("H2")) {
84 return H2;
85 }
86 if (databaseProductName.contains("HSQL Database Engine")) {
87 return HSQLDB;
88 }
89 if (databaseProductName.startsWith("Microsoft SQL Server")) {
90 return SQLSERVER;
91 }
92
93
94 if (databaseProductName.startsWith("MariaDB")
95
96 || (databaseProductName.contains("MySQL") && databaseProductVersion.contains("MariaDB"))
97
98 || (databaseProductName.contains("MySQL") && getSelectVersionOutput(connection).contains("MariaDB"))) {
99 return MARIADB;
100 }
101
102 if (databaseProductName.contains("MySQL")) {
103
104
105 return MYSQL;
106 }
107 if (databaseProductName.startsWith("Oracle")) {
108 return ORACLE;
109 }
110 if (databaseProductName.startsWith("PostgreSQL")) {
111 String selectVersionQueryOutput = getSelectVersionOutput(connection);
112 if (databaseProductName.startsWith("PostgreSQL 8") && selectVersionQueryOutput.contains("Redshift")) {
113 return REDSHIFT;
114 }
115 if (selectVersionQueryOutput.contains("CockroachDB")) {
116 return COCKROACHDB;
117 }
118 return POSTGRESQL;
119 }
120 if (databaseProductName.startsWith("DB2")) {
121
122
123
124
125
126 return DB2;
127 }
128 if (databaseProductName.startsWith("ASE")) {
129 return SYBASEASE_JTDS;
130 }
131 if (databaseProductName.startsWith("Adaptive Server Enterprise")) {
132 return SYBASEASE_JCONNECT;
133 }
134 if (databaseProductName.startsWith("HDB")) {
135 return SAPHANA;
136 }
137 if (databaseProductName.startsWith("Informix")) {
138 return INFORMIX;
139 }
140 if (databaseProductName.startsWith("Firebird")) {
141 return FIREBIRD;
142 }
143 if (databaseProductName.startsWith("Snowflake")) {
144 return SNOWFLAKE;
145 }
146 throw new FlywayException("Unsupported Database: " + databaseProductName);
147 }
148
149
156 public static String getSelectVersionOutput(Connection connection) {
157 PreparedStatement statement = null;
158 ResultSet resultSet = null;
159
160 String result;
161 try {
162 statement = connection.prepareStatement("SELECT version()");
163 resultSet = statement.executeQuery();
164 result = null;
165 if (resultSet.next()) {
166 result = resultSet.getString(1);
167 }
168 } catch (SQLException e) {
169 return "";
170 } finally {
171 JdbcUtils.closeResultSet(resultSet);
172 JdbcUtils.closeStatement(statement);
173 }
174
175 return result;
176 }
177
178
181 public String getName() {
182 return name;
183 }
184
185
188 public int getNullType() {
189 return nullType;
190 }
191
192 @Override
193 public String toString() {
194 return name;
195 }
196
197
198
199
200
201
202
203
204
205
206
207 }