1- // SPDX-FileCopyrightText: Copyright 2023-2025 Mark Rotteveel
1+ // SPDX-FileCopyrightText: Copyright 2023-2026 Mark Rotteveel
22// SPDX-License-Identifier: LGPL-2.1-or-later
33package org .firebirdsql .jdbc ;
44
55import org .firebirdsql .gds .ISCConstants ;
66import org .firebirdsql .gds .ng .FbExceptionBuilder ;
7+ import org .jspecify .annotations .Nullable ;
78
89import java .sql .ClientInfoStatus ;
910import java .sql .SQLClientInfoException ;
@@ -55,7 +56,7 @@ final class ClientInfoProvider {
5556 // Holds statement used for setting or retrieving client info properties.
5657 private final MetadataStatementHolder statementHolder ;
5758 // if null, use DEFAULT_CLIENT_INFO_PROPERTIES
58- private Set <ClientInfoProperty > knownProperties ;
59+ private @ Nullable Set <ClientInfoProperty > knownProperties ;
5960
6061 ClientInfoProvider (FBConnection connection ) throws SQLException {
6162 connection .checkValidity ();
@@ -154,7 +155,7 @@ Collection<ClientInfoProperty> getDefaultClientInfoProperties() {
154155 * Implementation of {@link FBConnection#getClientInfo(String)}.
155156 */
156157 @ SuppressWarnings ("SqlSourceToSinkFlow" )
157- public String getClientInfo (String name ) throws SQLException {
158+ public @ Nullable String getClientInfo (String name ) throws SQLException {
158159 ClientInfoProperty property ;
159160 try {
160161 property = ClientInfoProperty .parse (name );
@@ -270,6 +271,7 @@ public void setClientInfo(String name, String value) throws SQLException {
270271 SQLException forMessage = FbExceptionBuilder .forException (jb_clientInfoInvalidPropertyName )
271272 .messageParameter (name )
272273 .toSQLException ();
274+ //noinspection DataFlowIssue : null-check for robustness
273275 throw new SQLClientInfoException (forMessage .getMessage (), forMessage .getSQLState (),
274276 forMessage .getErrorCode (),
275277 Map .of (requireNonNullElse (name , "<null>" ), ClientInfoStatus .REASON_UNKNOWN ), e );
@@ -298,7 +300,7 @@ public void setClientInfo(Properties properties) throws SQLException {
298300 // Include USER_SESSION, and USER_TRANSACTION if not in auto-commit
299301 Predicate <ClientInfoProperty > includePropertyPredicate = property ->
300302 USER_SESSION .equals (property .context ) || !autoCommit && USER_TRANSACTION .equals (property .context );
301- var propertyValues = new HashMap <ClientInfoProperty , String >();
303+ var propertyValues = new HashMap <ClientInfoProperty , @ Nullable String >();
302304 // Populating with null to clear properties not included in parameter properties
303305 getKnownProperties ().stream ()
304306 .filter (includePropertyPredicate )
@@ -316,7 +318,7 @@ public void setClientInfo(Properties properties) throws SQLException {
316318 }
317319
318320 @ SuppressWarnings ("SqlSourceToSinkFlow" )
319- private void executeSetClientInfo (Map <ClientInfoProperty , String > propertyValues ) throws SQLException {
321+ private void executeSetClientInfo (Map <ClientInfoProperty , @ Nullable String > propertyValues ) throws SQLException {
320322 QuoteStrategy quoteStrategy = connection .getQuoteStrategy ();
321323 var sb = new StringBuilder ("""
322324 execute block
@@ -437,7 +439,7 @@ StringBuilder appendAsGetContext(StringBuilder sb, QuoteStrategy quoteStrategy)
437439 * value to set, use {@code null} to set SQL {@code NULL}
438440 * @return {@code sb} for chaining calls
439441 */
440- StringBuilder appendAsSetContext (StringBuilder sb , QuoteStrategy quoteStrategy , String value ) {
442+ StringBuilder appendAsSetContext (StringBuilder sb , QuoteStrategy quoteStrategy , @ Nullable String value ) {
441443 // 30 = 16 (prefix) + 9 (6 quotes, 2 commas, and closing parenthesis) + space for five quotes to escape
442444 sb .ensureCapacity (
443445 sb .length () + 30 + context .length () + name .length () + (value != null ? value .length () : 4 ));
0 commit comments