View Javadoc
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.oceanus.resource.OceanusBundleId;
20  import io.github.tonywasher.joceanus.prometheus.preference.PrometheusColumnType;
21  
22  /**
23   * Database Drivers. Also code that encapsulates differences between databases.
24   */
25  public enum PrometheusJDBCDriver {
26      /**
27       * SQLServer.
28       */
29      SQLSERVER,
30  
31      /**
32       * PostgreSQL.
33       */
34      POSTGRESQL,
35  
36      /**
37       * MySQL.
38       */
39      MYSQL,
40  
41      /**
42       * MariaDB.
43       */
44      MARIADB,
45  
46      /**
47       * H2.
48       */
49      H2;
50  
51      /**
52       * Buffer length.
53       */
54      private static final int BUFFER_LEN = 100;
55  
56      /**
57       * DefaultPort for MariaDB/MySQL.
58       */
59      static final int PORT_MARIADB = 3306;
60  
61      /**
62       * DefaultPort for PostgreSQL.
63       */
64      static final int PORT_POSTGRESQL = 5432;
65  
66      /**
67       * DefaultPort for SQLExpress.
68       */
69      static final int PORT_SQLEXPRESS = 50843;
70  
71      /**
72       * DefaultInstance for SQLExpress.
73       */
74      static final String INSTANCE_SQLEXPRESS = "SQLEXPRESS";
75  
76      /**
77       * The String name.
78       */
79      private String theName;
80  
81      @Override
82      public String toString() {
83          /* If we have not yet loaded the name */
84          if (theName == null) {
85              /* Load the name */
86              theName = bundleIdForDriver(this).getValue();
87          }
88  
89          /* return the name */
90          return theName;
91      }
92  
93      /**
94       * Determine whether we use instance.
95       *
96       * @return true/false
97       */
98      public boolean useInstance() {
99          return this == SQLSERVER;
100     }
101 
102     /**
103      * Determine whether we use quotes.
104      *
105      * @return true/false
106      */
107     public boolean useQuotes() {
108         return switch (this) {
109             case MYSQL, MARIADB -> false;
110             default -> true;
111         };
112     }
113 
114     /**
115      * Determine whether we use port.
116      *
117      * @return true/false
118      */
119     public boolean usePort() {
120         return switch (this) {
121             case MYSQL, MARIADB, POSTGRESQL, SQLSERVER -> true;
122             default -> false;
123         };
124     }
125 
126     /**
127      * Obtain default port.
128      *
129      * @return the default port
130      */
131     public Integer getDefaultPort() {
132         return switch (this) {
133             case MYSQL, MARIADB -> PORT_MARIADB;
134             case POSTGRESQL -> PORT_POSTGRESQL;
135             case SQLSERVER -> PORT_SQLEXPRESS;
136             default -> null;
137         };
138     }
139 
140     /**
141      * Obtain connection prefix.
142      *
143      * @return the connection prefix
144      */
145     public String getPrefix() {
146         return switch (this) {
147             case SQLSERVER -> "jdbc:sqlserver://";
148             case MYSQL -> "jdbc:mysql://";
149             case MARIADB -> "jdbc:mariadb://";
150             case H2 -> "jdbc:h2:mem:";
151             default -> "jdbc:postgresql://";
152         };
153     }
154 
155     /**
156      * Get connection string.
157      *
158      * @param pDatabase the database
159      * @param pServer   the server
160      * @param pPort     the port
161      * @return the connection string
162      */
163     public String getConnectionString(final String pDatabase,
164                                       final String pServer,
165                                       final Integer pPort) {
166         /* Create the buffer */
167         final StringBuilder myBuilder = new StringBuilder(BUFFER_LEN);
168         myBuilder.append(getPrefix());
169         if (this != H2) {
170             myBuilder.append(pServer);
171             if (pPort != null) {
172                 myBuilder.append(":");
173                 myBuilder.append(pPort);
174             }
175             if (this != SQLSERVER) {
176                 myBuilder.append("/");
177             }
178         }
179         if (this != SQLSERVER) {
180             myBuilder.append(pDatabase);
181         }
182         if (this == H2) {
183             myBuilder.append(";DB_CLOSE_DELAY=-1");
184         }
185 
186         /* Return the string */
187         return myBuilder.toString();
188     }
189 
190     /**
191      * Get connection string for database create.
192      *
193      * @param pServer the server
194      * @param pPort   the port
195      * @return the connection string
196      */
197     public String getConnectionString(final String pServer,
198                                       final Integer pPort) {
199         /* Create the buffer */
200         final StringBuilder myBuilder = new StringBuilder(BUFFER_LEN);
201         myBuilder.append(getPrefix());
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         if (this == POSTGRESQL) {
211             myBuilder.append("postgres");
212         }
213 
214         /* Return the string */
215         return myBuilder.toString();
216     }
217 
218     /**
219      * Obtain the database type for the field.
220      *
221      * @param pType the data type
222      * @return the database column type
223      */
224     public String getDatabaseType(final PrometheusColumnType pType) {
225         final boolean isSQLServer = this.equals(SQLSERVER);
226         final boolean isPostgreSQL = this.equals(POSTGRESQL);
227         return switch (pType) {
228             case BOOLEAN -> isPostgreSQL
229                     ? "boolean"
230                     : "bit";
231             case SHORT -> "smallint";
232             case INTEGER -> "int";
233             case LONG -> "bigint";
234             case FLOAT -> "real";
235             case DOUBLE -> {
236                 if (isSQLServer) {
237                     yield "float";
238                 }
239                 yield isPostgreSQL ? "double precision" : "double";
240             }
241             case DATE -> "date";
242             case MONEY -> isSQLServer
243                     ? "money"
244                     : "numeric(18,2)";
245             case DECIMAL -> isSQLServer
246                     ? "decimal"
247                     : "numeric";
248             case BINARY -> isPostgreSQL
249                     ? "bytea"
250                     : "varbinary";
251             default -> "varchar";
252         };
253     }
254 
255     /**
256      * Should we define binary length?
257      *
258      * @return true/false
259      */
260     public boolean defineBinaryLength() {
261         return switch (this) {
262             case MYSQL, MARIADB, SQLSERVER, H2 -> true;
263             default -> false;
264         };
265     }
266 
267     /**
268      * Should we explicitly drop indexes?
269      *
270      * @return true/false
271      */
272     public boolean explicitDropIndex() {
273         return switch (this) {
274             case POSTGRESQL, SQLSERVER, H2 -> true;
275             default -> false;
276         };
277     }
278 
279     /**
280      * Obtain the resource bundleId for the driver.
281      *
282      * @param pDriver the driver
283      * @return the resource bundleId
284      */
285     private static OceanusBundleId bundleIdForDriver(final PrometheusJDBCDriver pDriver) {
286         return switch (pDriver) {
287             case SQLSERVER -> PrometheusDBResource.DRIVER_SQLSERVER;
288             case POSTGRESQL -> PrometheusDBResource.DRIVER_POSTGRESQL;
289             case MYSQL -> PrometheusDBResource.DRIVER_MYSQL;
290             case MARIADB -> PrometheusDBResource.DRIVER_MARIADB;
291             case H2 -> PrometheusDBResource.DRIVER_H2;
292             default -> throw new IllegalArgumentException();
293         };
294     }
295 }