Skip to content

Commit

Permalink
#131: Added refresh filter.
Browse files Browse the repository at this point in the history
  • Loading branch information
redcatbear committed Apr 15, 2019
1 parent d8e005b commit 2be1a6d
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Optional;

import com.exasol.adapter.AdapterProperties;
import com.exasol.adapter.dialects.PostgreSQLIdentifierMapping;
Expand Down Expand Up @@ -46,15 +47,18 @@ public boolean ignoresUpperCaseTables() {
}

@Override
public List<TableMetadata> mapTables(final ResultSet remoteTables) throws SQLException {
public List<TableMetadata> mapTables(final ResultSet remoteTables, final Optional<List<String>> selectedTables)
throws SQLException {
final String tableName = readTableName(remoteTables);
if ((getIdentifierMapping() == PostgreSQLIdentifierMapping.CONVERT_TO_UPPER) && !ignoresUpperCaseTables()
if (isTableSelected(tableName, selectedTables) //
&& (getIdentifierMapping() == PostgreSQLIdentifierMapping.CONVERT_TO_UPPER) //
&& !ignoresUpperCaseTables() //
&& containsUppercaseCharacter(tableName)) {
throw new RemoteMetadataReaderException("Table \"" + tableName
+ "\" cannot be used in virtual schema. Set property " + IGNORE_ERRORS_PROPERTY + " to "
+ POSTGRESQL_UPPERCASE_TABLES_SWITCH + " to enforce schema creation.");
} else {
return super.mapTables(remoteTables);
return super.mapTables(remoteTables, selectedTables);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import java.sql.*;
import java.util.List;
import java.util.Optional;
import java.util.logging.Logger;

import com.exasol.adapter.AdapterProperties;
Expand Down Expand Up @@ -82,20 +83,21 @@ public SchemaMetadata readRemoteSchemaMetadata() {
final DatabaseMetaData remoteMetadata = this.connection.getMetaData();
final String adapterNotes = SchemaAdapterNotesJsonConverter.getInstance()
.convertToJson(getSchemaAdapterNotes());
final List<TableMetadata> tables = extractTableMetadata(remoteMetadata);
final List<TableMetadata> tables = extractTableMetadata(remoteMetadata, Optional.empty());
return new SchemaMetadata(adapterNotes, tables);
} catch (final SQLException exception) {
throw new RemoteMetadataReaderException("Unable to read remote schema metadata.", exception);
}
}

private List<TableMetadata> extractTableMetadata(final DatabaseMetaData remoteMetadata) throws SQLException {
private List<TableMetadata> extractTableMetadata(final DatabaseMetaData remoteMetadata,
final Optional<List<String>> selectedTables) throws SQLException {
final String catalogName = getCatalogNameFilter();
final String schemaName = getSchemaNameFilter();
logTablesScan(catalogName, schemaName);
try (final ResultSet remoteTables = remoteMetadata.getTables(catalogName, schemaName, ANY_TABLE,
SUPPORTED_TABLE_TYPES.toArray(new String[0]))) {
return mapTables(remoteTables);
return mapTables(remoteTables, selectedTables);
}
}

Expand All @@ -121,8 +123,9 @@ protected void logTablesScan(final String catalogName, final String schemaName)
});
}

private List<TableMetadata> mapTables(final ResultSet remoteTables) throws SQLException {
return this.tableMetadataReader.mapTables(remoteTables);
private List<TableMetadata> mapTables(final ResultSet remoteTables, final Optional<List<String>> selectedTables)
throws SQLException {
return this.tableMetadataReader.mapTables(remoteTables, selectedTables);
}

@Override
Expand Down Expand Up @@ -152,8 +155,15 @@ public SchemaAdapterNotes getSchemaAdapterNotes() {
}

@Override
public SchemaMetadata readRemoteSchemaMetadata(final List<String> tables) {
// FIXME Auto-generated method stub
throw new UnsupportedOperationException("Filtering tables not implemented.");
public SchemaMetadata readRemoteSchemaMetadata(final List<String> selectedTables) {
try {
final DatabaseMetaData remoteMetadata = this.connection.getMetaData();
final String adapterNotes = SchemaAdapterNotesJsonConverter.getInstance()
.convertToJson(getSchemaAdapterNotes());
final List<TableMetadata> tables = extractTableMetadata(remoteMetadata, Optional.of(selectedTables));
return new SchemaMetadata(adapterNotes, tables);
} catch (final SQLException exception) {
throw new RemoteMetadataReaderException("Unable to read remote schema metadata.", exception);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.*;
import java.util.logging.Logger;
import java.util.regex.Pattern;

Expand Down Expand Up @@ -37,18 +36,19 @@ public BaseTableMetadataReader(final ColumnMetadataReader columnMetadataReader,
}

@Override
public List<TableMetadata> mapTables(final ResultSet remoteTables) throws SQLException {
public List<TableMetadata> mapTables(final ResultSet remoteTables, final Optional<List<String>> selectedTables)
throws SQLException {
final List<TableMetadata> translatedTables = new ArrayList<>();
while (remoteTables.next()) {
mapOrSkipTable(remoteTables, translatedTables);
mapOrSkipTable(remoteTables, translatedTables, selectedTables);
}
return translatedTables;
}

protected void mapOrSkipTable(final ResultSet remoteTables, final List<TableMetadata> translatedTables)
throws SQLException {
protected void mapOrSkipTable(final ResultSet remoteTables, final List<TableMetadata> translatedTables,
final Optional<List<String>> selectedTables) throws SQLException {
final String tableName = readTableName(remoteTables);
if (isTableIncludedByMapping(tableName)) {
if (isTableIncludedByMapping(tableName) && isTableSelected(tableName, selectedTables)) {
mapOrSkipSupportedTable(remoteTables, translatedTables, tableName);
} else {
skipUnsupportedTable(tableName);
Expand All @@ -60,6 +60,10 @@ public boolean isTableIncludedByMapping(final String tableName) {
return true;
}

protected boolean isTableSelected(final String tableName, final Optional<List<String>> selectedTables) {
return !selectedTables.isPresent() || selectedTables.get().contains(tableName);
}

protected void mapOrSkipSupportedTable(final ResultSet remoteTables, final List<TableMetadata> translatedTables,
final String tableName) throws SQLException {
if (isTableFilteredOut(tableName)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Optional;

import com.exasol.adapter.dialects.SqlDialect.IdentifierCaseHandling;
import com.exasol.adapter.metadata.TableMetadata;
Expand All @@ -14,11 +15,13 @@ public interface TableMetadataReader {
/**
* Map a list of tables found in a JDBC result set to a list of {@link TableMetadata}
*
* @param remoteTables result set containing the tables to be mapped
* @param remoteTables result set containing the tables to be mapped
* @param selectedTables optional list of tables name that is used to narrow down the mapping
* @return list of {@link TableMetadata}
* @throws SQLException if either mapping the table or its columns produces an SQL error
*/
public List<TableMetadata> mapTables(ResultSet remoteTables) throws SQLException;
public List<TableMetadata> mapTables(ResultSet remoteTables, Optional<List<String>> selectedTables)
throws SQLException;

/**
* Adjust the case of the identifier as required and configured
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import org.junit.jupiter.api.BeforeEach;
Expand All @@ -19,7 +20,6 @@
import org.mockito.junit.jupiter.MockitoExtension;

import com.exasol.adapter.AdapterProperties;
import com.exasol.adapter.dialects.oracle.OracleTableMetadataReader;
import com.exasol.adapter.jdbc.ColumnMetadataReader;
import com.exasol.adapter.jdbc.TableMetadataReader;
import com.exasol.adapter.metadata.DataType;
Expand Down Expand Up @@ -50,7 +50,7 @@ void testTablesInTrashBinAreNotMapped() throws SQLException {
mockTableName(this.tablesMock, TABLE_A, TABLE_B, "BIN$TRASHED");
mockTableWithColumnsOfType(this.tablesMock, this.columnMetadataReaderMock, TABLE_A, DataType.createBool());
mockTableWithColumnsOfType(this.tablesMock, this.columnMetadataReaderMock, TABLE_B, DataType.createBool());
final List<String> tableNames = this.reader.mapTables(this.tablesMock) //
final List<String> tableNames = this.reader.mapTables(this.tablesMock, Optional.empty()) //
.stream() //
.map(TableMetadata::getName) //
.collect(Collectors.toList());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ private TableMetadata mapSingleTable(final PostgreSQLIdentifierMapping identifie
setIdentifierMappingProperty(identifierMapping, rawProperties);
final TableMetadataReader reader = new PostgreSQLTableMetadataReader(this.columnMetadataReaderMock,
new AdapterProperties(rawProperties));
final List<TableMetadata> tables = reader.mapTables(this.tablesMock);
final List<TableMetadata> tables = reader.mapTables(this.tablesMock, Optional.empty());
final TableMetadata table = tables.get(0);
return table;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,4 +212,22 @@ void testGetSchemaNameFilter() {
new AdapterProperties(rawProperties));
assertThat(reader.getSchemaNameFilter(), equalTo(expectedSchema));
}

// Don't mix this test up with the one for filtered tables. In the refresh request users can limit the tables they
// want refreshed. This is a different mechanism that coexists with the table filter via property. Both have to
// work together.
@Test
void testReadRemoteDataSkippingForSelectedTablesOnly() throws SQLException {
mockConnection();
mockTableA();
mockGetTableCalls();
mockSupportingMetadata();
final BaseRemoteMetadataReader reader = new BaseRemoteMetadataReader(this.connectionMock,
AdapterProperties.emptyProperties());
final SchemaMetadata metadata = reader.readRemoteSchemaMetadata(Arrays.asList(TABLE_A));
final List<TableMetadata> tables = metadata.getTables();
final TableMetadata tableAMetadata = tables.get(0);
assertAll(() -> assertThat(tables, iterableWithSize(1)),
() -> assertThat(tableAMetadata.getName(), equalTo(TABLE_A)));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import java.sql.*;
import java.util.List;
import java.util.Optional;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
Expand Down Expand Up @@ -48,7 +49,7 @@ void testMapTables() throws SQLException {
mockTableWithColumnsOfType(this.tablesMock, this.columnMetadataReaderMock, TABLE_B, DataType.createDate());
final TableMetadataReader reader = new BaseTableMetadataReader(this.columnMetadataReaderMock,
AdapterProperties.emptyProperties());
final List<TableMetadata> tables = reader.mapTables(this.tablesMock);
final List<TableMetadata> tables = reader.mapTables(this.tablesMock, Optional.empty());
final TableMetadata tableA = tables.get(0);
final TableMetadata tableB = tables.get(1);
assertAll(() -> assertThat(tables, iterableWithSize(2)), //
Expand Down Expand Up @@ -117,7 +118,7 @@ void testMapTablesIgnoresTablesThatHaveNoColumns() throws SQLException {
mockTableWithColumnsOfType(this.tablesMock, this.columnMetadataReaderMock, TABLE_A, DataType.createBool());
final TableMetadataReader reader = new BaseTableMetadataReader(this.columnMetadataReaderMock,
AdapterProperties.emptyProperties());
final List<TableMetadata> tables = reader.mapTables(this.tablesMock);
final List<TableMetadata> tables = reader.mapTables(this.tablesMock, Optional.empty());
final TableMetadata tableA = tables.get(0);
assertAll(() -> assertThat(tables, iterableWithSize(1)), //
() -> assertThat(tableA.getName(), equalTo(TABLE_A)));
Expand Down

0 comments on commit 2be1a6d

Please sign in to comment.