Skip to content

Commit bdec833

Browse files
authored
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.
1 parent e349a9a commit bdec833

2 files changed

Lines changed: 104 additions & 1 deletion

File tree

flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/ArrowDatabaseMetadata.java

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import java.sql.ResultSet;
4646
import java.sql.SQLException;
4747
import java.util.Arrays;
48+
import java.util.Collections;
4849
import java.util.EnumMap;
4950
import java.util.HashMap;
5051
import java.util.List;
@@ -86,9 +87,12 @@
8687
import org.apache.arrow.vector.util.Text;
8788
import org.apache.calcite.avatica.AvaticaConnection;
8889
import org.apache.calcite.avatica.AvaticaDatabaseMetaData;
90+
import org.slf4j.Logger;
91+
import org.slf4j.LoggerFactory;
8992

9093
/** Arrow Flight JDBC's implementation of {@link DatabaseMetaData}. */
9194
public class ArrowDatabaseMetadata extends AvaticaDatabaseMetaData {
95+
private static final Logger LOGGER = LoggerFactory.getLogger(ArrowDatabaseMetadata.class);
9296
private static final String JAVA_REGEX_SPECIALS = "[]()|^-+*?{}$\\.";
9397
private static final Charset CHARSET = StandardCharsets.UTF_8;
9498
private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
@@ -774,7 +778,34 @@ private <T> T getSqlInfoAndCacheIfCacheIsEmpty(
774778
}
775779
}
776780
}
777-
return desiredType.cast(cachedSqlInfo.get(sqlInfoCommand));
781+
T value = desiredType.cast(cachedSqlInfo.get(sqlInfoCommand));
782+
if (value != null) {
783+
return value;
784+
}
785+
LOGGER.debug(
786+
"SqlInfo {} not provided by server, returning default for type {}",
787+
sqlInfoCommand.name(),
788+
desiredType.getSimpleName());
789+
790+
// Return sensible defaults when SqlInfo is unavailable
791+
if (desiredType == Long.class) {
792+
return desiredType.cast(0L);
793+
} else if (desiredType == Integer.class) {
794+
return desiredType.cast(0);
795+
} else if (desiredType == Boolean.class) {
796+
return desiredType.cast(false);
797+
} else if (desiredType == String.class) {
798+
return desiredType.cast("");
799+
} else if (desiredType == Map.class) {
800+
return desiredType.cast(Collections.emptyMap());
801+
} else if (desiredType == List.class) {
802+
return desiredType.cast(Collections.emptyList());
803+
}
804+
805+
throw new SQLException(
806+
String.format(
807+
"The value of the SqlInfo %s is null and it could not be cast to %s.",
808+
sqlInfoCommand.name(), desiredType.getName()));
778809
}
779810

780811
private Optional<String> convertListSqlInfoToString(final List<?> sqlInfoList) {

flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/ArrowDatabaseMetadataTest.java

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1543,11 +1543,83 @@ public void testEmptySqlInfo() throws Exception {
15431543
try (final Connection testConnection =
15441544
FLIGHT_SERVER_EMPTY_SQLINFO_TEST_RULE.getConnection(false)) {
15451545
final DatabaseMetaData metaData = testConnection.getMetaData();
1546+
15461547
assertThat(metaData.getSQLKeywords(), is(""));
15471548
assertThat(metaData.getNumericFunctions(), is(""));
15481549
assertThat(metaData.getStringFunctions(), is(""));
15491550
assertThat(metaData.getSystemFunctions(), is(""));
15501551
assertThat(metaData.getTimeDateFunctions(), is(""));
1552+
1553+
assertThat(metaData.getMaxBinaryLiteralLength(), is(0));
1554+
assertThat(metaData.getMaxCharLiteralLength(), is(0));
1555+
assertThat(metaData.getMaxColumnNameLength(), is(0));
1556+
assertThat(metaData.getMaxColumnsInGroupBy(), is(0));
1557+
assertThat(metaData.getMaxColumnsInIndex(), is(0));
1558+
assertThat(metaData.getMaxColumnsInOrderBy(), is(0));
1559+
assertThat(metaData.getMaxColumnsInSelect(), is(0));
1560+
assertThat(metaData.getMaxColumnsInTable(), is(0));
1561+
assertThat(metaData.getMaxConnections(), is(0));
1562+
assertThat(metaData.getMaxCursorNameLength(), is(0));
1563+
assertThat(metaData.getMaxIndexLength(), is(0));
1564+
assertThat(metaData.getMaxSchemaNameLength(), is(0));
1565+
assertThat(metaData.getMaxProcedureNameLength(), is(0));
1566+
assertThat(metaData.getMaxCatalogNameLength(), is(0));
1567+
assertThat(metaData.getMaxRowSize(), is(0));
1568+
assertThat(metaData.getMaxStatementLength(), is(0));
1569+
assertThat(metaData.getMaxStatements(), is(0));
1570+
assertThat(metaData.getMaxTableNameLength(), is(0));
1571+
assertThat(metaData.getMaxTablesInSelect(), is(0));
1572+
assertThat(metaData.getMaxUserNameLength(), is(0));
1573+
1574+
assertThat(metaData.supportsColumnAliasing(), is(false));
1575+
assertThat(metaData.nullPlusNonNullIsNull(), is(false));
1576+
assertThat(metaData.supportsTableCorrelationNames(), is(false));
1577+
assertThat(metaData.supportsDifferentTableCorrelationNames(), is(false));
1578+
assertThat(metaData.supportsExpressionsInOrderBy(), is(false));
1579+
assertThat(metaData.supportsOrderByUnrelated(), is(false));
1580+
assertThat(metaData.supportsLikeEscapeClause(), is(false));
1581+
assertThat(metaData.supportsNonNullableColumns(), is(false));
1582+
assertThat(metaData.supportsIntegrityEnhancementFacility(), is(false));
1583+
assertThat(metaData.isCatalogAtStart(), is(false));
1584+
assertThat(metaData.supportsSelectForUpdate(), is(false));
1585+
assertThat(metaData.supportsStoredProcedures(), is(false));
1586+
assertThat(metaData.supportsCorrelatedSubqueries(), is(false));
1587+
assertThat(metaData.doesMaxRowSizeIncludeBlobs(), is(false));
1588+
assertThat(metaData.supportsTransactions(), is(false));
1589+
assertThat(metaData.dataDefinitionCausesTransactionCommit(), is(false));
1590+
assertThat(metaData.dataDefinitionIgnoredInTransactions(), is(false));
1591+
assertThat(metaData.supportsBatchUpdates(), is(false));
1592+
assertThat(metaData.supportsSavepoints(), is(false));
1593+
assertThat(metaData.supportsNamedParameters(), is(false));
1594+
assertThat(metaData.locatorsUpdateCopy(), is(false));
1595+
assertThat(metaData.supportsStoredFunctionsUsingCallSyntax(), is(false));
1596+
assertThat(metaData.supportsGroupBy(), is(false));
1597+
assertThat(metaData.supportsGroupByUnrelated(), is(false));
1598+
assertThat(metaData.supportsMinimumSQLGrammar(), is(false));
1599+
assertThat(metaData.supportsCoreSQLGrammar(), is(false));
1600+
assertThat(metaData.supportsExtendedSQLGrammar(), is(false));
1601+
assertThat(metaData.supportsANSI92EntryLevelSQL(), is(false));
1602+
assertThat(metaData.supportsANSI92IntermediateSQL(), is(false));
1603+
assertThat(metaData.supportsANSI92FullSQL(), is(false));
1604+
assertThat(metaData.supportsOuterJoins(), is(false));
1605+
assertThat(metaData.supportsFullOuterJoins(), is(false));
1606+
assertThat(metaData.supportsLimitedOuterJoins(), is(false));
1607+
assertThat(metaData.supportsSchemasInProcedureCalls(), is(false));
1608+
assertThat(metaData.supportsSchemasInIndexDefinitions(), is(false));
1609+
assertThat(metaData.supportsSchemasInPrivilegeDefinitions(), is(false));
1610+
assertThat(metaData.supportsCatalogsInIndexDefinitions(), is(false));
1611+
assertThat(metaData.supportsCatalogsInPrivilegeDefinitions(), is(false));
1612+
assertThat(metaData.supportsPositionedDelete(), is(false));
1613+
assertThat(metaData.supportsPositionedUpdate(), is(false));
1614+
assertThat(metaData.supportsSubqueriesInComparisons(), is(false));
1615+
assertThat(metaData.supportsSubqueriesInExists(), is(false));
1616+
assertThat(metaData.supportsSubqueriesInIns(), is(false));
1617+
assertThat(metaData.supportsSubqueriesInQuantifieds(), is(false));
1618+
assertThat(metaData.supportsUnion(), is(false));
1619+
assertThat(metaData.supportsUnionAll(), is(false));
1620+
assertThat(metaData.supportsConvert(), is(false));
1621+
1622+
assertThat(metaData.getDefaultTransactionIsolation(), is(Connection.TRANSACTION_NONE));
15511623
}
15521624
}
15531625
}

0 commit comments

Comments
 (0)