Skip to content

Commit

Permalink
Only enumerate tables when columns enumerating table is queried
Browse files Browse the repository at this point in the history
When table predicate is present one could enumerate all tables
that match the predicate. However, this is only beneficial
for columns enumerating metadata table since it can narrow
down results early.
  • Loading branch information
sopel39 committed Aug 27, 2019
1 parent 1429a85 commit 4caea76
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -290,9 +290,10 @@ private Set<QualifiedTablePrefix> getPrefixes(ConnectorSession session, Informat
return ImmutableSet.of();
}

SchemaTableName schemaTableName = handle.getSchemaTableName();
Set<QualifiedTablePrefix> prefixes = calculatePrefixesWithSchemaName(session, constraint.getSummary(), constraint.predicate());
if (isTablesEnumeratingTable(handle.getSchemaTableName())) {
Set<QualifiedTablePrefix> tablePrefixes = calculatePrefixesWithTableName(session, prefixes, constraint.getSummary(), constraint.predicate());
Set<QualifiedTablePrefix> tablePrefixes = calculatePrefixesWithTableName(schemaTableName, session, prefixes, constraint.getSummary(), constraint.predicate());
// in case of high number of prefixes it is better to populate all data and then filter
if (tablePrefixes.size() <= MAX_PREFIXES_COUNT) {
prefixes = tablePrefixes;
Expand Down Expand Up @@ -332,6 +333,7 @@ private Set<QualifiedTablePrefix> calculatePrefixesWithSchemaName(
}

public Set<QualifiedTablePrefix> calculatePrefixesWithTableName(
SchemaTableName schemaTableName,
ConnectorSession connectorSession,
Set<QualifiedTablePrefix> prefixes,
TupleDomain<ColumnHandle> constraint,
Expand All @@ -346,23 +348,28 @@ public Set<QualifiedTablePrefix> calculatePrefixesWithTableName(
.filter(this::isLowerCase)
.map(table -> table.toLowerCase(ENGLISH))
.map(table -> new QualifiedObjectName(catalogName, prefix.getSchemaName().get(), table)))
.filter(objectName -> metadata.getTableHandle(session, objectName).isPresent() || metadata.getView(session, objectName).isPresent())
.filter(objectName -> !isColumnsEnumeratingTable(schemaTableName) || metadata.getTableHandle(session, objectName).isPresent() || metadata.getView(session, objectName).isPresent())
.filter(objectName -> !predicate.isPresent() || predicate.get().test(asFixedValues(objectName)))
.map(QualifiedObjectName::asQualifiedTablePrefix)
.collect(toImmutableSet());
}

if (predicate.isPresent()) {
return prefixes.stream()
.flatMap(prefix -> Stream.concat(
metadata.listTables(session, prefix).stream(),
metadata.listViews(session, prefix).stream()))
.filter(objectName -> predicate.get().test(asFixedValues(objectName)))
.map(QualifiedObjectName::asQualifiedTablePrefix)
.collect(toImmutableSet());
if (!predicate.isPresent() || !isColumnsEnumeratingTable(schemaTableName)) {
return prefixes;
}

return prefixes;
return prefixes.stream()
.flatMap(prefix -> Stream.concat(
metadata.listTables(session, prefix).stream(),
metadata.listViews(session, prefix).stream()))
.filter(objectName -> predicate.get().test(asFixedValues(objectName)))
.map(QualifiedObjectName::asQualifiedTablePrefix)
.collect(toImmutableSet());
}

private boolean isColumnsEnumeratingTable(SchemaTableName schemaTableName)
{
return TABLE_COLUMNS.equals(schemaTableName);
}

private Stream<QualifiedTablePrefix> listSchemaNames(Session session)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import io.prestosql.transaction.TransactionManager;
import org.testng.annotations.Test;

import java.util.Map;
import java.util.Optional;

import static com.google.common.collect.ImmutableSet.toImmutableSet;
Expand Down Expand Up @@ -123,30 +124,12 @@ public void testInformationSchemaPredicatePushdown()
public void testInformationSchemaPredicatePushdownWithConstraintPredicate()
{
TransactionId transactionId = transactionManager.beginTransaction(false);
Constraint constraint = new Constraint(
TupleDomain.all(),
// test_schema has a table named "another_table" and we filter that out in this predicate
bindings -> {
NullableValue catalog = bindings.get(new InformationSchemaColumnHandle("table_catalog"));
NullableValue schema = bindings.get(new InformationSchemaColumnHandle("table_schema"));
NullableValue table = bindings.get(new InformationSchemaColumnHandle("table_name"));
boolean isValid = true;
if (catalog != null) {
isValid = ((Slice) catalog.getValue()).toStringUtf8().equals("test_catalog");
}
if (schema != null) {
isValid &= ((Slice) schema.getValue()).toStringUtf8().equals("test_schema");
}
if (table != null) {
isValid &= ((Slice) table.getValue()).toStringUtf8().equals("test_view");
}
return isValid;
});
Constraint constraint = new Constraint(TupleDomain.all(), TestInformationSchemaMetadata::testConstraint);

ConnectorSession session = createNewSession(transactionId);
ConnectorMetadata metadata = new InformationSchemaMetadata("test_catalog", this.metadata);
InformationSchemaTableHandle tableHandle = (InformationSchemaTableHandle)
metadata.getTableHandle(session, new SchemaTableName("information_schema", "views"));
metadata.getTableHandle(session, new SchemaTableName("information_schema", "columns"));
tableHandle = metadata.applyFilter(session, tableHandle, constraint)
.map(ConstraintApplicationResult::getHandle)
.map(InformationSchemaTableHandle.class::cast)
Expand Down Expand Up @@ -176,6 +159,44 @@ public void testInformationSchemaPredicatePushdownWithoutTablePredicate()
assertEquals(tableHandle.getPrefixes(), ImmutableSet.of(new QualifiedTablePrefix("test_catalog", "test_schema")));
}

@Test
public void testInformationSchemaPredicatePushdownWithConstraintPredicateOnViewsTable()
{
TransactionId transactionId = transactionManager.beginTransaction(false);

// predicate on non columns enumerating table should not cause tables to be enumerated
Constraint constraint = new Constraint(TupleDomain.all(), TestInformationSchemaMetadata::testConstraint);
ConnectorSession session = createNewSession(transactionId);
ConnectorMetadata metadata = new InformationSchemaMetadata("test_catalog", this.metadata);
InformationSchemaTableHandle tableHandle = (InformationSchemaTableHandle)
metadata.getTableHandle(session, new SchemaTableName("information_schema", "views"));
tableHandle = metadata.applyFilter(session, tableHandle, constraint)
.map(ConstraintApplicationResult::getHandle)
.map(InformationSchemaTableHandle.class::cast)
.orElseThrow(AssertionError::new);

assertEquals(tableHandle.getPrefixes(), ImmutableSet.of(new QualifiedTablePrefix("test_catalog", "test_schema")));
}

private static boolean testConstraint(Map<ColumnHandle, NullableValue> bindings)
{
// test_schema has a table named "another_table" and we filter that out in this predicate
NullableValue catalog = bindings.get(new InformationSchemaColumnHandle("table_catalog"));
NullableValue schema = bindings.get(new InformationSchemaColumnHandle("table_schema"));
NullableValue table = bindings.get(new InformationSchemaColumnHandle("table_name"));
boolean isValid = true;
if (catalog != null) {
isValid = ((Slice) catalog.getValue()).toStringUtf8().equals("test_catalog");
}
if (schema != null) {
isValid &= ((Slice) schema.getValue()).toStringUtf8().equals("test_schema");
}
if (table != null) {
isValid &= ((Slice) table.getValue()).toStringUtf8().equals("test_view");
}
return isValid;
}

private static ConnectorSession createNewSession(TransactionId transactionId)
{
return testSessionBuilder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ public void testLargeData()
assertQuery("SELECT count(*) from test_catalog.information_schema.tables WHERE table_name LIKE 'test_t_ble1'", "VALUES 2");
assertQuery("SELECT count(*) from test_catalog.information_schema.tables WHERE table_name LIKE 'test_t_ble1' AND table_name IN ('test_table1', 'test_table2')", "VALUES 2");
assertQuery("SELECT count(*) from test_catalog.information_schema.columns WHERE table_schema = 'test_schema1' AND table_name = 'test_table1'", "VALUES 100");
assertEquals(METADATA_CALLS_COUNTER.get() - metadataCallsCountBeforeTests, 30);
assertEquals(METADATA_CALLS_COUNTER.get() - metadataCallsCountBeforeTests, 29);
}

private static DistributedQueryRunner createQueryRunner()
Expand Down

0 comments on commit 4caea76

Please sign in to comment.