Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -500,8 +500,8 @@ public Connection getConnection() throws SQLException {

@Override public ResultSet getProcedures(String catalog, String schemaPattern, String procedureNamePattern) throws SQLException { throw new UnsupportedOperationException(); }
@Override public ResultSet getProcedureColumns(String catalog, String schemaPattern, String procedureNamePattern, String columnNamePattern) throws SQLException { throw new UnsupportedOperationException(); }
@Override public ResultSet getSchemas() throws SQLException { return connection.createStatement().executeQuery("SELECT NULL AS TABLE_SCHEM, NULL AS TABLE_CATALOG WHERE 0"); }
@Override public ResultSet getCatalogs() throws SQLException { return connection.createStatement().executeQuery("SELECT NULL AS TABLE_CAT WHERE 0"); }
@Override public ResultSet getSchemas() throws SQLException { return executeMetadataQuery("SELECT NULL AS TABLE_SCHEM, NULL AS TABLE_CATALOG WHERE 0"); }
@Override public ResultSet getCatalogs() throws SQLException { return executeMetadataQuery("SELECT NULL AS TABLE_CAT WHERE 0"); }
@Override public ResultSet getColumnPrivileges(String catalog, String schema, String table, String columnNamePattern) throws SQLException { throw new UnsupportedOperationException(); }
@Override public ResultSet getTablePrivileges(String catalog, String schemaPattern, String tableNamePattern) throws SQLException { throw new UnsupportedOperationException(); }
@Override public ResultSet getBestRowIdentifier(String catalog, String schema, String table, int scope, boolean nullable) throws SQLException { throw new UnsupportedOperationException(); }
Expand All @@ -510,26 +510,26 @@ public Connection getConnection() throws SQLException {
String sql = "SELECT NULL AS PKTABLE_CAT, NULL AS PKTABLE_SCHEM, NULL AS PKTABLE_NAME, NULL AS PKCOLUMN_NAME, " +
"NULL AS FKTABLE_CAT, NULL AS FKTABLE_SCHEM, NULL AS FKTABLE_NAME, NULL AS FKCOLUMN_NAME, " +
"0 AS KEY_SEQ, 0 AS UPDATE_RULE, 0 AS DELETE_RULE, NULL AS FK_NAME, NULL AS PK_NAME, 0 AS DEFERRABILITY WHERE 0";
return connection.createStatement().executeQuery(sql);
return executeMetadataQuery(sql);
}
@Override public ResultSet getExportedKeys(String catalog, String schema, String table) throws SQLException {
String sql = "SELECT NULL AS PKTABLE_CAT, NULL AS PKTABLE_SCHEM, NULL AS PKTABLE_NAME, NULL AS PKCOLUMN_NAME, " +
"NULL AS FKTABLE_CAT, NULL AS FKTABLE_SCHEM, NULL AS FKTABLE_NAME, NULL AS FKCOLUMN_NAME, " +
"0 AS KEY_SEQ, 0 AS UPDATE_RULE, 0 AS DELETE_RULE, NULL AS FK_NAME, NULL AS PK_NAME, 0 AS DEFERRABILITY WHERE 0";
return connection.createStatement().executeQuery(sql);
return executeMetadataQuery(sql);
}
@Override public ResultSet getCrossReference(String parentCatalog, String parentSchema, String parentTable, String foreignCatalog, String foreignSchema, String foreignTable) throws SQLException {
String sql = "SELECT NULL AS PKTABLE_CAT, NULL AS PKTABLE_SCHEM, NULL AS PKTABLE_NAME, NULL AS PKCOLUMN_NAME, " +
"NULL AS FKTABLE_CAT, NULL AS FKTABLE_SCHEM, NULL AS FKTABLE_NAME, NULL AS FKCOLUMN_NAME, " +
"0 AS KEY_SEQ, 0 AS UPDATE_RULE, 0 AS DELETE_RULE, NULL AS FK_NAME, NULL AS PK_NAME, 0 AS DEFERRABILITY WHERE 0";
return connection.createStatement().executeQuery(sql);
return executeMetadataQuery(sql);
}
@Override public ResultSet getTypeInfo() throws SQLException {
String sql = "SELECT 'VARCHAR' AS TYPE_NAME, " + java.sql.Types.VARCHAR + " AS DATA_TYPE, 0 AS PRECISION, " +
"NULL AS LITERAL_PREFIX, NULL AS LITERAL_SUFFIX, NULL AS CREATE_PARAMS, 1 AS NULLABLE, 1 AS CASE_SENSITIVE, " +
"3 AS SEARCHABLE, 0 AS UNSIGNED_ATTRIBUTE, 0 AS FIXED_PREC_SCALE, 0 AS AUTO_INCREMENT, " +
"NULL AS LOCAL_TYPE_NAME, 0 AS MINIMUM_SCALE, 0 AS MAXIMUM_SCALE, 0 AS SQL_DATA_TYPE, 0 AS SQL_DATETIME_SUB, 10 AS NUM_PREC_RADIX WHERE 0";
return connection.createStatement().executeQuery(sql);
return executeMetadataQuery(sql);
}
@Override public ResultSet getIndexInfo(String catalog, String schema, String table, boolean unique, boolean approximate) throws SQLException {
String sql = "SELECT NULL AS TABLE_CAT, NULL AS TABLE_SCHEM, '" + table + "' AS TABLE_NAME, " +
Expand All @@ -542,7 +542,7 @@ public Connection getConnection() throws SQLException {
sql += " WHERE il.\"unique\" = 1";
}
sql += " ORDER BY NON_UNIQUE, TYPE, INDEX_NAME, ORDINAL_POSITION";
return connection.createStatement().executeQuery(sql);
return executeMetadataQuery(sql);
}
@Override public boolean supportsResultSetType(int type) throws SQLException { return type == ResultSet.TYPE_FORWARD_ONLY; }
@Override public boolean supportsResultSetConcurrency(int type, int concurrency) throws SQLException { return type == ResultSet.TYPE_FORWARD_ONLY && concurrency == ResultSet.CONCUR_READ_ONLY; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,43 @@ void getTableTypesReturnsEveryXerialTableType() throws SQLException {
.containsExactlyInAnyOrder("TABLE", "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY");
}

@Test
void eachMetadataMethodClosesTheStatementThatProducedItsResultSet() throws SQLException {
LibsqlDatabaseMetaData metadata = new LibsqlDatabaseMetaData(new RecordingConnection(emptyResult()));
List<MetadataQuery> queries = List.of(
new MetadataQuery("getSchemas", metadata::getSchemas),
new MetadataQuery("getSchemas(catalog, pattern)", () -> metadata.getSchemas(null, null)),
new MetadataQuery("getCatalogs", metadata::getCatalogs),
new MetadataQuery("getTypeInfo", metadata::getTypeInfo),
new MetadataQuery("getImportedKeys", () -> metadata.getImportedKeys(null, null, "t")),
new MetadataQuery("getExportedKeys", () -> metadata.getExportedKeys(null, null, "t")),
new MetadataQuery(
"getCrossReference",
() -> metadata.getCrossReference(null, null, "parent", null, null, "child")),
new MetadataQuery(
"getIndexInfo", () -> metadata.getIndexInfo(null, null, "t", false, false)));

List<String> leakedMethods = new ArrayList<>();
for (MetadataQuery query : queries) {
ResultSet resultSet = query.action().execute();
LibsqlStatement statement = (LibsqlStatement) resultSet.getStatement();
resultSet.close();
if (!statement.isClosed()) {
leakedMethods.add(query.name());
}
statement.close();
}

assertThat(leakedMethods).isEmpty();
}

@FunctionalInterface
private interface MetadataCall {
ResultSet execute() throws SQLException;
}

private record MetadataQuery(String name, MetadataCall action) {}

@Test
void getColumnsReportsDeclaredTypesSizesNullabilityAndAutoIncrement() throws SQLException {
LibsqlDatabaseMetaData metadata = new LibsqlDatabaseMetaData(new StmtResultConnection(columnMetadataRows()));
Expand Down
Loading