# Jaybird 6.0.3 Release Notes

## 1. Jaybird 6.0.x changelog

Changes per Jaybird 6 release. See also What’s new in Jaybird 6. For known issues, consult Known issues.

### 1.1. Jaybird 6.0.3

The following was fixed or changed since Jaybird 6.0.2:

- Fixed: statement close could cause a hang of the connection (#876)

  A large amount (>= 64) of statement closes (or cleanup of leaked statements) without interleaving other server operations could cause a connection to Firebird 4.0 or higher to hang. This could also hang the cleaner thread used for closing leaked statements.

- Fixed: `ResultSet` move incorrectly closes input `Clob` (#880)

- Fixed: Batch execution with multiple empty strings resulted in error "Repeated blob id 0:0 in registerBlob()" (#888)

- Dependency update: updated `org.bouncycastle:bcprov-jdk18on` from 1.80 to 1.81 (used by `chacha64-plugin`) (#889)

- Fixed: On Java 24, `Connection.abort`, `Connection.setNetworkTimeout`, and `OperationMonitor.initOperationAware` always throw "java.lang.SecurityException: checking permissions is not supported" (#890)

### 1.2. Jaybird 6.0.2

The following was fixed or changed since Jaybird 6.0.1:

- Improvement: added `authPlugins` property on `FBManager` (#866)

  As part of this change, the interface `FBManagerMBean` now extends `AttachmentProperties`, so that all attachment properties are accessible.

- Improvement: increased default and maximum SQL info sizes used for retrieving statement information like columns, parameters and plan information (#869)

  The values were changed from the original default and maximum of 32,767 to:

  - For pure Java connections:

    - protocol 12 (Firebird 2.5): 65,535 (default and maximum),

    - protocol 13 (Firebird 3.0) and higher: 512 KiB default, 16 MiB maximum.

  - For native connections:

    - Firebird 2.5 and higher: 65,535 (default and maximum)

  This change improves the performance of preparing statements with a lot of columns and parameters by reducing the number of round-trips needed to retrieve the column and parameter information. It may also prevent truncation of “explained plans” for statements with very complex or extensive plans.

- Improvement: backported inline blob support (Firebird 5.0.3 and higher) from Jaybird 7 (#870)

  See also Inline blob support.

- Improvement: The time zone mapping was updated (#874)

  - The following time zone ids were added: `64901` ⇒ `Pacific/Kanton`, `64900` ⇒ `Europe/Kyiv`, `64899` ⇒ `America/Ciudad_Juarez`, `64898` ⇒ `GMT-03:00` (should be `America/Coyhaique`, but that zone name is not yet known in Java)

  - Time zone id `64903` is now mapped to `America/Nuuk`; previously it was mapped to `America/Godthab` as older versions of Java did not know `America/Nuuk`.

### 1.3. Jaybird 6.0.1

The following was fixed or changed since Jaybird 6.0.0:

- Improvement: backported deferred blob open optimization from Jaybird 7 (#842)

  See also Deferred blob open.

- Fixed: `NullPointerException` in `getGeneratedKeys()` with blob columns after (auto)commit (#846)

  As part of this fix, there was an incompatible change in the internal GDS-ng API. Various methods and constructors involved in blob handle creation now throw a `SQLException` if the database is not attached or the transaction is null or not active. See also Breaking changes internal API for 6.0.1.

- Fixed: Fetch response with status=0 (FETCH_OK) and count=0 was logged on DEBUG as an unexpected response (#848)

- Improvement: backported fetching all known blob info items on open from Jaybird 7 (#852)

  See also Requesting known info items on open.

- Dependency update: updated `net.java.dev.jna:jna-jpms` from 5.16.0 to 5.17.0 (used by `jaybird-native`) (#854)

- Dependency update: updated `org.bouncycastle:bcprov-jdk18on` from 1.79 to 1.80 (used by `chacha64-plugin`) (#856)

### 1.4. Jaybird 6.0.0

The following was fixed or changed after 6.0.0-beta-1:

- Improvement: stacktraces produced by `FbExceptionBuilder` no longer include `StackTraceElements` of the builder itself (#827)

- Improvement: support for custom SocketFactory in connection string and data sources (#828)

  See also Custom socket factory for pure Java connections.

- Improvement: added connection property `asyncFetch` and system property `org.firebirdsql.jdbc.defaultAsyncFetch` to disable async fetching for pure Java connections (#831)

  See also Asynchronous fetching

- Dependency update: updated `org.bouncycastle:bcprov-jdk18on` from 1.78.1 to 1.79 (used by `chacha64-plugin`)

- Dependency update: updated `net.java.dev.jna:jna-jpms` from 5.15.0 to 5.16.0 (used by `jaybird-native`)

### 1.5. Jaybird 6.0.0-beta-1

Initial release for evaluation.

## 2. Known issues

- Using a native connection with a Firebird 3.0 or higher client library to a Firebird 2.5 or older server may be slow to connect.

  Possible workarounds:

  - Use a native URL with the Firebird INET4 protocol (e.g. for `DriverManager` `jdbc:firebird:native:inet4://<serverName>[:<portNumber>/<databaseName>`).

  - Use the IPv4 address instead of the host name in the connection string

  - Use a Firebird 2.5 or earlier `fbclient`.

  This is caused by firebird#4971

- In Java 24, the mapping of some named `WITH TIME ZONE` values changed as Java’s mapping of short IDs changed. This should only affect cases where you explicitly obtain `ZonedDateTime` or `ZonedTime` instances with these named zones.

  - EST (ID 65136) → America/Panama; maps to -05:00 in older Java versions

  - HST (ID 65027) → Pacific/Honolulu; maps to -10:00 in older Java versions

  - MST (ID 65002) → America/Phoenix; maps to -07:00 in older Java versions

  This is informational only, and not something that we can fix or change in a later Jaybird release.

## 3. General Notes

Jaybird is a JDBC driver suite to connect to Firebird database servers from Java and other Java Virtual Machine (JVM) languages.

This driver does not work on Android, because it uses classes and features not available in Android.

### 3.1. About this version

Jaybird 6 is an incremental change from Jaybird 5.

The major changes and new features in Jaybird 6 are:

- Minimum supported Java version is Java 17.
  See Java support for more information.

- Minimum supported Firebird version is Firebird 3.0.
  See Firebird support for more information.

- The pure Java protocol — by default — no longer connects to Firebird 2.5 and older, as those versions are not supported.
  See Pure Java will not connect to unsupported Firebird versions by default for more information.

- The native and embedded protocols have been moved to a separate artifact, `jaybird-native`.
  See NATIVE and EMBEDDED support moved to a separate artifact for more information.

- OOREMOTE (OpenOffice/LibreOffice protocol) removed

- Modularization of Jaybird

- Connection property `createDatabaseIfNotExist`

- Report actual process ID (pid)

- Logging facade removed

- Support for ChaCha64 wire encryption

- Opt-in feature for package information in DatabaseMetaData

- Asynchronous fetching

- Blob performance improvements

- Support for executing transaction management statements

- Configurable buffer sizes for the wire protocol

- Broken connection detection for event manager

- Connection property to specify native library path

- Rewritten client info properties support

- `TIMESTAMP` fields now accept `LocalDate` and `LocalTime`

- `ResultSet` in auto-commit no longer closed after last row

- Changes to behaviour of updatable scrollable result sets

- Custom socket factory for pure Java connections

- …​ and other fixes and changes

Upgrading from Jaybird 5 should be straightforward, but please make sure to read Compatibility changes before using Jaybird 6. If you’re using Jaybird with the native or embedded connections, you will need to make some additional changes. See also Upgrading from Jaybird 5 to Jaybird 6.

Bug reports about undocumented changes in behavior are appreciated. Feedback can be sent to the Firebird-java mailing list or reported on the issue tracker https://github.com/FirebirdSQL/jaybird/issues.

### 3.2. Supported Firebird versions

Jaybird 6.0.3 was tested against Firebird 3.0.13, Firebird 4.0.6, and Firebird 5.0.3, but should also support other Firebird versions from 3.0 and up. Firebird 2.5 and older are not supported.

Firebird 6.0 is currently not considered supported (see also Firebird support in What’s new in Jaybird 6).

Jaybird 6 will — by default — not connect to Firebird 2.5 or older. See also Pure Java will not connect to unsupported Firebird versions by default.

This driver does not support InterBase.

### 3.3. Supported Java versions

Jaybird 6 supports Java 17 and higher (JDBC 4.3/JDBC 4.4). Support for earlier Java versions has been dropped.

Given the limited support period for Java 17 and higher versions, we limit support to Java 17, Java 21, and the latest Java release. Currently, that means we support Java 17, Java 21, and Java 24.

| Jaybird 5 serves as a “long-term support” version for Java 8 and Java 11, with maintenance releases at least until the release of Jaybird 7.

Jaybird 6 provides libraries compiled for Java 17.

Jaybird 6 is modularized. The available modules are:

`org.firebirdsql.jaybird`

  main Jaybird driver (`jaybird-6.0.3.jar`)

`org.firebirdsql.jaybird.chacha64`

  ChaCha64 wire encryption implementation (`chacha64-plugin-6.0.3.jar`)

`org.firebirdsql.jna`

  native and embedded protocol implementation using JNA (`jaybird-native-6.0.3.jar`)

See also Java support in What’s new in Jaybird 6.

### 3.4. Specification support

Jaybird supports the following specifications:

Specification | Notes
--- | ---
JDBC 4.4 | If a security manager is available, the driver still performs `SQLPermission` checks.
JDBC 4.3 | All JDBC 4.3 methods for features supported by Firebird.
JTA 1.0.1 | Implementation of `javax.transaction.xa.XAResource` interface via `XADataSource` implementation.

## 4. Support

If you need support with Jaybird, join the Firebird-Java Google Group and mailing list. You can subscribe by sending an email to firebird-java+subscribe@googlegroups.com.

Looking for professional support of Jaybird? Jaybird is now part of the Tidelift subscription.

For a more complete list, see the next section.

### 4.1. Where to get help

- On Stack Overflow, please tag your questions with jaybird and firebird

- The Firebird-Java group and corresponding mailing list firebird-java@googlegroups.com

  You can subscribe to the mailing list by sending an email to firebird-java+subscribe@googlegroups.com

- Looking for professional support of Jaybird? Jaybird is now part of the Tidelift subscription.

- The Firebird project home page

- Firebird-support and other Firebird mailing lists for questions not directly related to Jaybird and Java.

### 4.2. Contributing

There are several ways you can contribute to Jaybird or Firebird in general:

- Participate on the mailing lists

- Report bugs or submit patches on the tracker (see Reporting bugs)

- Create pull requests on GitHub (https://github.com/FirebirdSQL/jaybird)

- Become a developer (for Jaybird contact us on firebird-java, for Firebird in general, use the Firebird-devel mailing list)

- Donate to the Firebird Foundation (see https://firebirdsql.org/en/donate/)

- Become a paying Associate, Partner or sponsor of the Firebird Foundation (see https://firebirdsql.org/en/firebird-foundation/)

### 4.3. Reporting bugs

The developers follow the firebird-java Google Group. Join the list and post information about suspected bugs. List members may be able to help out to determine if it is an actual bug, provide a workaround and get you going again, whereas bug fixes might take a while.

You can also report bugs in the Jaybird bug tracker, https://github.com/FirebirdSQL/jaybird/issues.

When reporting bugs, please provide a minimal, but complete reproduction, including databases and sourcecode to reproduce the problem. Patches to fix bugs are also appreciated. Make sure the patch is against a recent master version of the code. You can also fork the jaybird repository and create pull requests.

## 5. Getting Jaybird 6

### 5.1. Jaybird 6.0.3

#### 5.1.1. Maven

Jaybird 6.0.3 is available on Maven Central.

groupId | `org.firebirdsql.jdbc`
artifactId | `jaybird`
version | `6.0.3`

For example:

    <dependency>
        <groupId>org.firebirdsql.jdbc</groupId>
        <artifactId>jaybird</artifactId>
        <version>6.0.3</version>
    </dependency>

If you want to use Type 2 support (native or embedded), you need to explicitly add `jaybird-native` as a dependency:

    <dependency>
        <groupId>org.firebirdsql.jdbc</groupId>
        <artifactId>jaybird-native</artifactId>
        <version>6.0.3</version>
    </dependency>

For Windows and Linux, you can add the `org.firebirdsql.jdbc:fbclient` dependency on your classpath to provide the native libraries for the `native` protocol. Be aware that this dependency does not support `embedded`.

See also Type 2 (native) and embedded driver.

To enable the “ChaCha64” wire encryption support for pure Java connections, also add:

    <dependency>
        <groupId>org.firebirdsql.jdbc</groupId>
        <artifactId>chacha64-plugin</artifactId>
        <version>6.0.3</version>
    </dependency>

#### 5.1.2. Gradle

See also Maven.

Examples:

Main Jaybird artifact

    implementation 'org.firebirdsql.jdbc:jaybird:6.0.3'

Jaybird native artifact (native and embedded protocol)

    implementation 'org.firebirdsql.jdbc:jaybird-native:6.0.3'

ChaCha64 wire encryption plugin

    implementation 'org.firebirdsql.jdbc:chacha64-plugin:6.0.3'

#### 5.1.3. Download

You can download the release of Jaybird from https://firebirdsql.org/en/jdbc-driver/

At minimum, Jaybird 6 requires `jaybird-6.0.3.jar`.

For native or embedded support, also add `jaybird-native-6.0.3.jar` and `jna-jpms-5.17.0.jar` on your classpath or modulepath. See also Type 2 (native) and embedded driver.

For “ChaCha64” wire-encryption support with pure Java connections, also add `chacha64-plugin-6.0.3.jar`, and `bcprov-jdk18on-1.81.jar` from the `lib` directory of the distribution zip.

## 6. Upgrading from Jaybird 5 to Jaybird 6

Please make sure to read Compatibility changes before upgrading to Jaybird 6.

### 6.1. Maven

Change the version of the dependency to `6.0.3`. If you’re using the artifact id `jaybird-jdkXX`, change it to `jaybird`.

When your Jaybird dependency defines the exclusion for `javax.resource:connector-api` (see example below), you can remove it as Jaybird no longer has a dependency on `connector-api`.

    <exclusions>
        <exclusion>
            <groupId>javax.resource</groupId>
            <artifactId>connector-api</artifactId>
        </exclusion>
    </exclusions>

For more detailed instructions, see also the information on Maven in Getting Jaybird 6.

If you use native or embedded, you now need to explicitly add `jaybird-native` as a dependency:

    <dependency>
        <groupId>org.firebirdsql.jdbc</groupId>
        <artifactId>jaybird-native</artifactId>
        <version>6.0.3</version>
    </dependency>

If you use native or embedded, make sure to update your JNA dependency to version `5.17.0` and artifact id `jna-jpms`, or remove it altogether as the dependencies will now be pulled in through the `jaybird-native` artifact.

    <dependency>
        <groupId>net.java.dev.jna</groupId>
        <artifactId>jna-jpms</artifactId>
        <version>5.17.0</version>
    </dependency>

| Previous Jaybird versions used `artifactId` `jna` instead of `jna-jpms`. Although both artifacts are nearly identical, the `jna-jpms` artifact provides a `module-info.class`, while the `jna` artifact does not. If you want to use Jaybird as a module, and use `jaybird-native`, make sure to use the `jna-jpms` artifact.

### 6.2. Manual install

If you manage your dependencies manually, you need to do the following:

1. Replace the Jaybird 5 library with the Jaybird 6 version

   - `jaybird-5.0.x.<java>.jar` with `jaybird-6.0.3.jar`

2. If you use the NATIVE or EMBEDDED protocols, add the following JARs to the classpath or modulepath

   - `jaybird-native-6.0.3.jar`

   - `jna-jpms-5.17.0.jar` from the `lib` directory of the distribution zip

     If you have an older version of JNA or a `jna-5.17.0` instead of `jna-jpms-5.17.0`, make sure to replace it with `jna-jpms`.

3. To enable “ChaCha64” wire encryption support add the following JARs to the classpath or modulepath

   - `chacha64-plugin-6.0.3.jar`

   - `bcprov-jdk18on-1.81.jar` from the `lib` directory of the distribution zip

### 6.3. Gotcha’s

If you find a problem while upgrading, or other bugs, please report it on https://github.com/FirebirdSQL/jaybird/issues (see also Reporting bugs).

For known issues, consult Known issues.

## 7. What’s new in Jaybird 6

For a full list of changes, see milestones “v6-initial” and “v6.0.0”.

### 7.1. Changes in version numbering

The minimum supported Java version of Jaybird 6 is Java 17. Our expectation is that Java version specific artifacts are no longer needed. As a consequence, the Java version has been dropped from the version number. The full version and naming convention is documented in jdp-2023-01: Version Number and Naming Scheme

As a result of these new naming conventions, the following has changed:

- Maven version: `6.0.0` (was `5.0.0.java8`)

- Distribution zip: `jaybird-6.0.0.zip` (was `jaybird-5.0.0.java8.zip`)

- Jaybird: `jaybird-6.0.0.jar` (was `jaybird-5.0.0.java8.jar`)

- Jaybird sources: `jaybird-6.0.0-sources.jar` (was `jaybird-5.0.0.java8-sources.jar`)

- Jaybird javadoc: `jaybird-6.0.0-javadoc.jar` (was `jaybird-5.0.0.java8-javadoc.jar`)

Furthermore, the client name reported to Firebird is now `Jaybird jaybird-6.0.0` (was: `Jaybird jaybird-5.0.0.java8`).

### 7.2. Java support

#### 7.2.1. Java versions before 17 no longer supported

Support of Java versions before Java 17 was dropped.

See also jdp-2022-03: Java 17 minimum version

#### 7.2.2. Java 17 and higher

Jaybird 6 supports Java 17 and higher (JDBC 4.3). Most of the JDBC 4.3 features have been implemented (in as far as they are supported by Firebird).

Given the limited support period for Java 17 and higher versions, not all Java releases are formally supported, see Supported Java versions for details.

### 7.3. Firebird support

Support for Firebird 2.5 has been dropped. See also Support for Firebird 2.5 dropped.

Jaybird 6 supports Firebird 3.0, Firebird 4.0, and Firebird 5.0.

| No promises on Firebird 6.0 support Firebird 6.0 is still in development, and includes changes — like schema support — that impact Jaybird. As a result — at this time — we make no promises on the support for Firebird 6.0 by Jaybird 6. We may delay support for Firebird 6.0 until Jaybird 7, or we may improve support during maintenance releases of Jaybird 6.

Jaybird 6 will — by default — not connect to unsupported versions (that is, Firebird 2.5 or older) using the pure Java protocol. See also Pure Java will not connect to unsupported Firebird versions by default.

### 7.4. Pure Java will not connect to unsupported Firebird versions by default

The pure Java protocol will by default no longer try the wire protocol versions of unsupported Firebird versions. This means that — by default — only protocol version 13 (Firebird 3.0) — 19 (Firebird 5.0.3 and higher) are tried. As a result, attempts to connect to Firebird 2.5 or earlier will result in error “connection rejected by remote interface” (`335544421` or `isc_connect_reject`).

The connection property `enableProtocol` can enable unsupported protocols, assuming a suitable protocol implementation is available on the classpath.

This connection property can have the following values:

- A comma-separated list of additional protocol versions to try (e.g. `"11,12"`). The listed versions are tried in addition to the supported protocol versions. Non-integer values or unknown protocol versions are silently ignored.

  It is possible to use the “masked” protocol version (e.g. `"32780"` for protocol version 12). However, we recommend using the unmasked version (e.g. `"12"` for protocol version 12).

- `"*"`— enable all available protocol versions

- `null` or empty string (`""`) — default behaviour, only use supported protocols

A different default value of `enableProtocol` can be set using the system property `org.firebirdsql.jdbc.defaultEnableProtocol`. This system property is checked each time a connection configuration is created, so it can be changed at runtime. If you use a Jaybird `DataSource` implementation, it uses the value at the time the `DataSource` is created; if you use `DriverManager`— this can include third-party data sources, it uses the value at the time the connection is created.

| Given these protocol versions and their Firebird versions are not supported, there is no guarantee that the driver will function correctly when an unsupported protocol is enabled. Especially things like database metadata could use features that are not supported by older Firebird versions. We recommend upgrading your Firebird version, or downgrading to a Jaybird version which still supports your Firebird version. For maximum compatibility, it is recommended to either use `"*"`, or to make sure to include the maximum protocol version of your Firebird version. Unsupported protocol versions may be removed in future major releases of Jaybird.

Table 1. Firebird versions and protocol versions
Firebird version | Maximum protocol
--- | ---
1.0 — 2.0 | 10
2.1 | 11
2.5 | 12
3.0 | 15[1][2]
4.0 | 16[3]
5.0 | 19[4]

### 7.5. NATIVE and EMBEDDED support moved to a separate artifact

The NATIVE (JDBC URL prefix `jdbc:firebird[sql]:native:`) and EMBEDDED (JDBC URL prefix `jdbc:firebird[sql]:embedded:`) protocol implementations have been moved to a separate artifact, `org.firebirdsql.jdbc:jaybird-native`.

If you use native or embedded connections using Jaybird, you will need to explicitly add the appropriate Maven dependency (or `jaybird-native-6.0.3.jar` and `jna-jpms-5.17.0.jar`) to your classpath.

See also Getting Jaybird 6.

### 7.6. OOREMOTE (OpenOffice/LibreOffice protocol) removed

The OOREMOTE protocol (JDBC URL prefix `jdbc:firebird[sql]:oo:`) has been removed in Jaybird 6.

See also jdp-2022-04: Deprecate OOREMOTE (OpenOffice/LibreOffice driver) for removal.

The recommended replacement is to use LibreOffice and the builtin “Firebird External” connection option in LibreOffice Base, instead of the “JDBC” option with Jaybird on the classpath of LibreOffice.

### 7.7. Modularization of Jaybird

Jaybird now uses real Java modules.

The available modules are:

`org.firebirdsql.jaybird`

  main Jaybird driver (`jaybird-6.0.3.jar`)

`org.firebirdsql.jaybird.chacha64`

  ChaCha64 wire encryption implementation (`chacha64-plugin-6.0.3.jar`)

`org.firebirdsql.jna`

  native and embedded protocol implementation using JNA (`jaybird-native-6.0.3.jar`)

We’ve tried to be liberal with exporting packages from Jaybird, but we have decided not to export some packages because we think they shouldn’t normally be accessed by users of Jaybird. If you run into problems with packages not being exported, please report this on firebird-java or on https://github.com/FirebirdSQL/jaybird/issues. Please include an explanation why you need to access a specific package. As a workaround, you can also add exports yourself with the `--add-exports` commandline option of `java` and `javac` and the `Add-Exports` manifest entry of your application (similar options exist for opens).

When the Jaybird JAR files are on the classpath, they should behave as before. For modular applications, once added to the modulepath instead of the classpath, they will behave in a more restricted fashion.

If you use Jaybird only as a JDBC driver (through `java.sql.DriverManager`), having the driver on the modulepath and having `requires java.sql` in the `module-info.java` of your application should be sufficient. If your code uses classes and other types from Jaybird, you will also need to add `requires org.firebirdsql.jaybird`.

The ChaCha64 plugin, `org.firebirdsql.jaybird.chacha64`, will just need to be present on the modulepath to be loaded.

The same goes for the native protocol module, `org.firebirdsql.jna`, but we recommend you only add it to the modulepath if you actually need native or embedded access. You also need to replace any `jna-<version>.jar` with `jna-jpms-5.17.0.jar` (the modular variant of JNA).

If you use `org.firebirdsql.jna` to implement a Firebird embedded provider, you’ll need to add `requires org.firebirdsql.jna` and an appropriate `provides org.firebirdsql.jna.embedded.spi.FirebirdEmbeddedProvider with <classname>` in your `module-info.java`. For compatibility with use on the classpath, it is recommended to also provide the `META-INF/services/org.firebirdsql.jna.embedded.spi.FirebirdEmbeddedProvider` file.

For more information, see also jdp-2023-13: Modularization of Jaybird.

### 7.8. Connection property `createDatabaseIfNotExist`

The Boolean connection property `createDatabaseIfNotExist` instructs Jaybird to attempt to create the database if it does not exist yet. This property can be used in the JDBC URL, in the `Properties` object passed to `DriverManager`, and can be set on data sources.

Although Jaybird already allowed you to create databases using `org.firebirdsql.management.FBManager`, this is not always accessible, for example in tools or libraries that only expose or use the JDBC API. This new property provides an alternative way to create databases.

Jaybird allows you to set or override connection properties specifically for creating the database by suffixing the property name with `@create` (case-sensitive). This can be used to set configuration properties that are only relevant for creating the database, or — for example — to use a different user or role for creating the database than used for normal connections.

As an example:

    String jdbcUrl = "jdbc:firebird://localhost/exampledb" +
        "?createDatabaseIfNotExist=true&" +
        "user@create=sysdba&password@create=masterkey";
    try (Connection connection = DriverManager.getConnection(
        jdbcUrl, "normaluser", "password")) {
      // ...
    }

If the database already exists, the connection will be made with user `normaluser`, but if the database does not exist, the database and the connection will be created with user `sysdba`.

| The errors Firebird returns do not make it possible to determine definitively if the database does not exist, or if there is another reason that the connection failed. Jaybird applies some simple rules to exclude some classes of errors, and not attempt to create a database in those cases. If you find cases where you think Jaybird should not — or on the contrary, should — attempt to create a database, please report them on https://github.com/FirebirdSQL/jaybird/issues.

For more information, see also jdp-2024-02: Create database through JDBC URL.

### 7.9. Report actual process ID (pid)

The pure Java implementation will now report the actual process ID (pid) in connection property `isc_dpb_process_id`. The native implementation already did this.

For pure Java connections, the reported process ID can be overridden using the connection property `processId` or the system property `org.firebirdsql.jdbc.pid`. This feature is retained for backwards compatibility.

When a `SecurityManager` is installed, the entire call-chain needs to have the `RuntimePermission("manageProcess")` to obtain the process ID in pure Java connections. If this permission check fails, Jaybird will silently ignore it and not set the `isc_dpb_process_id` based on the actual process ID.

### 7.10. Logging facade removed

The logging facade from package `org.firebirdsql.logging` has been removed, and is replaced by the Java Platform Logging API (JEP 264).

The Java Platform Logging API by default logs to `java.util.logging`, but it is possible to plug in different logging platforms. For example, Log4j provides the `log4j-jpl` dependency which will replace the default binding to `java.util.logging` with one to Log4j.

With this change, Jaybird no longer provides an option to specify a custom logger implementation, so the system property `org.firebirdsql.jdbc.loggerImplementation` is no longer supported. If you need a custom logger, you will need to implement `java.lang.System.Logger` and `java.lang.System.LogFinder` and provide the necessary service loader definition (see the Java documentation for details).

The system properties `org.firebirdsql.jdbc.forceConsoleLogger` and `org.firebirdsql.jdbc.disableLogging` are also no longer supported. Equivalent behaviour is achieved by configuring the active logging library.

### 7.11. Support for ChaCha64 wire encryption

Support for the “ChaCha64” wire encryption — introduced in Firebird 4.0.1 — was added for the `PURE_JAVA` protocol. Given this requires a dependency on the Bouncy Castle provider (`bcprov-jdk18on`), the plugin is made available as a separate artifact: `org.firebirdsql.jdbc:chacha64-plugin` on Maven or `chacha64-plugin-6.0.3.jar` in the distribution zip.

When deploying manually, please make sure to also include the `bcprov-jdk18on-1.81.jar` from the `lib` directory of the distribution zip on the classpath.

Limitations of ChaCha lead to introduction of ChaCha64

The “ChaCha” wire encryption introduced in Firebird 4.0 and Jaybird 5 uses a 96-bit nonce and 32-bit counter. This 32-bit counter limits the amount of data you can transfer to a maximum of 256 GiB. As the Firebird wire protocol doesn’t support “re-keying” the encryption plugin, this means the connection breaks if 256GiB has been sent or received. This breaking is done to prevent key re-use, which could make the data stream vulnerable to certain types of cryptological analysis.

To address this, Firebird 4.0.1 added the “ChaCha64” wire encryption, which uses a 64-bit nonce and 64-bit counter.

As part of this change, Jaybird is now capable of loading `EncryptionPluginSpi` instances using the service loader mechanism. The API of `EncryptionPluginSpi` and `EncryptionPlugin` and other classes and interfaces in package `org.firebirdsql.gds.ng.wire.crypt` should still be considered unstable and internal API, so use it at your own risk to implement your own plugins. If you want to use it for implementing your own encryption plugins, let us know on firebird-java. We can then look at stabilizing the API and considering it formally a public API.

See also jdp-2023-06: ChaCha64 Support

### 7.12. Opt-in feature for package information in DatabaseMetaData

Firebird 3.0 added packages, which can contain stored procedures and functions. The JDBC API does not provide a standard way of accessing information about packages, or the routines defined in packages. Instead of adding additional Jaybird-specific metadata methods, we’ve added an “opt-in” feature that provides access through normal metadata methods, using the “catalog” to report packages.

This feature can be enabled by setting the connection property `useCatalogAsPackage` to `true`. When this connection property is enabled, the `DatabaseMetaData` of that connection will have the following changes in behaviour:

- `getCatalogs()` lists packages, with package names in `TABLE_CAT`.

- `getFunctions`, `getFunctionColumns`, `getProcedures`, and `getProcedureColumns` include information on procedures or functions in packages

  - Columns `FUNCTION_CAT`/`PROCEDURE_CAT` will report:

    - For packaged procedures and functions — the package name

    - For normal (non-package) procedures and functions — an empty string instead of `null` (because of the following rule)

  - If parameter `catalog` is `""` (empty string), only normal stored procedures or stored functions are reported.

  - If parameter `catalog` is `null`, both packaged and normal stored procedures or stored functions are reported.

  - For other values of parameter `catalog`, these metadata methods will only return procedures, functions, or their columns of the specified package (exact match, case-sensitive; not a `LIKE` pattern)

  - For normal (non-package) procedures and functions, the `SPECIFIC_NAME` column will be the unquoted function or procedure name (same as when `useCatalogAsPackage` is not enabled), and for packaged procedures and functions, it will be `quoted-package-name + '.' + quoted-routine-name` (e.g. `"SOME_PACKAGE"."SOME_FUNCTION"`)

- `getCatalogSeparator()` returns `"."` (string with period).

- `getCatalogTerm()` returns `"PACKAGE"`.

- `isCatalogAtStart()` returns `true`.

- `getMaxCatalogNameLength()` returns 31 or 63 depending on the maximum identifier length of the Firebird version.

- `supportsCatalogsInDataManipulation()` returns `true` (i.e. access selectable stored procedures and functions from packages).

- `supportsCatalogsInProcedureCalls()` returns `true`.

- The other `supportsCatalogsIntype()` methods continue to return `false`.

- Other metadata methods with a `catalog` parameter continue to ignore it, just like they do when `useCatalogAsPackage` is disabled.

The `useCatalogAsPackage` connection property does not result in any other behaviour.

Keep in mind, that this is non-standard behaviour, and standard JDBC tools or libraries may not work correctly when this property is enabled. This feature may be discontinued and removed in the future if Jaybird needs to implement “real” catalogs (e.g. because Firebird started supporting catalogs).

See also jdp-2023-08: Use Catalog as Package

### 7.13. Asynchronous fetching

For pure Java connections, non-holdable forward-only result sets now perform asynchronous fetches. Asynchronous fetches are implemented for protocol implementation version 11 and higher (i.e. Firebird 2.1 or higher), but are formally only supported for protocol version 13 and higher (i.e. Firebird 3.0 or higher).

In normal usage of a result set, the first fetch will be a normal synchronous fetch. If certain conditions are met, subsequent fetches will be performed asynchronously.

The conditions for using asynchronous fetch are considered an implementation detail and may change in point releases. In Jaybird 6.0.0, the conditions to enable asynchronous fetching are:

1. The result set has type `FORWARD_ONLY`.

2. The result set does not have a cursor name set.

3. Any synchronous fetch on the statement cursor retrieved at least 15 rows. Be aware that the server may return fewer rows than the configured fetch size (default is 400), depending on Firebird version, row size and other factors.

When the asynchronous fetch is triggered is also an implementation detail and may change in point releases. In Jaybird 6.0.0, the conditions to perform an asynchronous fetch are:

- Size of the row buffer is equal to the “low-water mark”.

  This “low-water mark” is calculated as ~33% of the maximum number of rows returned by previous fetches, with a minimum of 10 rows.

  As a consequence of this condition, reducing the fetch size equal to or less than the “low-water mark” may cause asynchronous fetches to stop being triggered, as the buffer size may remain smaller than this “low-water mark” (this effect may be reduced if there is other activity on the connection after the asynchronous fetch was performed). In that case, a synchronous fetch is triggered when the buffer is empty.

- Fetch size at time of async fetch is larger than 1. This may be the configured fetch size, or the fetch size derived taking into account the configured maximum row count.

Native connections do not support this type of asynchronous fetching, but `fbclient` itself provides a different form of internal asynchronous fetching for native connections.

Asynchronous fetching — for pure Java — can be disabled with the Boolean connection property `asyncFetch`, by setting it to `false`. The system property `org.firebirdsql.jdbc.defaultAsyncFetch` can be used to disable it globally; this system property is checked dynamically when the connection configuration is created. These properties are primarily intended for troubleshooting or workarounds if it turns out this feature has problems; they may be removed in a future Jaybird version once this feature has proven itself.

### 7.14. Blob performance improvements

#### 7.14.1. Reading blobs

Performance of reading blobs has been improved, especially when using `getBytes` on `ResultSet` or `Blob`, or `getString` on `ResultSet` or `Clob`, or reading from a blob input stream with `read(byte[], int, int)` and similar methods with a byte array and requested length greater than 50% of the configured `blobBufferSize`.

Testing on a local network (Wi-Fi) shows an increase in throughput of roughly 50-100% for reading large blobs with the default `blobBufferSize` of 16384.

These throughput improvements were only realised in the pure Java protocol, because there we had the opportunity to avoid all additional allocations by writing directly from the network stream into the destination byte array, and this allows us to ignore the configured `blobBufferSize` and use up to the maximum request size of 65535 bytes instead.

This is not possible for the JNA-based protocols (native/embedded), as the implementation requires a direct byte buffer to bridge to the native API, and thus we can’t ignore the `blobBufferSize`. We were able to realise some other optimizations (in both pure Java and JNA), by avoiding allocation of a number of intermediate objects, but this has only marginal effects on the throughput.

#### 7.14.2. Writing blobs

Performance of writing blobs was improved, especially when using `setBytes` on `PreparedStatement`, `ResultSet` or `Blob`, or `setString` on `PreparedStatement`, `ResultSet` or `Clob`, or writing to a blob output stream with `write(byte[], int, int)` and similar methods with a byte array larger than the configured `blobBufferSize`. A smaller improvement was made when using arrays larger than 50% of the `blobBufferSize`.

Testing on a local network (Wi-Fi) shows an increase in throughput of roughly 300-400% for writing large blobs with the default `blobBufferSize` of 16384. The improvement is not available for all methods of writing blobs, for example using `ResultSet.setBinaryStream` does not see this improvement, as it relies on the `blobBufferSize` for transferring the blob content.

Most of these throughput improvements were only realised in the pure Java protocol, because there we had the opportunity to avoid all additional allocations by writing directly from the source byte array to the network stream, and this allows us to ignore the configured `blobBufferSize` and use up to the maximum segment size of 65535 bytes instead.

For the JNA-based protocols (native/embedded) a smaller throughput improvement was realised, by using the maximum segment size for the first roundtrip if the array write used offset `0`. If the length is larger than the maximum segment size, or if the offset is non-zero, we need to allocate a buffer (for subsequent segments in case offset is `0`), and thus cannot ignore the `blobBufferSize`.

Similar to the improvements for reading, we were also able to realise some other optimizations (in both pure Java and JNA), by avoiding allocation of a number of intermediate objects, but this has only marginal effects on the throughput.

#### 7.14.3. Deferred blob open

Added in: Jaybird 6.0.1, backported from Jaybird 7

In the pure Java implementation, performance of reading and writing blobs was improved by deferring the server-side opening or creating of a blob until an actual server-side operation (putting or getting a segment, or getting blob info). The open or create blob request is pipelined with the subsequent operation, avoiding a round trip to the server. This is especially noticeable in connections with high latency.

Artificial testing on local WiFi with small blobs shows around 85% increase in throughput (comparing a 6.0.1-SNAPSHOT against 6.0.0).

The Inline blob support for Firebird 5.0.3 and higher replaces this improvement for smallish blobs, but it still has benefit for blobs larger than `maxInlineBlobSize` or blobs that are discarded when the inline blob cache is full.

This optimization is available for Firebird 2.1 and higher, but formally only supported for Firebird 3.0 and higher.

For native connections, a similar optimization — but only for reading blobs — is available when using a Firebird 5.0.2 or higher fbclient, independent of the Jaybird version.

#### 7.14.4. Requesting known info items on open

Added in: Jaybird 6.0.1, backported from Jaybird 7

In the pure Java implementation, when an input blob is opened, all known blob information items are requested. Subsequent blob information requests on the same `FbBlob` handle are fulfilled using the cached information. If the request contains information items not in the cache, the request is sent to the server.

For access through JDBC, this optimization has little to no effect, as one of the few times Jaybird itself requests blob information is immediately after opening the blob, which is optimized by the deferred blob open. Direct use of `FirebirdBlob.BlobInputStream.length()` or the GDS-ng internal API may benefit from this change. We’re also investigating further changes to the implementation of Jaybird that could benefit from this.

This optimization is available for Firebird 2.1 and higher, but formally only supported for Firebird 3.0 and higher.

For native connections, a similar optimization is available when using a Firebird 5.0.2 or higher fbclient, independent of the Jaybird version.

#### 7.14.5. Inline blob support

Added in: Jaybird 6.0.2, backported from Jaybird 7

Introduced in Firebird 5.0.3 (protocol 19), inline blobs offer a significant performance improvement for querying smallish blobs. As the name suggests, blobs are sent inline together with the row data, avoiding additional round trips to the server for reading the blob data and blob information.

There are two connection properties affecting inline blobs:

`maxInlineBlobSize` (aliases: `max_inline_blob_size`, `isc_dpb_max_inline_blob_size`)

  Maximum size in bytes of the blob (default: `65535`).
  A value of `0` will disable sending of inline blobs.

  The maximum value is decided by the Firebird server, and is currently `65535`; this may change in the future

  If a blob is smaller than the specified size, the server will send it inline. The size includes segment lengths, so the actual maximum blob data received is `N * 2` bytes smaller, where N is the number of segments of the actual blob.

  The default can be changed with system property `org.firebirdsql.jdbc.defaultMaxInlineBlobSize`.

`maxBlobCacheSize` (aliases: `max_blob_cache_size`, `isc_dpb_max_blob_cache_size`)

  Maximum size in bytes — per connection — of the blob cache (default: `10485760` or 10 MiB).
  A value of `0` will disable the cache, but does not disable sending of inline blobs. Set `maxInlineBlobSize` to `0` to disable sending of inline blobs.

  For pure Java, only the data size is counted towards the cache size. For native, the segment lengths also count towards the cache size.

  The default can be changed with system property `org.firebirdsql.jdbc.defaultMaxBlobCacheSize`.

This feature works with pure Java and native connections when connecting to Firebird 5.0.3 or higher. For native connections, a Firebird 5.0.3 or higher client library must be used.

If the maximum blob cache size is reached, received inline blobs will be discarded. For pure Java connections, an inline blob is removed from the cache on first use, or when the transaction associated with the blob ends. The native client implementation may have different cache eviction rules.

As pure Java connections remove the inline blob from the cache on first use, subsequent attempts to read the same blob — by getting a different instance of `java.sql.Blob` or through multiple calls to the `ResultSet.getXXX` methods — will use a server-side blob. This can also happen if multiple columns or rows, even in different result sets on the same connection, point to the same blob id in the same transaction.

If you execute queries returning blobs, while those blobs are never actually opened, you may fill up the cache and later received inline blobs are then discarded. Especially in long-running transactions, this may reduce the effectiveness of this feature.

Artificial testing on local WiFi with small blobs (200 bytes) shows a 30,000-45,000% (yes, thousand)[5] increase in throughput comparing a 6.0.2-SNAPSHOT against 6.0.0, and a 15,000-25,000% increase in throughput comparing a 6.0.2-SNAPSHOT against 6.0.1.

#### 7.14.6. Minimum `blobBufferSize` 512 bytes

As part of the performance improvements, a minimum `blobBufferSize` of 512 bytes was introduced. Configuring values less than 512 will be ignored and use 512 instead.

#### 7.14.7. Maximum segment size raised

For connections to Firebird 3.0 and higher, the maximum segment size was raised from 32765 to 65535 bytes to match the maximum segment size supported by Firebird.

The maximum segment size is the maximum size for sending segments (put) to the server. Due to protocol limitations, retrieving segments from the server (get) is two bytes (or multiples of two bytes) shorter[6].

#### 7.14.8. Effectiveness of `blobBufferSize` larger than maximum segment size

Previously, when reading blobs, a `blobBufferSize` larger than the maximum segment size was effectively ignored. Now, when reading through an input stream, a `blobBufferSize` larger than the maximum segment size can be used.

Jaybird will use one or more roundtrips to fill the buffer. To avoid inefficient fetches, a minimum of 90% of the buffer size will be filled up to the `blobBufferSize`. This change is not likely to improve performance, but it may allow for optimizations when reading or transferring data in large chunks.

In general, setting the `blobBufferSize` larger than 65535 bytes will likely not improve performance.

#### 7.14.9. Internal API changes for `FbBlob`

Three new methods were added to `FbBlob`:

`int get(byte[] b, int off, int len)`

  populates the array `b`, starting at `off`, for the requested `len` bytes from the blob, and returns the actual number of bytes read. This method will read until `len` bytes have been read, and only return less than `len` when end-of-blob was reached.

`int get(byte[] b, int off, int len, float minFillFactor)`

  populates the array `b`, starting at `off`, for at least `minFillFactor` * `len` bytes (up to `len` bytes) from the blob, and returns the actual number of bytes read.

`void put(byte[] b, int off, int len)`

  sends data from array `b` to the blob, starting at `off`, for the requested `len` bytes.

The documentation of method `FbBlob.putSegment(byte[])` contradicted itself, by requiring implementations to batch larger arrays, but also requiring them to throw an exception for larger arrays, and the actual implementations provided by Jaybird threw an exception. This contradiction has been removed, and the implementations will now send arrays longer than the maximum segment size to the server in multiple put requests.

### 7.15. Support for executing transaction management statements

In Jaybird 5 and earlier, it was not possible to execute the transaction management statements `COMMIT`, `ROLLBACK` (without `RETAIN` or a savepoint) and `SET TRANSACTION`. For `COMMIT` and `ROLLBACK` it would seem to work, but subsequent use of the connection would then break because the connection assumed it still had an active transaction.

Formally, the JDBC specification says — paraphrased — that if something can be done through the JDBC API, that those API methods should be used; you should not use equivalent statements. However, from a perspective of flexibility, and for example for executing scripts, it can be useful to be able to execute those statements.

Jaybird now optionally allows you to execute `COMMIT [WORK]`, `ROLLBACK [WORK]` and `SET TRANSACTION […​]`. By default, Jaybird 6 explicitly rejects attempts to execute those statements, instead of the half-working/half-broken situation of previous versions.

To allow execution of `COMMIT [WORK]`, `ROLLBACK [WORK]` and `SET TRANSACTION […​]`, the connection property `allowTxStmts` needs to be set to `true`. This can be done using a JDBC connection property `allowTxStmts`, or `setAllowTxStmts(boolean)` on `DataSource` instances.

| Just because you can, doesn’t mean you should use this. For code solutions, you should use the normal methods in the JDBC API whenever possible. Only use this solution for scripts, or in case it is cumbersome or not possible to access the Jaybird extensions to the JDBC API to control the transaction configuration.

In the implementation, the use of `COMMIT` and `ROLLBACK` will not be executed as statements on the server, but instead call `Connection.commit()` and `Connection.rollback()`. The `SET TRANSACTION` statement — if allowed — is executed with execute immediate, and not through a statement handle.

| Contrary to its name, and the SQL standard behaviour, Firebird’s `SET TRANSACTION` immediately starts a transaction.

Enabling this feature can also make it easier to use the table reservation feature, compared to `FirebirdConnection.setTransactionParameters(TransactionParameterBuffer)` or `FirebirdConnection.setTransactionParameters(int, TransactionParameterBuffer)`, which requires access to the Jaybird API interfaces.

This feature has the following limitations:

- Transaction management statements cannot be executed when auto-commit is enabled, or if the connection is participating in a distributed transaction. This is the same behaviour as implemented for `Connection.commit()` and `Connection.rollback()`.

- Executing `COMMIT` or `ROLLBACK`— when auto-commit is disabled — is silently ignored if there is no active transaction. This is the same behaviour as implemented for `Connection.commit()` and `Connection.rollback()`.

- `SET TRANSACTION` cannot be executed if there is an active transaction. In other words, you will need to call `Connection.commit()` or execute `COMMIT` (or roll back) before you can start a new transaction this way.

- Transaction management statements are not supported by `Statement.addBatch(String)`, `PreparedStatement.addBatch()`, and `Connection.prepareCall(…​)`.

For more information, see also jdp-2024-01: Explicit support for transaction statements.

### 7.16. Configurable buffer sizes for the wire protocol

The sizes of a number of buffers used in the wire protocol were increased from 512 bytes to 8192 bytes. This specifically concerns:

- wire compression — deflate (compression)

- wire compression — inflate (decompression)

- wire encryption — decrypt

  There is no such buffer for the reverse (encryption), as this is already handled by the general output buffer.

This change might not be desirable in all situations as it increases the total amount of memory per connection, or there can be reasons to further increase these buffers. To address this, we have added system properties to configure a number of buffers which were previously not configurable:

`org.firebirdsql.wire.deflateBufferSize`

  Buffer size in bytes for deflate (compression). Has a minimum size of 512 and a default value of 8192.

`org.firebirdsql.wire.inflateBufferSize`

  Buffer size in bytes for inflate (decompression). Has a minimum size of 512 and a default value of 8192.

`org.firebirdsql.wire.decryptBufferSize`

  Buffer size in bytes for decryption. Has a minimum size of 512 and a default value 8192.

  | As the decryption input buffer determines the size of the decryption output buffer, the actual allocation is up to twice the specified value.

`org.firebirdsql.wire.inputBufferSize`

  Buffer size in bytes for reading data from the socket. Has a minimum size of 1024 and a default value of 16384.

  | This property should not be confused with the socket buffer size (configurable with the `socketBufferSize` connection property). Setting this value higher than `socketBufferSize` is unlikely to have any benefits.

`org.firebirdsql.wire.outputBufferSize`

  Buffer size in bytes for writing data. Has a minimum size of 1024 and a default value of 32767.

  | This property should not be confused with the socket buffer size (configurable with the `socketBufferSize` connection property). Contrary to the input buffer size, setting it higher than `socketBufferSize` might have performance benefits.

These properties need to be set before Jaybird is loaded and used (e.g. on the commandline with `-‍D<propertyName>=<propertyValue`).

| The minimum sizes and default values should be considered an implementation detail and might change in a future major version. The “deflate” and “inflate” buffers are only used when wire compression is enabled. The “decrypt” buffer is only applied when wire encryption is used (the default with Firebird 3.0 and higher).

The order of buffers for input is as follows:

    Jaybird ⇐ [inflate ⇐] [decrypt ⇐] input ⇐ socket

The order of buffers for output is as follows:

    Jaybird ⇒ output [⇒ deflate] ⇒ socket

A future version may introduce connection properties to control this per connection.

### 7.17. Broken connection detection for event manager

The event manager now attempts to detect if the underlying database connection is broken. Once a broken connection is detected, the event manager will attempt to close or forcibly disconnect itself and report itself as not connected.

For proper detection of some types of network problems in a timely manner, it may be necessary to configure the `soTimeout` of the event manager before connecting. When the `createFor(Connection)` method has been used, this can be configured through the `soTimeout` connection property, or — for pure Java connections only — the `setNetworkTimeout` method of the `Connection` object.

This detection depends on actual activity, like an event posting a new count, or a new event registration.

### 7.18. Connection property to specify native library path

A connection property `nativeLibraryPath` was added to specify the directory where `fbclient` (for native connections), or `fbembed` or `fbclient` (for embedded connections) can be loaded. If a file path is used instead of a directory path, the parent directory will be used for the search path. In other words, it is not possible to use it load a differently named library.

| This property comes with a very important caveat: it only works for the first native or embedded connection (to a database or service) made within a JVM. Once any client library is loaded, that library is used for all subsequent native and embedded connections.

This property is only exposed as a JDBC property. For data sources, it needs to be set with `setProperty(String, String)` or `setNonStandardProperty(String)`.

The primary use case for this property is for situations where configuring the system property `jna.library.path` is not easy to do (e.g. in third-party applications).

For embedded connections, if there is a valid `FirebirdEmbeddedProvider` on the classpath, it will be used instead of the location specified by `nativeLibraryPath`.

### 7.19. Rewritten client info properties support

Client info properties were introduced in JDBC 4.0 and implemented in Jaybird 2.2. This support has been rewritten to remove some limitations and correct some problems with the previous implementation.

The new implementation discerns two types of property names:

1. without context; get/set in `USER_SESSION` context of `RDB$GET/SET_CONTEXT`

2. with context, when the name ends in `@USER_SESSION`, `@USER_TRANSACTION` or `@SYSTEM`; get/set without that suffix in the specified context. Properties with multiple contexts (e.g. `property@SYSTEM@USER_SESSION`) are not allowed to prevent ambiguity. Everything else is a property without context.

A property named `<name>@USER_SESSION` is handled identical to `<name>`. The “without context” name is preferred and recommended for `USER_SESSION` properties, and `Connection.getClientInfo()` will use the “without context” name as the key for `USER_SESSION` properties.

A property named `<name>@USER_TRANSACTION` is set and get as `<name>` in context `USER_TRANSACTION`. When a connection is in auto-commit mode, attempts to set or get `USER_TRANSACTION` properties are ignored (nothing is stored, and `null` is returned without accessing the database).

A property named `<name>@SYSTEM` is retrieved as `<name>` in the context `SYSTEM`. Properties in the `SYSTEM` context are read-only, so they cannot be set. For `Connection.setClientInfo(String, String)`, attempts to set a `SYSTEM` property result in a `SQLClientInfoException`, for `Connection.setClientInfo(Properties)`, `SYSTEM` properties are silently ignored.

Attempts to retrieve non-existent properties, even from `SYSTEM` will return `null` and will not result in an exception.

A connection registers properties known to that specific connection. By default, only the JDBC-specified properties `ApplicationName`, `ClientUser` and `ClientHostName` (see also below) are known. A successful get or set of a property will register that property as a known property for the current connection only.

The method `Connection.getClientInfo()` will retrieve only known properties (the default properties and those registered for the current connection). It will not attempt to query or identify other variables registered in any context.

The method `Connection.setClientInfo(Properties)` clears (sets to `NULL`) known properties in `USER_SESSION` and — if not in auto-commit —`USER_TRANSACTION` if they are not included in the `Properties` object.

`DatabaseMetaData.getClientInfoProperties()` reports the JDBC-specified properties only; it will not report the additional properties registered for the current connection.

The JDBC-specified properties are:

> `ApplicationName`

>   The name of the application currently utilizing the connection

> `ClientUser`

>   The name of the user that the application using the connection is performing work for. This may not be the same as the username that was used in establishing the connection.

> `ClientHostname`

>   The hostname of the computer the application using the connection is running on.

JDBC API documentation of java.sql.Connection

All JDBC-specified properties are get and set in `USER_SESSION`. On get of `ApplicationName`, if this property is not currently set in `USER_SESSION`, it falls back to get the value from `CLIENT_PROCESS@SYSTEM`. The `CLIENT_PROCESS@SYSTEM` value can be specified using the connection property `processName` or system property `org.firebirdsql.jdbc.processName`. The `ClientUser` and `ClientHostname` properties are considered application-specific and have no default value or fallback.

Compared to the previous implementation, the important differences are:

- `Connection.getClientInfo()` now reports properties; the previous implementation always returned an empty `Properties` object.

- `Connection.getClientInfo(String)` with a property name without context now queries only `USER_SESSION`; the previous implementation queried `USER_TRANSACTION`, and if not set, fell back to the value from `USER_SESSION`. To retrieve from `USER_TRANSACTION` in the new implementation, use `<name>@USER_TRANSACTION`.

- `Connection.setClientInfo(Properties)` now clears known properties not included in the `Properties` object; the previous implementation only set the included properties.

- Successful get or set of a property registers it as known property of the connection and influences behaviour of subsequent calls to `getClientInfo()` and `setClientInfo(Properties)` on that connection

- `DatabaseMetaData.getClientInfoProperties` now reports the JDBC-specified properties, and nothing else; the previous implementation always returned an empty result set.

Connection pools and known connection properties

If you use a connection pool populated from `org.firebirdsql.ds.FBConnectionPoolDataSource` or `org.firebirdsql.ds.FBXADataSource`, the known properties are reset each time the connection is handed out by the pool. This assumes the pool uses `getConnection()` from `PooledConnection`/`XAConnection` each time it hands out the connection. This reset only removes the property name from the list of known properties, it does not clear the property values from `USER_SESSION`. If properties contain sensitive values you will need to explicitly clear them.

This reset is not applied when using a connection pool which is populated by different means (e.g. from `DriverManager` or from a normal `javax.sql.DataSource` like `org.firebirdsql.ds.FBSimpleDataSource`). If your connection pool implementation supports custom code to reset a connection, and you need known properties to reset when a connection is reused, make it call `FirebirdConnection.resetKnownClientInfoProperties()`, or call it yourself:

    if (connection.isWrapperFor(FirebirdConnection.class)) {
        connection.unwrap(FirebirdConnection.class)
                .resetKnownClientInfoProperties();
    }

In the future, Jaybird may be changed to also perform this reset in `Connection.beginRequest()` and/or `Connection.endRequest()`.

See also jdp-2023-11: New design client info properties

### 7.20. `TIMESTAMP` fields now accept `LocalDate` and `LocalTime`

The JDBC specification does not specify support for `LocalDate` and `LocalTime` on `TIMESTAMP` (without time zone). However, when we introduced support for the `java.time` types, we implemented support for getting `LocalDate` and `LocalTime` (through `getObject`), but did not provide support for setting values of those types (through `setObject`) on `TIMESTAMP`.

We have now addressed this inconsistency, by also introducing support for setting these types on `TIMESTAMP` with the following behaviour:

- `setObject(…​, localTime)` sets a `LocalDateTime` derived as `LocalDate.EPOCH.atTime(localTime)` (i.e. on 1970-01-01)

- `setObject(…​, localDate)` sets a `LocalDateTime` derived as `localDate.atStartOfDay()` (i.e. at 00:00:00)

### 7.21. `ResultSet` in auto-commit no longer closed after last row

In previous Jaybird versions, iterating over a forward-only result set in auto-commit mode would implicitly close the result set after the last row was fetched — i.e. when `next()` returned `false`. This behaviour complied with the JDBC 3.0 requirements, but in JDBC 4.0 this requirement was removed, but still allowed.

In Jaybird 6, this implicit close has been removed. In auto-commit mode, a result set will now remain open until explicitly closed using `ResultSet.close()`, when any statement is executed, when the auto-commit mode is disabled, or by the close of the `Statement` or `Connection`.

As a result set close is an auto-commit boundary, this change may delay commit of the active transaction until another action on the connection. If you relied on this implicit close for correctness of your application, you may need to add an explicit call to `ResultSet.close()`— e.g. using try-with-resources.

For more information, see also jdp-2024-03: Do not close result set after last row in auto-commit.

### 7.22. Changes to behaviour of updatable scrollable result sets

Jaybird 5 introduced support for server-side scrollable cursors on Firebird 5.0 and higher in the pure Java protocol. This can be enabled using the connection property `scrollableCursor=SERVER`.

For implementation reasons, updatable server-side scrollable cursors had a different behaviour than the emulated client-side scrollable cursors. These differences were:

- New rows are inserted at the end of the cursor; in emulated they were inserted immediately before the current row.

- Deleted rows have an all-`null` marker row; in emulated the row was removed from the cursor.

- The result set reports `true` for `rowDeleted()`, `rowInserted()` or `rowUpdated()` for — respectively — deleted, inserted or updated rows; in emulated these always reported `false`.

In Jaybird 6, this new behaviour is now also used for the updatable emulated scrollable cursors. The reason is that having two different sets of behaviours can be confusing, as it makes it impossible to switch between the two without having to account for the behavioural differences (either intentionally, or because you’re connecting with the native or embedded protocol, or to an older version of Firebird).

We’re considering to make server-side scrollable cursors the default in a future Jaybird version (Jaybird 7 or later).

See also jdp-2024-05: Behaviour of Updatable Result Sets.

### 7.23. Custom socket factory for pure Java connections

A custom socket factory can now be specified, to customize the creation of the `java.net.Socket` instance of a pure Java database or service connection.

The connection property `socketFactory` accepts the class name of an implementation of `javax.net.SocketFactory`. This socket factory is created anew for each connection. If `socketFactory` is not specified, Jaybird will use `SocketFactory.getDefault()` as its factory.

The `SocketFactory` implementation must adhere to the following rules:

- The class must have a public single-arg constructor accepting a `java.util.Properties` object, or a public no-arg constructor.

- The implementation of `SocketFactory#createSocket()` must return an unconnected socket; the other `createSocket` methods are not called by Jaybird.

  If you don’t want to implement the other `createSocket` methods, we recommend throwing `java.lang.UnsupportedOperationException` with a clear message from those methods.

It is possible to pass custom connection properties to the socket factory if it has a public single-arg constructor accepting a `Properties` object. Jaybird will instantiate the socket factory with a `Properties` object containing only the connection properties with the suffix `@socketFactory` and non-`null` values; non-string values are converted to string. In the future, we may also — selectively — pass other connection properties, but for now we only expose those properties that are explicitly set for the socket factory.

For example, say we have some custom socket factory called `org.example.CustomProxySocketFactory` with a `CustomProxySocketFactory(Properties)` constructor:

    var props = new Properties()
    props.setProperty("user", "sysdba");
    props.setProperty("password", "masterkey");
    props.setProperty("socketFactory", "org.example.CustomProxySocketFactory");
    props.setProperty("proxyHost@socketFactory", "localhost");
    props.setProperty("proxyPort@socketFactory", "1234");
    props.setProperty("proxyUser@socketFactory", "proxy-user");
    props.setProperty("proxyPassword@socketFactory", "proxy-password");

    try (var connection = DriverManager.getConnection(
            "jdbc:firebird://remoteserver.example.org/db", props)) {
        // use connection
    }

This will create the specified socket factory, passing a `Properties` object containing only the four custom properties ending in `@socketFactory`. The other properties — here `user`, `password` and `socketFactory`— are not passed to the socket factory.

See also jdp-2024-09: Custom socket factory for pure Java connections

### 7.24. Other fixes and changes

- Improvement: Setting oversized strings on `CHAR` or `VARCHAR` parameters with character set UTF8 will now throw a `DataTruncation` exception on `setString` (and not set a value) instead of a `SQLException` with a “string right truncation” error on execute (#396)

  With this change, the behaviour for UTF8 is now consistent with that of single-byte character sets. For UTF8, the `DataTruncation` reports the transfer size and data size in Unicode codepoints. For other multibyte character sets, the `DataTruncation` reports those sizes in bytes. This change is not applied to UNICODE_FSS, as Firebird 3.0 and earlier do not enforce character length limits for this character set, only byte length limits.

  The `setBytes` method on `CHAR` and `VARCHAR` parameters only check the byte length limit.

- Improvement: Implemented `java.sql.Connection.abort(Executor)` to forcibly abort a connection (#496)

  The `java.sql.Connection` is marked closed immediately, after which the executor is used to mark client-side statements and result sets as closed, and then closes the actual physical connection. The close of the physical connection is not a clean close and may result in “connection reset by peer” errors (e.g. error 10054 on Windows, error 104 on Linux) logged in `firebird.log`. Active transactions may not be rolled back immediately; this will be delayed until the server detects that the connection was closed. It is possible that some listeners are not informed of the connection, statement or result set close. When a security manager is active, calling `abort` requires the `SQLPermission` “callAbort”.

- Changed: `DatabaseMetaData.getTypeInfo()` column `FIXED_PREC_SCALE` (column 11) now returns `false` for all data types except `NUMERIC` and `DECIMAL` (#551)

  This was done because of the stated requirement “can it be a money value”. Previously almost all types returned `true` (including — for example —`BOOLEAN` and `TIMESTAMP`, which are definitely not money types).

- Consistent use of `BigDecimal.valueOf(double)` instead of a combination of `new BigDecimal(double)` and `BigDecimal.valueOf(double)` (#553)

- Switched blob identification in message BLR from `blr_quad` to `blr_blob2` (#726)

- Removed `finalize()` methods and — where it made sense — replaced them with use of `Cleaner` (#727)

- Fixed: `FBResultSetMetaData.getPrecision` would always estimate the precision of `NUMERIC` or `DECIMAL` columns instead of obtaining the actual precision if the column position was 71 or higher (#731)

  This fix was backported to Jaybird 5.0.5.

- Optimized the query to retrieve extended field info for `ResultSetMetaData.getPrecision` to only retrieve columns of type `NUMERIC` or `DECIMAL` (#732)

  This improvement was backported to Jaybird 5.0.5.

- Added methods `List<String> getTypeAliasList()` and `List<String> getSupportedProtocolList()` to `GDSFactoryPlugin`, and deprecated `String[] getTypeAliases()` and `String[] getSupportedProtocols()` for removal in Jaybird 7 or later

- Fixed formatting of `isc_formatted_exception` to not repeat the original parameters of the exception (#749)

- Added aliases `ApplicationName` and `applicationName` for connection property `processName` (#751)

- Fixed: on `CHAR` fields, a too short value could be returned if the string contained one or more codepoints represented by surrogate pairs and the string length in `char` exceeded the maximum string length (#760)

  We now truncate the returned string if the codepoint count exceeds the maximum string length.

  This change was also backported to Jaybird 5.0.3.

- Improvement: Do not reject attempts to read blob id 0 (#764)

  Previously, Jaybird rejected attempts to read blobs with blob id `0` (not on all code paths, for some only when assertions are enabled). Formally, blob id `0` is not a valid blob id, but in practice they can occur (e.g. due to bugs, or access components/drivers explicitly setting a blob column to id `0`). Other drivers and tools simply send the requests for blob id `0` to the server, which then treats it as an empty blob. For consistency, we decided to let Jaybird handle it the same.

  This change was also backported to Jaybird 5.0.3.

- Improvement: `Statement.getResultSet` no longer throws a `SQLException` with message “Only one result set at a time/statement” if the current result set has already been returned by `executeQuery` or a previous call to `getResultSet` (#762)

  Repeated calls to `getResultSet` will now return the current result set. As part of this change implementations of `FirebirdStatement.getCurrentResultSet` now simply returns `getResultSet`, and the `getCurrentResultSet` method has been deprecated for removal in Jaybird 7.

  This change was also backported to Jaybird 5.0.5.

- Fixed: The implementation of `Blob.getBytes(long, int)` threw a `SQLException` if the remaining bytes of the blob were less than the requested number of bytes (#767)

  The JDBC API specifies “This `byte` array contains up to `length` consecutive bytes starting at position pos.”, so the implementation was changed to return up to `length` bytes, or the remaining actual blob length, whichever is shorter.

  The JDBC API does not specify what should happen if the requested position is beyond the end-of-blob. The modified implementation returns an empty array, but given this is unspecified behaviour, we reserve the option to change this in the future to throw an exception instead.

- Fixed: `CallableStatement.getXXX(String)` could return value from wrong column (#771)

  This change was also backported to Jaybird 4.0.10 and Jaybird 5.0.3.

- `FBResultSetNotUpdatableException` now extends `SQLNonTransientException` instead of `FBSQLException`.

- Jaybird no longer throws any instances of `FBSQLException`.

  `FBSQLException` has been deprecated for removal in Jaybird 7.

- Fixed: FBRowUpdater incorrectly considers result set with only partial PK updatable (#780)

  This change also improves performance of `updateRow()`, `insertRow()`, `deleteRow()` and `refreshRow()`. The best row identifier or `RDB$DB_KEY` were detected each time when calling `updateRow()`, `insertRow()`, `deleteRow()`, or `refreshRow()`. This has been improved so this detection is done once, and in a way that non-updatable result sets can now be downgraded to `CONCUR_READ_ONLY` instead of throwing an exception when performing the modification.

  This change was backported to Jaybird 5.0.4.

- Improved detection of (non-)updatable result sets.

  If the best row identifier was not matched, but the result set contains `RDB$DB_KEY`, we will now consider the result set updatable. However, if the table in question has a primary key, and the columns missing from the result set are not generated, this may still fail when calling `ResultSet.insertRow()`.

- The user manager API (`UserManager`/`FBUserManager` and `User`/`FBUser` in package `org.firebirdsql.management`) has been deprecated (#782)

  We do not plan to remove this API at this time, but we recommend that you switch to using the SQL user management statements.

- Fixed: Use of offset timezone names (e.g. `+05:00`) for `sessionTimeZone` would result in a warning being logged, and an incorrect conversion applied (in UTC instead of the offset) when using the legacy time types (#786)

  This change was also backported to Jaybird 5.0.4.

- New feature: Added column `JB_PK_INDEX_NAME` to the result set of `DatabaseMetaData.getPrimaryKeys` with the name of the index backing the primary key (#791)

  Given this is a non-standard extension, it is advisable to retrieve this column by name, not by position.

- Improvement: `sessionTimeZone` now also accepts the Java offset names (`GMT[+-]HH:MM`), which will be automatically converted to the Firebird compatible name (`[+-]HH:MM`).

- New feature: `ResultSetMetaData.isAutoIncrement(int)` reports `true` for identity columns if Jaybird can identify the underlying table and column (#793)

  This feature was backported to Jaybird 5.0.5.

- New feature: Boolean connection property `extendedMetadata` (default `true`) to disable querying of extended metadata for `getPrecision(int)` and `isAutoIncrement(int)` of `ResultSetMetaData` (#795)

  Disabling extended metadata may improve performance of these `ResultSetMetaData` methods in exchange for estimated precision information of `NUMERIC` and `DECIMAL` columns, and not being able to determine the auto-increment status of `INTEGER`, `BIGINT` or `SMALLINT` columns.

  This feature was backported to Jaybird 5.0.5.

- Improvement: The `FILTER_CONDITION` of `DatabaseMetaData.getIndexInfo` is populated for Firebird 5.0 partial indices (#797)

  This improvement was backported to Jaybird 5.0.5.

- Improvement: Added column `JB_PK_INDEX_NAME` and `JB_FK_INDEX_NAME` to the result set of to `getImportedKeys`, `getExportedKeys` and `getCrossReference` of `DatabaseMetaData` with the names of the index backing the primary key and foreign key (#798)

  Given this is a non-standard extension, it is advisable to retrieve these columns by name, not by position.

- Change: `TYPE_FORWARD_ONLY` is no longer upgraded to `TYPE_SCROLL_INSENSITIVE` when requesting holdable result sets explicitly (holdability `HOLD_CUSORS_OVER_COMMIT`) or implicitly (`defaultResultSetHoldable=true` when not specifying holdability) (#802)

  See also Forward-only holdable result sets no longer upgraded to scroll-insensitive.

- Improvement: `isPoolable()` on `PreparedStatement` and `CallableStatement` now returns the default of `true`—`Statement` returns `false`— as required by JDBC, and `setPoolable` records the value set to be returned by `isPoolable` (#803)

  To be clear, Jaybird does not provide statement pooling. This change is only about returning and recording the poolable information for JDBC compliance, so it can be used by — for example — connection pool implementations that provide statement pooling.

- The state of `Connection.setReadOnly(boolean)` was not retained after calling `Connection.setTransactionIsolation(int)` or other method calls that changed the current transaction parameter buffer (#805)

- Fixed: Exceptions during statement execution did not always complete the statement, which could delay transaction commit in auto-commit mode (#806)

  This fix was backported to Jaybird 5.0.6.

- Fixed: `ResultSet.isBeforeFirst()` and `ResultSet.isAfterLast()` should always report `false` for an empty result set (#808)

- Most public classes in package `org.firebirdsql.jdbc` have been annotated with `@InternalApi` to reflect that they are not actually part of the public API of Jaybird.

  Informally, these classes were already considered internal API, but given they are `public`, we now explicitly and formally document their status for clarity.

  Where possible, use the standard JDBC interfaces. If you need access to Firebird-specifics, unwrap or cast to the `org.firebirdsql.jdbc.FirebirdXXX` interfaces. Only cast to or otherwise access the concrete classes of `org.firebirdsql.jdbc` if you really have to, and keep in mind that their API — if not defined in `java.sql` or `FirebirdXXX` interfaces — may change in point releases.

  If you have a clear use-case that currently requires access to the concrete implementation classes, and you think it should be possible through a public API, please let us know on firebird-java or the https://github.com/FirebirdSQL/jaybird/issues.

- Improvement: moved methods `getExecutionPlan()` and `getExplainedExcutionPlan()` from `FirebirdPreparedStatement` to `FirebirdStatement`, and clarified behaviour.

  We also fixed a potential `NullPointerException` in the implementation of these methods in `PreparedStatement` and `CallableStatement`.

  The methods `getLastExecutionPlan()` and `getLastExplainedExecutionPlan()` which were already defined in `FirebirdStatement` now have a default implementation that call `getExecutionPlan()` and `getExplainedExecutionPlan()`. These methods have been deprecated with the advice to use the new getters. For now, we have no plans to remove these methods in a future release.

- Added dependency on `org.jspecify:jspecify` for nullability annotations.

  We are working on adding nullability information where applicable, but right now annotation of Jaybird is far from complete, and this will generally only be added when we touch a class for other reasons. The addition of these annotations is intended for making it easier for us to reason about the implementation, and get static analysis warnings about possible programming errors. Hopefully it will — in time — provide some benefits for users of Jaybird’s extension interfaces and “internal” APIs.

  If a type or its containing package is not annotated, consider return values and parameters of its methods nullable unless stated otherwise in the API documentation.

  In practice, this is an optional dependency, but Maven will pull it in by default, as that is recommended by JSpecify. If the JSpecify JAR is not included on the classpath or modulepath, Jaybird will still work.

- `DatabaseMetaData` now reports `ResultSet.TYPE_SCROLL_SENSITIVE` as not supported, as it is always downgraded to `TYPE_SCROLL_INSENSITIVE`, and thus effectively not supported.

  This affects the return value of the methods `supportsResultSetType(int)`, `supportsResultSetConcurrency(int, int)`, `ownUpdatesAreVisible(int)`, `ownDeletesAreVisible(int)`, `ownInsertsAreVisible(int)`.

- Improvement: `setObject`/`updateObject` methods on `PreparedStatement`, `CallableStatement` and `ResultSet` with the `int scaleOrLength` parameter will now redirect to variants accepting a length of `set/updateBinaryStream` for `InputStream` and `set/updateCharacterStream` for `Reader` (#822)

- New feature: Reporting of `SQLWarning`s can be disabled with connection property `reportSQLWarnings` (supported case-insensitive values: `ALL` (default), `NONE`) (#825)

  The default can be overridden globally using system property `org.firebirdsql.jdbc.defaultReportSQLWarnings`.

## 8. Compatibility changes

Jaybird 6 introduces some changes in compatibility and announces future breaking changes.

The list might not be complete, if you notice a difference in behavior that is not listed, please report it as bug. It might have been a change we forgot to document, but it could just as well be an implementation bug.

### 8.1. Support for Firebird 2.5 dropped

Jaybird 6 has dropped support for Firebird 2.5 (see also jdp-2021-03: Drop Firebird 2.5 support).

By default, Jaybird 6 will only connect to Firebird 3.0 and higher. See also Unsupported protocol version disabled by default.

If the version 12 protocol (Firebird 2.5) is explicitly enabled, we expect the driver to remain functional, but chances are certain metadata — e.g. `DatabaseMetaData`— will break if we use features introduced in newer Firebird versions.

### 8.2. Unsupported protocol version disabled by default

The wire protocol versions for Firebird 2.5 and earlier are disabled by default to disallow connection for the pure Java protocol. Attempts to connect to Firebird 2.5 or earlier will result in error “connection rejected by remote interface” (`335544421` or `isc_connect_reject`). You can use connection property `enableProtocol=*` or — for example —`enableProtocol=10,11,12` to re-enable these protocols, or use the native protocol to connect instead.

As these protocols — and their Firebird versions — are not supported, it is possible things will break, especially for metadata — e.g. `DatabaseMetaData` if we use features introduced in newer Firebird versions.

See also Pure Java will not connect to unsupported Firebird versions by default.

### 8.3. Support for Java versions before Java 17 dropped

Jaybird 6 does not support Java versions before Java 17. You will need to upgrade to Java 17 or higher, or remain on Jaybird 5.

Jaybird 5 will serve as a form of “long-term support” for Java 8 and 11, with maintenance releases at least until the release of Jaybird 7.

### 8.4. Native and embedded require extra artifact

The main `jaybird` artifact no longer provides native and embedded support. Add the `jaybird-native` artifact if you use native or embedded (JDBC URL prefix `jdbc:firebird[sql]:native:` or `jdbc:firebird[sql]:embedded:`).

See also NATIVE and EMBEDDED support moved to a separate artifact.

### 8.5. Support for jdbc:firebirdsql:oo: (OpenOffice/LibreOffice driver) dropped

The OOREMOTE protocol (JDBC URL prefix `jdbc:firebird[sql]:oo:`) has been removed in Jaybird 6.

The recommended replacement is to use LibreOffice and the builtin “Firebird External” connection option in LibreOffice Base, instead of the “JDBC” option with Jaybird on the classpath of LibreOffice.

### 8.6. Removed connection property timestampUsesLocalTimezone

The connection property `timestampUsesLocalTimezone` has been removed. The exact semantics and usage of this property were unclear. It was previously deprecated in Jaybird 5 for removal in Jaybird 6 or later.

Other code associated with this property was also removed.

### 8.7. Differences in client info property behavior

The rewritten client info properties implementation may result in the following incompatibilities:

- `setClientInfo(Properties)` will now clear all known properties of `USER_SESSION` and — if not in auto-commit —`USER_TRANSACTION` which are not included in the `Properties` object; Jaybird 5 and earlier only set properties listed in the `Properties` object. The recommended approach is to use `getClientInfo()`, modify the returned `Properties` object (update values, add new properties, and remove properties which should be cleared), and call `setClientInfo(Properties)` with that object.

- Initially, a connection only knows the properties `ApplicationName`, `ClientUser` and `ClientHostname`. Other properties are registered for the current connection when getting or setting properties.

- `getClientInfo(String)` with a name without context will now always return the value from `USER_SESSION`; Jaybird 5 and earlier returned the value in `USER_TRANSACTION` and fell back to `USER_SESSION` if the property did not exist in `USER_TRANSACTION`. To get the value from `USER_TRANSACTION`, use `<name>@USER_TRANSACTION`.

- If the property `ApplicationName` in `USER_SESSION` has no value, it falls back to `CLIENT_PROCESS` in `SYSTEM` (which reports the value of the `processName` connection property); Jaybird 5 and earlier reported `null` without falling back.

See also Rewritten client info properties support.

### 8.8. New Operation.Type value for async fetch

With the introduction of async fetch, the `org.firebirdsql.gds.ng.monitor.Operation.Type` enum has two new values added:

`STATEMENT_ASYNC_FETCH_START` | Start of async fetch. Covers sending of the fetch request. This operation is cancellable.
`STATEMENT_ASYNC_FETCH_COMPLETE` | Completion of async fetch. Covers processing the responses of the fetch request. This operation is not cancellable. Attempts to cancel this operation will throw an exception.

If you’re currently using the `OperationAware` interface to monitor and/or cancel fetches, make sure to also process `STATEMENT_ASYNC_FETCH_START` and/or `STATEMENT_ASYNC_FETCH_COMPLETE` as appropriate.

### 8.9. Changes in datetime conversions

The conversions of datetime values were overhauled to use the `java.time` types wherever possible.

This results in some minor differences:

- `getString(…​)` on a `TIME` field will now render fractional seconds if available

- `setString(…​)` on a `TIME` field now has seconds optional and accepts fractional seconds

- `setTime(…​)` on a `TIME` field will not set sub-second values (previously this could vary with the millisecond value wrapped by `java.sql.Time`)

- `getString(…​)` on a `TIMESTAMP` field will now render without `.0` at the end if the value does not have fractional seconds (e.g. `2023-07-22 12:43:45` instead of `2023-07-22 12:43:45.0`)

- `setString(…​)` on a `TIMESTAMP` field now has seconds optional

- `setString(…​)` on a `TIMESTAMP` field now also accepts ISO 8601 datetime strings (that is, with a `T` as a separator instead of a space, for example, `2023-07-22 12:43:45` and `2023-07-22T12:43:45` are now both accepted)

- `setDate(…​)` on a `TIMESTAMP` field now sets time to 00:00:00 (previously this could vary with the millisecond value wrapped by `java.sql.Date`)

- `setTime(…​)` on a `TIMESTAMP` field will now always set at 1970-01-01, and will not set sub-second values (previously this could vary with the millisecond value wrapped by `java.sql.Time`)

- `setTimestamp(…​)` on a `CHAR`/`VARCHAR`/`BLOB SUB_TYPE TEXT` field will now set the value without `.0` at the end if the value does not have fractional seconds (e.g. `2023-07-22 12:43:45` instead of `2023-07-22 12:43:45.0`)

- `getTimestamp(…​)` on a `CHAR`/`VARCHAR`/`BLOB SUB_TYPE TEXT` field will now also parse ISO 8601 datetime strings (that is, with a `T` as a separator instead of a space, for example, `2023-07-22 12:43:45` and `2023-07-22T12:43:45` are now both accepted), and seconds are now optional

- `getTime(…​)` on a `CHAR`/`VARCHAR`/`BLOB SUB_TYPE TEXT` field will now parse values without seconds and values with fractional seconds. Though it can parse it, the resulting value will not include fractional seconds.

- `setDate(…​, Calendar)` on a `CHAR`/`VARCHAR`/`BLOB SUB_TYPE TEXT` field will now use the `Calendar` to rebase the date, this can result in an off-by-one difference in the date compared to previous versions (depending on the time zone set on the `Calendar`)

- `getDate(…​, Calendar)` on a `CHAR`/`VARCHAR`/`BLOB SUB_TYPE TEXT` field will now use the `Calendar` to rebase the date, this can result in an off-by-one difference in the date compared to previous versions (depending on the time zone set on the `Calendar`)

- The `TypeConversionException` thrown by `getDate(…​)`, `getTime(…​)` and `getTimestamp(…​)` on unsupported types may now report `java.time.LocalDate`, `java.time.LocalTime` or `java.time.LocalDateTime` as the type in its error message instead of `java.sql.Date`, `java.sql.Time`, or `java.sql.Timestamp`

### 8.10. Execution of `COMMIT` and `ROLLBACK` rejected by default

Attempts to prepare or execute `COMMIT` or `ROLLBACK` (without `RETAIN` or a savepoint) will now fail by default. In previous versions, executing these statements would work, but leave the connection in an unusable state. The exact error will — generally — be one of the following:

`337248313` | “Execution of COMMIT statement is not allowed, use Connection.commit(), or set connection property allowTxStmts to true”
`337248314` | “Execution of ROLLBACK statement is not allowed, use Connection.rollback(), or set connection property allowTxStmts to true”
`337248319` | “Using addBatch with a transaction management statement is not supported”
`337248320` | “Using prepareCall with a transaction management statement is not supported”

In the case of the `execute`, `executeUpdate` or `executeLargeUpdate` methods of `Statement`, or the `prepareStatement` methods of `Connection`, this can be resolved by allowing the execution with connection property `allowTxStmts` set to `true`.

In the case of `Statement.executeQuery(String)` and `PreparedStatement.executeQuery()`, you will need to switch to using one of the other `execute`, `executeUpdate` or `executeLargeUpdate` methods.

It is not possible to use the `prepareCall` methods of `Connection` with these statements. In previous versions of Jaybird, subsequent execution wouldn’t work either — or attempt to execute stored procedures called `COMMIT` or `ROLLBACK`, but it is now rejected early in the `prepareCall` methods of `Connection`. Switch to using `prepareStatement`.

Additionally, using `Statement.addBatch(String)` and `PreparedStatement.addBatch()` will not work with these statements. Switch to using one of the normal execute methods.

See also Support for executing transaction management statements.

### 8.11. Forward-only holdable result sets no longer upgraded to scroll-insensitive

Jaybird no longer upgrades `TYPE_FORWARD_ONLY` holdable result sets to `TYPE_SCROLL_INSENSITIVE`. As a result, for these result sets, only the `next()` navigation method is allowed, and other navigation methods will throw an `SQLException`, just like a forward-only non-holdable result set.

In previous versions, this upgrade occurred when creating a `TYPE_FORWARD_ONLY` result set, either explicitly when asking for holdability `HOLD_CURSORS_OVER_COMMIT`, or implicitly when `defaultResultsetHoldable=true` (or `defaultHoldable=true` or `result_set_holdable=true`) was set and no holdability was specified for the statement itself.

If you relied on this type upgrade to access navigation methods other than `next()`, you will need to explicitly ask for a `TYPE_SCROLL_INSENSITIVE` result set.

### 8.12. Read-only behaviour of connections

In previous versions of Jaybird the read-only state of a connection was not retained if the transaction parameter buffer was replaced, for example by calls to `setTransactionIsolation(int)`.

Now this has been corrected, it is possible that your code unexpectedly throws an exception with message “attempted update during read-only transaction [SQLState:25006, ISC error code:335544361]” (error `isc_read_only_trans`).

You need to make sure to call `setReadOnly(false)` if the connection was previously marked read-only. If you’re using a connection pool, you need to ensure it properly resets the read-only state of the connection when checking in or checking out the connection. For example, both Apache DBCP and Apache Tomcat connection pools requires the `defaultReadOnly` property to be set (i.e. to `false`), otherwise it will not reset the read-only state.

If overridden transaction mappings are used, and the default isolation level has `isc_tpb_read`, the connection will be marked as read-only. As a result, switching isolation levels will now also result in read-only transactions, even if the mapping of the other isolation level is defined with `isc_tpb_write`. You will need to explicitly call `setReadOnly(false)`, or — better yet — do not override transaction mappings with a `isc_tpb_read`, but always use `isc_tpb_write`, and control read-only state only through `setReadOnly`.

### 8.13. `ResultSet` in auto-commit no longer closed after last row

For more information, see `ResultSet` in auto-commit no longer closed after last row.

### 8.14. Behavioural changes for updatable scrollable `ResultSet`

For more information, see Changes to behaviour of updatable scrollable result sets.

### 8.15. Some packages not accessible when Jaybird is on the modulepath

Due to modularization, the following packages are no longer accessible when Jaybird is used from the modulepath:

#### 8.15.1. `jaybird` dependency

- `org.firebirdsql.gds.ng.dbcrypt.simple`

- `org.firebirdsql.gds.ng.tz`

- `org.firebirdsql.gds.ng.wire.auth.legacy`

- `org.firebirdsql.gds.ng.wire.auth.srp`

- `org.firebirdsql.gds.ng.wire.crypt.arc4`

- `org.firebirdsql.gds.ng.wire.crypt.chacha`

- `org.firebirdsql.gds.ng.wire.versionNN` (with NN, is `10`, `11`, `12`, `13`, `15`, `16` and `18`)

- `org.firebirdsql.jaybird`

- `org.firebirdsql.jaybird.parser`

- `org.firebirdsql.jaybird.props.internal`

- `org.firebirdsql.jaybird.util`

- `org.firebirdsql.jdbc.escape`

- `org.firebirdsql.jdbc.meta`

#### 8.15.2. `jaybird-native` dependency

- `org.firebirdsql.gds.impl.jni`

- `org.firebirdsql.gds.ng.jna`

- `org.firebirdsql.jna.embedded`

- `org.firebirdsql.jna.fbclient`

### 8.16. Removal of classes, packages and methods without deprecation

Below list of removals may look daunting, but if you use Jaybird only as a JDBC driver, through the JDBC API, you’re likely unaffected. Although we list them as removed without deprecation, some were marked as deprecated retroactively in Jaybird 5.0.3 or later.

This section does not include all changes to packages or classes considered internal API.

#### 8.16.1. Removal of packages without deprecation

The following packages have been removed in Jaybird 6 without deprecation:

- `org.firebirdsql.logging`; there is no replacement

#### 8.16.2. Removal of methods without deprecation

The following methods have been removed in Jaybird 6 without deprecation:

- `FBConnection`

  - `prepareMetaDataStatement(String, int, int)`; use `prepareStatement(String, int, int, int, boolean, boolean)`

  - `getStatementListener()`; there is no replacement

  - `inTransaction()`; there is no replacement

- `JaybirdSystemProperties`

  - `isForceConsoleLogger()`; there is no replacement

  - `isDisableLogging()`; there is no replacement

  - `getLoggerImplementation()`; there is no replacement

- `FBCallableStatement`

  - `findOutParameter(String)` (protected); use `getAndAssertSingletonResultSet().findColumn(paramName)`; carefully check if that is the correct usage (the method was removed because the old usage within Jaybird resulted in mapping the wrong column)

- `FBProcedureCall`

  - `mapOutParamIndexToPosition(int, boolean)`; use `mapOutParamIndexToPosition(int)` (equivalent to passing `true`), there is no replacement for the `false` behaviour

#### 8.16.3. Removal of classes without deprecation

The following classes have been removed in Jaybird 6 without deprecation:

- `FbLocalDatabaseFactory`— unused since removal of LOCAL protocol implementation in Jaybird 5.

- `DatatypeCoder.RawDateTimeStruct` (semi-internal API) — use one of the `java.time` types (`LocalDateTime`, `LocalDate` or `LocalTime`). Though this class was publicly accessible through `ResultSet.getObject/updateObject` and `PreparedStatement.setObject`, it is internal API, and we expect it is unlikely to be actually used in user code.

- `FBDriverConsistencyCheckException`— unused since the changes to client info properties.

The following classes are no longer accessible in Jaybird 6:

- `RowValueBuilder` is now package private

The following classes are no longer extensible in Jaybird 6 as they are now `sealed` or `final`:

- `FBPooledConnection`

  - Visibility was also reduced to package-private

- `FBXAConnection`

  - Visibility was also reduced to package-private

- `PooledConnectionHandler`

  - Class was already package-private

- `XAConnectionHandler`

  - Visibility was also reduced to package-private

- `StoredProcedureMetaDataFactory`

  - Visibility was also reduced to package-private

#### 8.16.4. Removal of constants without deprecation

The following constants have been removed in Jaybird 6 without deprecation:

- `JaybirdSystemProperties`

  - `FORCE_CONSOLE_LOGGER_PROP`; there is no replacement

  - `DISABLE_LOGGING_PROP`; there is no replacement

  - `LOGGER_IMPLEMENTATION_PROP`; there is no replacement

- `SQLStateConstants`

  - `SQL_STATE_INVALID_CONN_ATTR` (`01S00`) — it was unused; there is no replacement

  - `SQL_STATE_INVALID_COLUMN` (`HY002`); replaced by `SQL_STATE_INVALID_DESC_FIELD_ID` (`HY091`)

  - `SQL_STATE_INVALID_ARG_VALUE` (`HY009`); used with wrong meaning, replaced by multiple other constants (`SQL_STATE_INVALID_USE_NULL` (`HY009`, same value), `SQL_STATE_ATT_CANNOT_SET_NOW` (`HY011`) , `SQL_STATE_INVALID_ATTR_VALUE` (`HY024`), `SQL_STATE_INVALID_STRING_LENGTH` (`HY090`))

  - `SQL_STATE_INVALID_TRANSACTION_STATE` (`25S01`) — it was unused; there is no replacement

  - `SQL_STATE_TRANSACTION_ACTIVE` (`25S02`) — it was unused; there is no replacement

  - `SQL_STATE_TRANSACTION_ROLLED_BACK` (`25S03`) — it was unused; there is no replacement

  - `SQL_STATE_CONNECTION_FAILURE_IN_TX` (`08007`) — it was unused; there is no replacement

  - `SQL_STATE_COMM_LINK_FAILURE` (`08S01`) — it was unused; there is no replacement

- `FBProcedureCall`

  - `OLD_CALLABLE_STATEMENT_COMPATIBILITY`; there is no replacement

### 8.17. Removal of deprecated classes, packages and methods

Below list of removals may look daunting, but if you use Jaybird only as a JDBC driver, through the JDBC API, you’re likely unaffected.

#### 8.17.1. Removal of deprecated packages

The following packages have been removed in Jaybird 6:

- `org.firebirdsql.gds.impl.oo`

- `org.firebirdsql.jdbc.oo`

#### 8.17.2. Removal of deprecated methods

The following methods have been removed in Jaybird 6:

- `FirebirdConnectionProperties`
  Changes to the `FirebirdConnectionProperties` interface affect the data source implementations in `org.firebirdsql.ds`, and `FBManagedConnectionFactory`.

  - `getDatabase()` and all its implementations; use `DatabaseConnectionProperties.getDatabaseName()`

  - `setDatabase(String)` and all its implementations; use `DatabaseConnectionProperties.setDatabaseName(String)`

  - `getNonStandardProperty(String)` and all its implementations; use `BaseProperties.getProperty(String)`

  - `setNonStandardProperty(String,String)` and all its implementations; use `BaseProperties.setProperty(String,String)`

  - `getBuffersNumber` and all its implementations; use `DatabaseConnectionProperties.getPageCacheSize`

  - `setBuffersNumber` and all its implementations; use `DatabaseConnectionProperties.setPageCacheSize`

- `IConnectionProperties`

  - `short getConnectionDialect()` and all its implementations; use `int DatabaseConnectionProperties.getSqlDialect()`

  - `setConnectionDialect(short)`, and all its implementations; use `DatabaseConnectionProperties.setSqlDialect(int)`

- `FBSimpleDataSource.get/setBlobBufferLength`; use `get/setBlobBufferSize`

- `EventManager`

  - `get/setHost`; use `get/setServerName`

  - `get/setPort`; use `get/setPortNumber`

  - `get/setDatabase`; use `get/setDatabaseName`

- `GDSFactory.getJdbcUrl(GDSType, String)`; use `GDSFactory.getJdbcUrl(GDSType, DatabaseConnectionProperties)`

- `FBManagedConnection.getDatabase()`; there is no direct replacement, but the information can be obtained from the connection properties

- `GDSHelper.getIscEncoding()`; there is no replacement

- `FirebirdConnection.getIscEncoding`; there is no replacement

- `FBBlob`

  - constructors `FBBlob(GDSHelper)` and `FBBlob(GDSHelper, FBObjectListener.BlobListener)`; use `FBBlob(GDSHelper, FBObjectListener.BlobListener, Config)`

  - constructors `FBBlob(GDSHelper c, long blobId)` and `FBBlob(GDSHelper c, long blobId, FBObjectListener.BlobListener blobListener)`; use `FBBlob(GDSHelper, long, FBObjectListener.BlobListener, Config)`

- `DatabaseConnectionProperties`

  - `isTimestampUsesLocalTimezone`/`setTimestampUsesLocalTimezone(boolean)`; there is no replacement

- `FBSQLException`

  - constructor `FBSQLException(String, SQLException)`; use `FBSQLException(String)` or `FBSQLException(String, String)` followed by `setNextException(SQLException)`

  - `getInternalException()`; use `getCause()`

- `FBServiceManager`

  - `executeServicesOperation(ServiceRequestBuffer)`; use `executeServicesOperation(FbService, ServiceRequestBuffer)`

- `FirebirdDriver` (and `FBDriver`)

  - `newConnectionProperties()`— was not previously deprecated, see next method

  - `connect(FirebirdConnectionProperties)`; use `FBSimpleDataSource` for programmatic access to connection properties and connection creation

#### 8.17.3. Removal of deprecated classes

The following classes have been removed in Jaybird 6:

- `org.firebirdsql.gds.ng.listeners.DefaultDatabaseListener`; implementing `DatabaseListener` is now sufficient as all methods in the interface now have a default implementation that does nothing

- `org.firebirdsql.gds.ng.listeners.DefaultStatementListener`; implementing `StatementListener` is now sufficient as all methods in the interface now have a default implementation that does nothing

- `org.firebirdsql.jdbc.FBConnectionDefaults`; its replacement, `org.firebirdsql.jaybird.props.PropertyConstants`, is considered internal API

#### 8.17.4. Removal of deprecated constants

The following constants have been removed in Jaybird 6:

- All public String constants in `FBDriver`; the replacement for most constants can be found in `org.firebirdsql.jaybird.props.PropertyNames`, though some will be removed without replacement

- `ISCConstants.isc_dpb_*` that are DPB items; the replacement is the constant with the same name in `org.firebirdsql.jaybird.fb.constants.DpbItems`

- `ISCConstants.isc_tpb_*` that are TPB items; the replacement is the constant with the same name in `org.firebirdsql.jaybird.fb.constants.TpbItems`

- `ISCConstants.isc_spb_*` that are SPB items; the replacement is the constant with the same name in `org.firebirdsql.jaybird.fb.constants.SpbItems`

- `ISCConstants.isc_bpb_*` that are BPB items; the replacement is the constant with the same name in `org.firebirdsql.jaybird.fb.constants.BpbItems`

- `ISCConstants.isc_bpb_type_segmented` and `ISCConstants.isc_bpb_type_stream`; the replacement is the constant with the same name in `org.firebirdsql.jaybird.fb.constants.BpbItems.TypeValues`

- All constants in `DatabaseParameterBuffer`; use the equivalent constant from `org.firebirdsql.jaybird.fb.constants.DpbItems`

- All constants in `TransactionParameterBuffer`; use the equivalent constant from `org.firebirdsql.jaybird.fb.constants.TpbItems`

- All constants in `ServiceParameterBuffer`; use the equivalent constant from `org.firebirdsql.jaybird.fb.constants.SpbItems`

- All constants in `BlobParameterBuffer`; use the equivalent constant from `org.firebirdsql.jaybird.fb.constants.BpbItems` and `org.firebirdsql.jaybird.fb.constants.BpbItems.TypeValues`

- All `TPB_*` constants in `FirebirdConnection`; use the equivalent constant from `org.firebirdsql.jaybird.fb.constants.TpbItems`

- All public String constants in `org.firebirdsql.jdbc.FBConnectionProperties`; the replacement for most constants can be found in `org.firebirdsql.jaybird.props.PropertyNames`, though some will be removed without replacement

- `GDSHelper.DEFAULT_BLOB_BUFFER_SIZE`; its replacement, `org.firebirdsql.jaybird.props.PropertyConstants.DEFAULT_BLOB_BUFFER_SIZE`, is considered internal API

- All constants in `IConnectionProperties`; use the equivalent constant from `org.firebirdsql.jaybird.props.PropertyConstants`, though this class is considered internal API

- All constants in `IServiceProperties`; use the equivalent constant from `org.firebirdsql.jaybird.props.PropertyConstants`, though this class is considered internal API

- `PropertyNames.timestampUsesLocalTimezone`; there is no replacement

### 8.18. Breaking changes internal API

The following breaking changes were made to the internal API, like the GDS-ng API in `org.firebirdsql.gds.ng` and sub-packages. These changes are primarily interesting for implementers of custom GDS-ng implementations or forks of Jaybird, or people using these low-level APIs directly.

| Only changes we think are relevant to driver implementers or (internal) API users are documented. This means there may be undocumented changes to internal API. If you are confronted with such a change, let us know on firebird-java, so we can take this into account when documenting future changes.

- `FbWireDatabase`

  - `enqueueDeferredAction(DeferredAction)` now throws `SQLException` to be able to handle exceptions for sync actions if there are a lot of deferred packets

- `FbWireOperations`

  - `enqueueDeferredAction(DeferredAction)` now throws `SQLException` (see also `FbWireDatabase` above)

- `AbstractFbStatement`

  - `setCursorName(String)` is now final; subclasses need to implement `setCursorNameImpl(String)` to provide the actual implementation. These implementations do not need to take out the lock, nor notify the exception listener dispatcher, as that is already handled in the final `setCursorName(String)` method.

  - The most recent cursor name is now accessible with `protected String getCursorName()`. Its value is reset to `null` on each prepare.

- `AbstractFbWireStatement`

  - `close()` is now final

  - `wrapDeferredResponse` received an extra parameter, `boolean requiresSync`. This parameter signals if the deferred response requires some form of synchronization action to instruct the server to send the response. When in doubt, use `false` to communicate that no such synchronization is required.

- `JnaDatabase`

  - `getEncodingDefinition` was removed; there is no replacement

- `DeferredAction`

  - `wrapDeferredResponse` received an extra parameter, `boolean requiresSync`. This parameter signals if the deferred response requires some form of synchronization action to instruct the server to send the response. When in doubt, use `false` to communicate that no such synchronization is required.

- `AsynchronousChannelListener.Event` was converted to a record, so it is now final, and its getters (`getEventId()` and `getEventCount()`) have been replaced by accessor methods (`eventId()` and `eventCount()`)

- `DbAttachInfo` was converted to a record, so its getters (`getServerName()`, `getPortNumber()` and `getAttachObjectName()`) have been replaced by accessor methods (`serverName()`, `portNumber()`, `attachObjectName()`)

- `XdrInputStream`

  - `skipPadding` return type was changed to `void` as the return value is never used in Jaybird code

  - `skipFully` was removed; use standard Java `InputStream.skipNBytes` instead

  - `readShort` was removed as it was unused

- The no-arg constructor of `FBXAException` was removed

- `FBResultSet`

  - `close(boolean)` was removed; use `close(boolean, CompletionReason)`

- `FBProcedureCall` is no longer cloneable; use `FBProcedureCall.copyOf(FBProcedureCall)`

- `UnixCrypt` was replaced by `LegacyHash`, which only performs the password hash specific to Firebird legacy authentication

- `GDSFactoryPlugin.getDatabasePath(String, Integer, String)` and `getDatabasePath(String)` no longer throw `GDSException`, but instead throw `SQLException`

- `GDSFactory.getDatabasePath(…​)` no longer throw `GDSException`, but instead throw `SQLException`

- `GDSServerVersionException` no longer extends `GDSException`, but instead extends `SQLNonTransientException`

- `GDSException` was significantly modified and deprecated for future removal. Most of its implementation was removed, and it now extends `SQLException`. Only the constructors `GDSException(int)`, `GDSException(int, Throwable)` and `GDSException(String)` were retained. All other constructors and methods have been removed.

- `WireGDSFactoryPlugin`, `NativeGDSFactoryPlugin` and `EmbeddedGDSFactoryPlugin` are now final

- `FbEmbeddedDatabaseFactory` is now final

- `FbClientDatabaseFactory` and `FbEmbeddedDatabaseFactory` now have a private constructor; use their static `getInstance()` method to obtain an instance

- `DefaultDatatypeCoder.intToBytes(int)` was removed; use `encodeInt(int)`

- `ChaChaEncryptionPlugin` and `ChaChaEncryptionPluginSpi` are now final

- `CryptSessionConfig`, the JavaBeans-style accessors have been replaced with record-style accessors:

  - `getEncryptionIdentifier()` → `encryptionIdentifier()`

  - `getEncryptKey()` → `encryptKey()`

  - `getDecryptKey()` → `decryptKey()`

  - `getSpecificData()` → `specificData()`

- `EncryptionIdentifier`, some JavaBeans-style accessors have been replaced with record-style accessors:

  - `getType()` → `type()`

  - `getPluginName()` → `pluginName()`

- `KnownServerKey.PluginSpecificData`, the JavaBeans-style accessors have been replaced with record-style accessors:

  - `getEncryptionIdentifier()` → `encryptionIdentifier()`

  - `getSpecificData()` → `specificData()`

- `EncryptionPlugin` and `EncryptionPluginSpi`, the JavaBeans-style accessor has been replaced with a record-style accessor:

  - `getEncryptionIdentifier()` → `encryptionIdentifier()`

- `StringArgument`

  - constructor `StringArgument(int, ArgumentType, String)`; use `StringArgument(int, ArgumentType, String, Encoding)`

- `FBConnection`

  - `checkClientInfoSupport()` was removed; there is no replacement

- `IEncodingFactory`

  - `<T extends DatatypeCoder> T getOrCreateDatatypeCoder(Class<T>)` was removed; its replacements is `<T extends DatatypeCoder> T getOrCreateDatatypeCoder(Class<T>, Function<IEncodingFactory, T>)` where the function is a factory for the desired `DatatypeCoder` instance if it doesn’t already exist.

- The following classes in `org.firebirdsql.util` were moved to `org.firebirdsql.jaybird.util`. This package is internal API only, and not exported from the module.

  - `ByteArrayHelper`

  - `ExceptionHelper`

  - `IOUtils`

  - `Primitives`

  - `ReflectionHelper`

  - `SQLExceptionChainBuilder`

  - `StringUtils`

- `DbMetadataMediator` was moved to package `org.firebirdsql.jdbc` for module accessibility reasons.

- `DatatypeCoder`

  - `encodeTimestamp(Timestamp, Calendar, boolean)` was removed; there is no replacement

  - `decodeTimestamp(Timestamp, Calendar, boolean)` was removed; there is no replacement

  - `encodeTimestampCalendar(Timestamp, Calendar)` was removed; use `encodeLocalDateTime(LocalDateTime)`

  - `decodeTimestampCalendar(byte[], Calendar)` was removed; use `decodeLocalDateTime(byte[])`

  - `encodeTimestampRaw(DatatypeCoder.RawDateTimeStruct)` was removed; use `encodeLocalDateTime(LocalDateTime)`

  - `decodeTimestampRaw(byte[])` was removed; use `decodeLocalDateTime(byte[])`

  - `encodeTime(Time, Calendar, boolean)` was removed; there is no replacement

  - `decodeTime(Time, Calendar, boolean)` was removed; there is no replacement

  - `encodeTimeCalendar(Time, Calendar)` was removed; use `encodeLocalTime(LocalTime)`

  - `decodeTimeCalendar(byte[], Calendar)` was removed; use `decodeLocalTime(byte[])`

  - `encodeTimeRaw(DatatypeCoder.RawDateTimeStruct)` was removed; use `encodeLocalTime(LocalTime)`

  - `decodeTimeRaw(byte[])` was removed; use `decodeLocalTime(byte[])`

  - `encodeDate(Date, Calendar)` was removed; there is no replacement

  - `decodeDate(Date, Calendar)` was removed; there is no replacement

  - `encodeDateCalendar(Date, Calendar)` was removed; use `encodeLocalDate(LocalDate)`

  - `decodeDateCalendar(byte[], Calendar)` was removed; use `decodeLocalDate(byte[])`

  - `encodeDateRaw(DatatypeCoder.RawDateTimeStruct)` was removed; use `encodeLocalDate(LocalDate)`

  - `decodeDateRaw(byte[])` was removed; use `decodeLocalDate(byte[])`

- `FetchResponse` was converted to a record, and its getters (`getStatus()` and `getCount()`) have been replaced by accessor methods (`status()` and `count()`)

- `GenericResponse` was converted to a record, and its getters (`getObjectHandle()`, `getBlobId()`, `getData()` and `exception()`) have been replaced by accessor methods (`objectHandle()`, `blobId()`, `data()` and `exception()`)

- `SQLResponse` was converted to a record, and its getter (`getCount()`) has been replaced by an accessor method (`count()`)

- `SQLExceptionChainBuilder`

  - Moved to package `org.firebirdsql.jaybird.util`; this package is internal API only, and not exported from the module (see also earlier)

  - The generics `<E extends SQLException>` were removed from this class

    - `append` and `addFirst` now always expect `SQLException`

    - `getException()` now always returns `SQLException`

  - Constructor `SQLExceptionChainBuilder(SQLException)` was removed, as in practice this was never used; replacement is `new SQLExceptionChainBuilder().append(exception)`

- `FBTpb` was removed, and its usages were replaced with `TransactionParameterBuffer`

- `FBTpbMapper` no longer implements `Cloneable`, use `FBTpbMapper.copyOf(FBTpbMapper)` instead

- `ParameterBuffer` now extends `Serializable`, as all implementations are serializable, and some usages expect serializable behaviour even when the interfaces were used (though in practice, these objects are hardly ever serialized)

- `FBManagedConnection`

  - `setReadOnly(boolean)` was renamed to `setTpbReadOnly(boolean)` to reflect what it actually does

  - `isReadOnly()` was renamed to `isTpbReadOnly()` to reflect what it actually does

- `FBObjectListener.FetcherListener`

  - `fetcherClosed(FBFetcher)` was removed

  - `allRowsFetched(FBFetcher)` was removed

- `FBObjectListener.ResultSetListener`

  - `allRowsFetched(ResultSet)` was removed

- `GDSExceptionHelper` and its nested class `GDSMessage`

  - Replacement is the class `MessageTemplate`

The `/isc_error_msg.properties` and `/isc_error_sqlstates.properties` resources have been removed. Their replacements are the `/org/firebirdsql/firebird_N_error_msg.properties` and `/org/firebirdsql/firebird_N_sql_states.properties` resources, where N is the facility code of the error. This allows us to avoid loading messages from facilities which are not actually used.

#### 8.18.1. Breaking changes internal API for 6.0.1

Bug fixes in Jaybird 6.0.1 introduced the following breaking changes in the GDS-ng API and its implementations. As this is an internal API, our policy allows breaking changes in point releases. This should only affect maintainers of Jaybird forks, or people using the internal API directly.

- `FbDatabase`

  - `createInputBlob` and `createOutputBlob` now throw `SQLException`

- `ProtocolDescriptor`

  - `createInputBlob` and `createOutputBlob` now throw `SQLException`

- `AbstractFbWireBlob` and subclasses

  - Constructors now throw `SQLException` if the provided database is null or not attached, or the provided transaction is null or not active. Previously, passing in a null transaction would result in a `NullPointerException`.

### 8.19. Unlikely breaking changes

The following changes might cause issues, though we think this is unlikely:

#### 8.19.1. Removal of finalization

With the removal of finalization, the replacement cleanup has been simplified, and in some cases left out entirely.

Possible effects include:

- If a close/cleanup is performed by the `Cleaner`, listeners will not get notified. Given it is unlikely there will not be strong reference to an object if something is still interested in its listener events, we think this is acceptable.

- The closing of a pure Java connection which was not explicitly closed is now simply a socket close handled by the cleanup action of the socket itself. Server-side this may result in delayed cleanup of a connection and its resources, and occurrences of “connection reset by peer” (e.g. error 10054 on Windows, error 104 on Linux). If you see an increase of these errors, we recommend you hunt for connection leaks in your application.

#### 8.19.2. Conversion from double to BigDecimal

Conversions from `double` to `java.math.BigDecimal` now always use `BigDecimal.valueOf(double)`. Previously, a combination of `new BigDecimal(double)` and `BigDecimal.valueOf(double)` was used.

This change may result in minor differences in precision or rounding of values.

### 8.20. Breaking changes for Jaybird 7

With Jaybird 7 the following breaking changes will be introduced.

#### 8.20.1. Removal of deprecated classes, packages and methods

##### Removal of deprecated methods

The following methods will be removed in Jaybird 7:

- `GDSFactoryPlugin` (semi-internal API)

  - `getTypeAliases()`— use `getTypeAliasList()`

  - `getSupportedProtocols`— use `getSupportedProtocolList()`

- `GDSHelper` (internal API)

  - `startTransaction(TransactionParameterBuffer)`— use `FbDatabase.startTransaction(TransactionParameterBuffer)` followed by `GDSHelper.setCurrentTransaction(FbTransaction)`

- `FirebirdStatement`

  - `getCurrentResultSet()`— use `getResultSet()`

- `SqlCountHolder` (internal API)

  - `getLongUpdateCount()`— use `updateCount()`

  - `getLongDeleteCount()`— use `deleteCount()`

  - `getLongInsertCount()`— use `insertCount()`

  - `getLongSelectCount()`— use `selectCount()`

##### Removal of deprecated classes

The following classes have been deprecated and will be removed in Jaybird 7:

- `GDSException`; use `SQLException` or one of its (normal) subclasses. Previous versions of `GDSFactoryPlugin` declared `throws GDSException` for some methods, but now `throws SQLException`. To retain some semblance of backwards-compatibility, this class was retrofitted to extend `SQLException`.

- `FBSQLException`; use `SQLException`

#### 8.20.2. Removal of deprecated constants

The following constants have been deprecated and will be removed in Jaybird 7:

- `ISCConstants`

  - `isc_isc_sql_dialect_conflict_num` (was already deprecated, now for removal); use `isc_sql_dialect_conflict_num`

  - `isc_err_max`; there is no replacement

- `QuoteStrategy`— due to addition of methods `appendLiteral` and `quoteLiteral` the original enum names no longer made sense

  - `NO_QUOTES`— use `DIALECT_1`

  - `QUOTES`— use `DIALECT_3`

- `SQLStateConstants`

  - `SQL_STATE_CONNECTION_CLOSED` (`08003`); use `SQL_STATE_CONNECTION_FAILURE` (`08006`). The use of `08003` for a closed connection error was wrong, and has been updated to use `08006`.

## 9. Compatibility notes

### 9.1. Type 2 (native) and embedded driver

Since Jaybird 6, the native and embedded part of the driver has been moved to a separate artifact, `jaybird-native`. The Jaybird Native GDS Factory plugin uses JNA to access the client library. If you want to use the Type 2 driver, or Firebird embedded, then you need to include `jaybird-native-6.0.3` and `jna-jpms-5.17.0.jar` on the classpath.

When using Maven, you need to specify the dependency on `jaybird-native`:

    <dependency>
        <groupId>org.firebirdsql.jdbc</groupId>
        <artifactId>jaybird-native</artifactId>
        <version>6.0.3</version>
    </dependency>

The `fbclient.dll`, `fbembed.dll`, `libfbclient.so`, or `libfbembed.so` need to be on the path, or the location needs to be specified in the system property `jna.library.path` (as an absolute or relative path to the directory/directories containing the library file(s)).

For Windows and Linux, you can add the `org.firebirdsql.jdbc:fbclient` dependency on your classpath to provide the native libraries for the `native` and `local` protocol. Be aware that this dependency does not support `embedded`.

    <dependency>
        <groupId>org.firebirdsql.jdbc</groupId>
        <artifactId>fbclient</artifactId>
        <version>5.0.2.0</artifactId>
    </dependency>

For more information about this library, see https://github.com/mrotteveel/jaybird-fbclient.

In the future we may provide JARs with the embedded libraries of a specific Firebird version.

1. since Firebird 3.0.2, version 13 for 3.0.0 and 3.0.1
2. Jaybird has no protocol 14 implementation
3. Jaybird has no protocol 17 implementation
4. since Firebird 5.0.3, version 18 for 5.0.0 — 5.0.2
5. The wide range of the percentages is due to running the test with a single hop and two hops between client and server, and thus a wide range of latency.
6. For get the maximum segment size is actually the maximum buffer size to receive one or more segments which are prefixed with two bytes for the length