Skip to content

Commit f92556e

Browse files
committed
#629 Initial draft of JDP-2024-02: Create database through JDBC URL
1 parent 713db1e commit f92556e

File tree

1 file changed

+108
-0
lines changed

1 file changed

+108
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
= JDP-2024-02: Create database through JDBC URL
2+
3+
== Status
4+
5+
* Draft
6+
* Proposed for: Jaybird 6
7+
8+
== Type
9+
10+
* Feature-Specification
11+
12+
== Context
13+
14+
In Jaybird 5 and earlier, it is possible to create a new database using the `FBManager` class.
15+
This requires access to this class, either directly or through reflection.
16+
17+
It would be handy to have a way to create a database through use of the JDBC API only (so no extension APIs or Jaybird-specific classes or methods), for example to create database in third-party JDBC tools or libraries without Jaybird/Firebird specific support.
18+
19+
Although Firebird has a https://firebirdsql.org/file/documentation/html/en/refdocs/fblangref50/firebird-50-language-reference.html[`CREATE DATABASE` statement^], in reality this is partially handled by `fbclient.dll`/`libfbclient.so`, which will parse out information to send an `op_create` request to the server (or the equivalent internal call to the engine in case of embedded), and then use "`execute immediate`" with a modified version of the `CREATE DATABASE` statement on that newly created database for the final initialization.
20+
This split of responsibilities between client and server is also the reason executing a `CREATE DATABASE` statement on an existing JDBC connection does not work.
21+
22+
Some options of the `CREATE DATABASE` statement have equivalent DPB items, but other items can only be configured with the modified `CREATE DATABASE` statement (or a later `ALTER DATABASE` statement).
23+
These DPB items can usually also be specified on normal connections, and are applied if the connecting user has admin rights, or is the database owner.
24+
25+
In Firebird, database are isolated from each other, so it is not possible to switch a connection between databases (catalogs).
26+
27+
For comparison, other JDBC drivers offer options like:
28+
29+
* Connection property to create database if it doesn't currently exist:
30+
+
31+
--
32+
[horizontal]
33+
MySQL::
34+
Boolean property https://dev.mysql.com/doc/connector-j/en/connector-j-connp-props-connection.html#cj-conn-prop_createDatabaseIfNotExist[`createDatabaseIfNotExist`^]
35+
--
36+
* Automatically create database if it doesn't currently exist:
37+
+
38+
--
39+
[horizontal]
40+
H2::
41+
For embedded mode only (see http://h2database.com/html/features.html#database_only_if_exists[Opening a Database Only if it Already Exists^]).
42+
HSQLDB::
43+
For embedded mode only (see http://hsqldb.org/doc/2.0/guide/running-chapt.html#rgc_new_db[Creating a New Database^]).
44+
--
45+
* Support executing `CREATE DATABASE` or equivalent:
46+
+
47+
--
48+
[horizontal]
49+
PostgreSQL::
50+
After executing `CREATE DATABASE`, the connection still points to the initial database of the connection.
51+
Requires switching the catalog with `Connection.setCatalog(...)`.
52+
SQL Server::
53+
Same as PostgreSQL.
54+
--
55+
56+
== Decision
57+
58+
Jaybird adds a Boolean connection property `createDatabaseIfNotExist` which defaults to `false`.
59+
When set to `true`, if the connection cannot be created because the database does not exist, Jaybird will try to create a database.
60+
This property will be added as a JDBC connection property and as a getter/setter pair for data sources.
61+
62+
In addition, to allow connection properties which are only applied when creating a database, connections properties ending in `@create` (case-sensitive) can override the "`normal`" connection properties with the name before `@create`.
63+
For data sources, these properties will need to be set as non-standard properties.
64+
65+
The following properties cannot be overridden by `@create` properties:
66+
67+
* `serverName` (alias: `host`)
68+
* `portNumber` (alias: `port`)
69+
* `attachObjectName` (alias: `databaseName`, `serviceName`, `database`)
70+
71+
That is, a missing database cannot trigger the creation of a different database (other database name or server).
72+
Using a different user (with `user@create` and `password@create`) than the normal user, or a different role (with `roleName@create`) is explicitly and intentionally supported.
73+
74+
The "`attach`" otherwise "`create`" decision is made in the XCA layer, specifically -- for the current implementation -- in the constructor of `FBManagedConnection`.
75+
This may be moved elsewhere in the XCA layer if needed during implementation or at a later time.
76+
77+
=== Rejected design decisions
78+
79+
The following alternatives or options were considered, but rejected:
80+
81+
Support creating a new database with an existing connection::
82+
Intercept the `CREATE DATABASE` statement and handle it in a similar manner as `fbclient` does.
83+
With the following subdivision of solutions:
84+
Switch the connection to the new database:::
85+
This might cause confusion/problems, especially if the connection is held in a connection pool (e.g. it is returned to the pool, and the next user assumes it is connected to the original DB, while it is connected to the new DB).
86+
Keep the connection to the original database:::
87+
This will cause confusion because the user likely expects that subsequent statements are executed against the new DB.
88+
With the lack of catalog support, it is also impossible to switch to that new database with the existing connection.
89+
Terminate/kill connection after execution:::
90+
Avoids the confusion of the previous points, but is not very user-friendly.
91+
Allow "`database-less`" connections::
92+
In this solution, a (virtual) connection can be made to -- for example -- `jdbc:firebird://localhost/`, and that connection can only be used to create a new database.
93+
After executing a `CREATE DATABASE` statement, the connection will switch to that new database.
94+
+
95+
This is complex to implement, and results in an inconsistent API between real connections and "`database-less`" connections.
96+
For example, it allows database creation on one connection, but not another, and the majority of JDBC methods on such connections will not work or not work correctly.
97+
Allow `CREATE DATABASE` statement in connection property::
98+
This would give more flexibility in configuring the newly created database, but would require client-side parsing, and potential confusion with ignoring things like the database name in the statement, and precedence of properties specified in the connection properties vs in the `CREATE DATABASE` statement.
99+
+
100+
This might be an idea for a future improvement or extension.
101+
102+
== Consequences
103+
104+
Jaybird will support database creation through the connection property `createDatabaseIfNotExist`, and allow overriding the normal connection properties by adding those properties with names suffixed with `@create`.
105+
106+
Jaybird may restrict under what conditions or errors it will create a new database.
107+
Unfortunately, the non-existence of a database is not a clear and specific error, or `isc_io_error`/`335544344` is not specific and possibly other errors maybe raised when the database does not exist, so we may need to refine this in later releases.
108+
As such, the conditions when creation of a database is attempted is an implementation decision that may change with point releases.

0 commit comments

Comments
 (0)