This is an automated email from the ASF dual-hosted git repository.

jbonofre pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-java.git


The following commit(s) were added to refs/heads/main by this push:
     new bdec833fb GH-994: Fix DatabaseMetaData NPEs when SqlInfo is 
unavailable (#995)
bdec833fb is described below

commit bdec833fb69f945db9f3c767715c93d09214f2b5
Author: Pedro Matias <[email protected]>
AuthorDate: Wed Mar 11 07:34:47 2026 +0000

    GH-994: Fix DatabaseMetaData NPEs when SqlInfo is unavailable (#995)
    
    ## What's Changed
    
    Multiple DatabaseMetaData methods had NPEs when the method
    `ArrowDatabaseMetadata.getSqlInfoAndCacheIfCacheIsEmpty(final SqlInfo
    sqlInfoCommand, final Class<T> desiredType)`
    returned null.
    
    Now the method never returns null. If the database server does not
    provide the requested info, either a sensible default is returned or a
    SQLException is thrown.
    
    Closes #994.
---
 .../arrow/driver/jdbc/ArrowDatabaseMetadata.java   | 33 +++++++++-
 .../driver/jdbc/ArrowDatabaseMetadataTest.java     | 72 ++++++++++++++++++++++
 2 files changed, 104 insertions(+), 1 deletion(-)

diff --git 
a/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/ArrowDatabaseMetadata.java
 
b/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/ArrowDatabaseMetadata.java
index 502270e1c..0110525fe 100644
--- 
a/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/ArrowDatabaseMetadata.java
+++ 
b/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/ArrowDatabaseMetadata.java
@@ -45,6 +45,7 @@ import java.sql.DatabaseMetaData;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.EnumMap;
 import java.util.HashMap;
 import java.util.List;
@@ -86,9 +87,12 @@ import org.apache.arrow.vector.types.pojo.Schema;
 import org.apache.arrow.vector.util.Text;
 import org.apache.calcite.avatica.AvaticaConnection;
 import org.apache.calcite.avatica.AvaticaDatabaseMetaData;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /** Arrow Flight JDBC's implementation of {@link DatabaseMetaData}. */
 public class ArrowDatabaseMetadata extends AvaticaDatabaseMetaData {
+  private static final Logger LOGGER = 
LoggerFactory.getLogger(ArrowDatabaseMetadata.class);
   private static final String JAVA_REGEX_SPECIALS = "[]()|^-+*?{}$\\.";
   private static final Charset CHARSET = StandardCharsets.UTF_8;
   private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
@@ -774,7 +778,34 @@ public class ArrowDatabaseMetadata extends 
AvaticaDatabaseMetaData {
         }
       }
     }
-    return desiredType.cast(cachedSqlInfo.get(sqlInfoCommand));
+    T value = desiredType.cast(cachedSqlInfo.get(sqlInfoCommand));
+    if (value != null) {
+      return value;
+    }
+    LOGGER.debug(
+        "SqlInfo {} not provided by server, returning default for type {}",
+        sqlInfoCommand.name(),
+        desiredType.getSimpleName());
+
+    // Return sensible defaults when SqlInfo is unavailable
+    if (desiredType == Long.class) {
+      return desiredType.cast(0L);
+    } else if (desiredType == Integer.class) {
+      return desiredType.cast(0);
+    } else if (desiredType == Boolean.class) {
+      return desiredType.cast(false);
+    } else if (desiredType == String.class) {
+      return desiredType.cast("");
+    } else if (desiredType == Map.class) {
+      return desiredType.cast(Collections.emptyMap());
+    } else if (desiredType == List.class) {
+      return desiredType.cast(Collections.emptyList());
+    }
+
+    throw new SQLException(
+        String.format(
+            "The value of the SqlInfo %s is null and it could not be cast to 
%s.",
+            sqlInfoCommand.name(), desiredType.getName()));
   }
 
   private Optional<String> convertListSqlInfoToString(final List<?> 
sqlInfoList) {
diff --git 
a/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/ArrowDatabaseMetadataTest.java
 
b/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/ArrowDatabaseMetadataTest.java
index 81579cc38..3ab1460b2 100644
--- 
a/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/ArrowDatabaseMetadataTest.java
+++ 
b/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/ArrowDatabaseMetadataTest.java
@@ -1543,11 +1543,83 @@ public class ArrowDatabaseMetadataTest {
     try (final Connection testConnection =
         FLIGHT_SERVER_EMPTY_SQLINFO_TEST_RULE.getConnection(false)) {
       final DatabaseMetaData metaData = testConnection.getMetaData();
+
       assertThat(metaData.getSQLKeywords(), is(""));
       assertThat(metaData.getNumericFunctions(), is(""));
       assertThat(metaData.getStringFunctions(), is(""));
       assertThat(metaData.getSystemFunctions(), is(""));
       assertThat(metaData.getTimeDateFunctions(), is(""));
+
+      assertThat(metaData.getMaxBinaryLiteralLength(), is(0));
+      assertThat(metaData.getMaxCharLiteralLength(), is(0));
+      assertThat(metaData.getMaxColumnNameLength(), is(0));
+      assertThat(metaData.getMaxColumnsInGroupBy(), is(0));
+      assertThat(metaData.getMaxColumnsInIndex(), is(0));
+      assertThat(metaData.getMaxColumnsInOrderBy(), is(0));
+      assertThat(metaData.getMaxColumnsInSelect(), is(0));
+      assertThat(metaData.getMaxColumnsInTable(), is(0));
+      assertThat(metaData.getMaxConnections(), is(0));
+      assertThat(metaData.getMaxCursorNameLength(), is(0));
+      assertThat(metaData.getMaxIndexLength(), is(0));
+      assertThat(metaData.getMaxSchemaNameLength(), is(0));
+      assertThat(metaData.getMaxProcedureNameLength(), is(0));
+      assertThat(metaData.getMaxCatalogNameLength(), is(0));
+      assertThat(metaData.getMaxRowSize(), is(0));
+      assertThat(metaData.getMaxStatementLength(), is(0));
+      assertThat(metaData.getMaxStatements(), is(0));
+      assertThat(metaData.getMaxTableNameLength(), is(0));
+      assertThat(metaData.getMaxTablesInSelect(), is(0));
+      assertThat(metaData.getMaxUserNameLength(), is(0));
+
+      assertThat(metaData.supportsColumnAliasing(), is(false));
+      assertThat(metaData.nullPlusNonNullIsNull(), is(false));
+      assertThat(metaData.supportsTableCorrelationNames(), is(false));
+      assertThat(metaData.supportsDifferentTableCorrelationNames(), is(false));
+      assertThat(metaData.supportsExpressionsInOrderBy(), is(false));
+      assertThat(metaData.supportsOrderByUnrelated(), is(false));
+      assertThat(metaData.supportsLikeEscapeClause(), is(false));
+      assertThat(metaData.supportsNonNullableColumns(), is(false));
+      assertThat(metaData.supportsIntegrityEnhancementFacility(), is(false));
+      assertThat(metaData.isCatalogAtStart(), is(false));
+      assertThat(metaData.supportsSelectForUpdate(), is(false));
+      assertThat(metaData.supportsStoredProcedures(), is(false));
+      assertThat(metaData.supportsCorrelatedSubqueries(), is(false));
+      assertThat(metaData.doesMaxRowSizeIncludeBlobs(), is(false));
+      assertThat(metaData.supportsTransactions(), is(false));
+      assertThat(metaData.dataDefinitionCausesTransactionCommit(), is(false));
+      assertThat(metaData.dataDefinitionIgnoredInTransactions(), is(false));
+      assertThat(metaData.supportsBatchUpdates(), is(false));
+      assertThat(metaData.supportsSavepoints(), is(false));
+      assertThat(metaData.supportsNamedParameters(), is(false));
+      assertThat(metaData.locatorsUpdateCopy(), is(false));
+      assertThat(metaData.supportsStoredFunctionsUsingCallSyntax(), is(false));
+      assertThat(metaData.supportsGroupBy(), is(false));
+      assertThat(metaData.supportsGroupByUnrelated(), is(false));
+      assertThat(metaData.supportsMinimumSQLGrammar(), is(false));
+      assertThat(metaData.supportsCoreSQLGrammar(), is(false));
+      assertThat(metaData.supportsExtendedSQLGrammar(), is(false));
+      assertThat(metaData.supportsANSI92EntryLevelSQL(), is(false));
+      assertThat(metaData.supportsANSI92IntermediateSQL(), is(false));
+      assertThat(metaData.supportsANSI92FullSQL(), is(false));
+      assertThat(metaData.supportsOuterJoins(), is(false));
+      assertThat(metaData.supportsFullOuterJoins(), is(false));
+      assertThat(metaData.supportsLimitedOuterJoins(), is(false));
+      assertThat(metaData.supportsSchemasInProcedureCalls(), is(false));
+      assertThat(metaData.supportsSchemasInIndexDefinitions(), is(false));
+      assertThat(metaData.supportsSchemasInPrivilegeDefinitions(), is(false));
+      assertThat(metaData.supportsCatalogsInIndexDefinitions(), is(false));
+      assertThat(metaData.supportsCatalogsInPrivilegeDefinitions(), is(false));
+      assertThat(metaData.supportsPositionedDelete(), is(false));
+      assertThat(metaData.supportsPositionedUpdate(), is(false));
+      assertThat(metaData.supportsSubqueriesInComparisons(), is(false));
+      assertThat(metaData.supportsSubqueriesInExists(), is(false));
+      assertThat(metaData.supportsSubqueriesInIns(), is(false));
+      assertThat(metaData.supportsSubqueriesInQuantifieds(), is(false));
+      assertThat(metaData.supportsUnion(), is(false));
+      assertThat(metaData.supportsUnionAll(), is(false));
+      assertThat(metaData.supportsConvert(), is(false));
+
+      assertThat(metaData.getDefaultTransactionIsolation(), 
is(Connection.TRANSACTION_NONE));
     }
   }
 }

Reply via email to