1 /*
2 * Prometheus: Application Framework
3 * Copyright 2012-2026. Tony Washer
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6 * use this file except in compliance with the License. You may obtain a copy
7 * of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 * License for the specific language governing permissions and limitations under
15 * the License.
16 */
17 package io.github.tonywasher.joceanus.prometheus.database;
18
19 import io.github.tonywasher.joceanus.prometheus.preference.PrometheusColumnType;
20
21 /**
22 * Database Drivers. Also code that encapsulates differences between databases.
23 */
24 public enum PrometheusJDBCDriver {
25 /**
26 * SQLServer.
27 */
28 SQLSERVER,
29
30 /**
31 * PostgreSQL.
32 */
33 POSTGRESQL,
34
35 /**
36 * MySQL.
37 */
38 MYSQL,
39
40 /**
41 * MariaDB.
42 */
43 MARIADB,
44
45 /**
46 * H2.
47 */
48 H2;
49
50 /**
51 * Buffer length.
52 */
53 private static final int BUFFER_LEN = 100;
54
55 /**
56 * DefaultPort for MariaDB/MySQL.
57 */
58 static final int PORT_MARIADB = 3306;
59
60 /**
61 * DefaultPort for PostgreSQL.
62 */
63 static final int PORT_POSTGRESQL = 5432;
64
65 /**
66 * DefaultPort for SQLExpress.
67 */
68 static final int PORT_SQLEXPRESS = 50843;
69
70 /**
71 * DefaultInstance for SQLExpress.
72 */
73 static final String INSTANCE_SQLEXPRESS = "SQLEXPRESS";
74
75 /**
76 * The String name.
77 */
78 private String theName;
79
80 @Override
81 public String toString() {
82 /* If we have not yet loaded the name */
83 if (theName == null) {
84 /* Load the name */
85 theName = PrometheusDBResource.getKeyForDriver(this).getValue();
86 }
87
88 /* return the name */
89 return theName;
90 }
91
92 /**
93 * Determine whether we use instance.
94 *
95 * @return true/false
96 */
97 public boolean useInstance() {
98 switch (this) {
99 case SQLSERVER:
100 return true;
101 case MYSQL:
102 case MARIADB:
103 case H2:
104 case POSTGRESQL:
105 default:
106 return false;
107 }
108 }
109
110 /**
111 * Determine whether we use quotes.
112 *
113 * @return true/false
114 */
115 public boolean useQuotes() {
116 switch (this) {
117 case MYSQL:
118 case MARIADB:
119 return false;
120 case SQLSERVER:
121 case H2:
122 case POSTGRESQL:
123 default:
124 return true;
125 }
126 }
127
128 /**
129 * Determine whether we use port.
130 *
131 * @return true/false
132 */
133 public boolean usePort() {
134 switch (this) {
135 case MYSQL:
136 case MARIADB:
137 case POSTGRESQL:
138 case SQLSERVER:
139 return true;
140 case H2:
141 default:
142 return false;
143 }
144 }
145
146 /**
147 * Obtain default port.
148 *
149 * @return the default port
150 */
151 public Integer getDefaultPort() {
152 switch (this) {
153 case MYSQL:
154 case MARIADB:
155 return PORT_MARIADB;
156 case POSTGRESQL:
157 return PORT_POSTGRESQL;
158 case SQLSERVER:
159 return PORT_SQLEXPRESS;
160 case H2:
161 default:
162 return null;
163 }
164 }
165
166 /**
167 * Obtain connection prefix.
168 *
169 * @return the connection prefix
170 */
171 public String getPrefix() {
172 switch (this) {
173 case SQLSERVER:
174 return "jdbc:sqlserver://";
175 case MYSQL:
176 return "jdbc:mysql://";
177 case MARIADB:
178 return "jdbc:mariadb://";
179 case H2:
180 return "jdbc:h2:mem:";
181 case POSTGRESQL:
182 default:
183 return "jdbc:postgresql://";
184 }
185 }
186
187 /**
188 * Get connection string.
189 *
190 * @param pDatabase the database
191 * @param pServer the server
192 * @param pPort the port
193 * @return the connection string
194 */
195 public String getConnectionString(final String pDatabase,
196 final String pServer,
197 final Integer pPort) {
198 /* Create the buffer */
199 final StringBuilder myBuilder = new StringBuilder(BUFFER_LEN);
200 myBuilder.append(getPrefix());
201 if (this != H2) {
202 myBuilder.append(pServer);
203 if (pPort != null) {
204 myBuilder.append(":");
205 myBuilder.append(pPort);
206 }
207 if (this != SQLSERVER) {
208 myBuilder.append("/");
209 }
210 }
211 if (this != SQLSERVER) {
212 myBuilder.append(pDatabase);
213 }
214 if (this == H2) {
215 myBuilder.append(";DB_CLOSE_DELAY=-1");
216 }
217
218 /* Return the string */
219 return myBuilder.toString();
220 }
221
222 /**
223 * Get connection string for database create.
224 *
225 * @param pServer the server
226 * @param pPort the port
227 * @return the connection string
228 */
229 public String getConnectionString(final String pServer,
230 final Integer pPort) {
231 /* Create the buffer */
232 final StringBuilder myBuilder = new StringBuilder(BUFFER_LEN);
233 myBuilder.append(getPrefix());
234 myBuilder.append(pServer);
235 if (pPort != null) {
236 myBuilder.append(":");
237 myBuilder.append(pPort);
238 }
239 if (this != SQLSERVER) {
240 myBuilder.append("/");
241 }
242 if (this == POSTGRESQL) {
243 myBuilder.append("postgres");
244 }
245
246 /* Return the string */
247 return myBuilder.toString();
248 }
249
250 /**
251 * Obtain the database type for the field.
252 *
253 * @param pType the data type
254 * @return the database column type
255 */
256 public String getDatabaseType(final PrometheusColumnType pType) {
257 final boolean isSQLServer = this.equals(SQLSERVER);
258 final boolean isPostgreSQL = this.equals(POSTGRESQL);
259 switch (pType) {
260 case BOOLEAN:
261 return isPostgreSQL
262 ? "boolean"
263 : "bit";
264 case SHORT:
265 return "smallint";
266 case INTEGER:
267 return "int";
268 case LONG:
269 return "bigint";
270 case FLOAT:
271 return "real";
272 case DOUBLE:
273 return isSQLServer
274 ? "float"
275 : isPostgreSQL
276 ? "double precision"
277 : "double";
278 case DATE:
279 return "date";
280 case MONEY:
281 return isSQLServer
282 ? "money"
283 : "numeric(18,2)";
284 case DECIMAL:
285 return isSQLServer
286 ? "decimal"
287 : "numeric";
288 case BINARY:
289 return isPostgreSQL
290 ? "bytea"
291 : "varbinary";
292 case STRING:
293 default:
294 return "varchar";
295 }
296 }
297
298 /**
299 * Should we define binary length?
300 *
301 * @return true/false
302 */
303 public boolean defineBinaryLength() {
304 switch (this) {
305 case MYSQL:
306 case MARIADB:
307 case SQLSERVER:
308 case H2:
309 return true;
310 case POSTGRESQL:
311 default:
312 return false;
313 }
314 }
315
316 /**
317 * Should we explicitly drop indexes?
318 *
319 * @return true/false
320 */
321 public boolean explicitDropIndex() {
322 switch (this) {
323 case POSTGRESQL:
324 case SQLSERVER:
325 case H2:
326 return true;
327 case MYSQL:
328 case MARIADB:
329 default:
330 return false;
331 }
332 }
333 }