Skip to content

Commit f95b084

Browse files
committed
[CALCITE-6728] Introduce new methods to lookup tables and schemas inside schemas
1 parent 041619f commit f95b084

40 files changed

+1653
-511
lines changed

cassandra/src/main/java/org/apache/calcite/adapter/cassandra/CassandraSchema.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.apache.calcite.schema.Table;
3030
import org.apache.calcite.schema.impl.AbstractSchema;
3131
import org.apache.calcite.schema.impl.MaterializedViewTable;
32+
import org.apache.calcite.schema.lookup.LikePattern;
3233
import org.apache.calcite.sql.SqlSelect;
3334
import org.apache.calcite.sql.SqlWriter;
3435
import org.apache.calcite.sql.SqlWriterConfig;
@@ -325,8 +326,8 @@ private void addMaterializedViews() {
325326
query = buf.toString();
326327

327328
// Add the view for this query
328-
String viewName = "$" + getTableNames().size();
329-
SchemaPlus schema = parentSchema.getSubSchema(name);
329+
String viewName = "$" + tables().getNames(LikePattern.any()).size();
330+
SchemaPlus schema = parentSchema.subSchemas().get(name);
330331
if (schema == null) {
331332
throw new IllegalStateException("Cannot find schema " + name
332333
+ " in parent schema " + parentSchema.getName());

core/src/main/java/org/apache/calcite/adapter/clone/CloneSchema.java

+5-2
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
import org.apache.calcite.schema.Schemas;
3434
import org.apache.calcite.schema.Table;
3535
import org.apache.calcite.schema.impl.AbstractSchema;
36+
import org.apache.calcite.schema.lookup.LikePattern;
37+
import org.apache.calcite.schema.lookup.Lookup;
3638

3739
import com.google.common.base.Suppliers;
3840
import com.google.common.collect.ImmutableList;
@@ -68,8 +70,9 @@ public CloneSchema(SchemaPlus sourceSchema) {
6870

6971
@Override protected Map<String, Table> getTableMap() {
7072
final Map<String, Table> map = new LinkedHashMap<>();
71-
for (String name : sourceSchema.getTableNames()) {
72-
final Table table = sourceSchema.getTable(name);
73+
final Lookup<Table> tables = sourceSchema.tables();
74+
for (String name : tables.getNames(LikePattern.any())) {
75+
final Table table = tables.get(name);
7376
if (table instanceof QueryableTable) {
7477
final QueryableTable sourceTable = (QueryableTable) table;
7578
map.put(name,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to you under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.calcite.adapter.jdbc;
18+
19+
import org.apache.calcite.linq4j.tree.Expression;
20+
import org.apache.calcite.rel.type.RelProtoDataType;
21+
import org.apache.calcite.schema.Function;
22+
import org.apache.calcite.schema.Schema;
23+
import org.apache.calcite.schema.SchemaPlus;
24+
import org.apache.calcite.schema.SchemaVersion;
25+
import org.apache.calcite.schema.Schemas;
26+
import org.apache.calcite.schema.Table;
27+
import org.apache.calcite.schema.lookup.LikePattern;
28+
import org.apache.calcite.schema.lookup.Lookup;
29+
30+
import org.checkerframework.checker.nullness.qual.Nullable;
31+
32+
import java.util.Collection;
33+
import java.util.Collections;
34+
import java.util.Set;
35+
36+
import static java.util.Objects.requireNonNull;
37+
38+
/**
39+
* Base class for JDBC schemas.
40+
*/
41+
public abstract class JdbcBaseSchema implements Schema {
42+
43+
@Override public abstract Lookup<Table> tables();
44+
45+
46+
@Override public @Nullable Table getTable(String name) {
47+
return tables().get(name);
48+
}
49+
50+
@Override public Set<String> getTableNames() {
51+
return tables().getNames(LikePattern.any());
52+
}
53+
54+
@Override public abstract Lookup<? extends Schema> subSchemas();
55+
56+
@Override public @Nullable Schema getSubSchema(String name) {
57+
return subSchemas().get(name);
58+
}
59+
60+
@Override public Set<String> getSubSchemaNames() {
61+
return subSchemas().getNames(LikePattern.any());
62+
}
63+
64+
65+
@Override public @Nullable RelProtoDataType getType(String name) {
66+
return null;
67+
}
68+
69+
@Override public Set<String> getTypeNames() {
70+
return Collections.emptySet();
71+
}
72+
73+
@Override public final Collection<Function> getFunctions(String name) {
74+
return Collections.emptyList();
75+
}
76+
77+
@Override public final Set<String> getFunctionNames() {
78+
return Collections.emptySet();
79+
}
80+
81+
@Override public Expression getExpression(final @Nullable SchemaPlus parentSchema,
82+
final String name) {
83+
requireNonNull(parentSchema, "parentSchema");
84+
return Schemas.subSchemaExpression(parentSchema, name, getClass());
85+
}
86+
87+
@Override public boolean isMutable() {
88+
return false;
89+
}
90+
91+
@Override public Schema snapshot(final SchemaVersion version) {
92+
return this;
93+
}
94+
}

core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcCatalogSchema.java

+61-42
Original file line numberDiff line numberDiff line change
@@ -22,22 +22,27 @@
2222
import org.apache.calcite.schema.Schema;
2323
import org.apache.calcite.schema.SchemaPlus;
2424
import org.apache.calcite.schema.Schemas;
25+
import org.apache.calcite.schema.Table;
2526
import org.apache.calcite.schema.Wrapper;
26-
import org.apache.calcite.schema.impl.AbstractSchema;
27+
import org.apache.calcite.schema.lookup.IgnoreCaseLookup;
28+
import org.apache.calcite.schema.lookup.LikePattern;
29+
import org.apache.calcite.schema.lookup.LoadingCacheLookup;
30+
import org.apache.calcite.schema.lookup.Lookup;
2731
import org.apache.calcite.sql.SqlDialect;
2832
import org.apache.calcite.sql.SqlDialectFactory;
2933
import org.apache.calcite.sql.SqlDialectFactoryImpl;
3034
import org.apache.calcite.util.BuiltInMethod;
3135

3236
import com.google.common.base.Suppliers;
33-
import com.google.common.collect.ImmutableMap;
37+
import com.google.common.collect.ImmutableSet;
3438

3539
import org.checkerframework.checker.nullness.qual.Nullable;
3640

3741
import java.sql.Connection;
3842
import java.sql.ResultSet;
3943
import java.sql.SQLException;
40-
import java.util.Map;
44+
import java.util.Optional;
45+
import java.util.Set;
4146
import java.util.function.Supplier;
4247
import javax.sql.DataSource;
4348

@@ -51,20 +56,21 @@
5156
* an instance of {@link JdbcSchema}.
5257
*
5358
* <p>This schema is lazy: it does not compute the list of schema names until
54-
* the first call to {@link #getSubSchemaMap()}. Then it creates a
55-
* {@link JdbcSchema} for each schema name. Each JdbcSchema will populate its
59+
* the first call to {@link #subSchemas()} and {@link Lookup#get(String)}. Then it creates a
60+
* {@link JdbcSchema} for this schema name. Each JdbcSchema will populate its
5661
* tables on demand.
5762
*/
58-
public class JdbcCatalogSchema extends AbstractSchema implements Wrapper {
63+
public class JdbcCatalogSchema extends JdbcBaseSchema implements Wrapper {
5964
final DataSource dataSource;
6065
public final SqlDialect dialect;
6166
final JdbcConvention convention;
6267
final String catalog;
68+
private final Lookup<JdbcSchema> subSchemas;
6369

64-
/** Sub-schemas by name, lazily initialized. */
70+
/** default schema name, lazily initialized. */
6571
@SuppressWarnings({"method.invocation.invalid", "Convert2MethodRef"})
66-
final Supplier<SubSchemaMap> subSchemaMapSupplier =
67-
Suppliers.memoize(() -> computeSubSchemaMap());
72+
private final Supplier<Optional<String>> defaultSchemaName =
73+
Suppliers.memoize(() -> Optional.ofNullable(computeDefaultSchemaName()));
6874

6975
/** Creates a JdbcCatalogSchema. */
7076
public JdbcCatalogSchema(DataSource dataSource, SqlDialect dialect,
@@ -73,6 +79,40 @@ public JdbcCatalogSchema(DataSource dataSource, SqlDialect dialect,
7379
this.dialect = requireNonNull(dialect, "dialect");
7480
this.convention = requireNonNull(convention, "convention");
7581
this.catalog = catalog;
82+
this.subSchemas = new LoadingCacheLookup<>(new IgnoreCaseLookup<JdbcSchema>() {
83+
@Override public @Nullable JdbcSchema get(String name) {
84+
try (Connection connection = dataSource.getConnection();
85+
ResultSet resultSet =
86+
connection.getMetaData().getSchemas(catalog, name)) {
87+
while (resultSet.next()) {
88+
final String schemaName =
89+
requireNonNull(resultSet.getString(1),
90+
"got null schemaName from the database");
91+
return new JdbcSchema(dataSource, dialect, convention, catalog, schemaName);
92+
}
93+
} catch (SQLException e) {
94+
throw new RuntimeException(e);
95+
}
96+
return null;
97+
}
98+
99+
@Override public Set<String> getNames(LikePattern pattern) {
100+
final ImmutableSet.Builder<String> builder =
101+
ImmutableSet.builder();
102+
try (Connection connection = dataSource.getConnection();
103+
ResultSet resultSet =
104+
connection.getMetaData().getSchemas(catalog, pattern.pattern)) {
105+
while (resultSet.next()) {
106+
builder.add(
107+
requireNonNull(resultSet.getString(1),
108+
"got null schemaName from the database"));
109+
}
110+
} catch (SQLException e) {
111+
throw new RuntimeException(e);
112+
}
113+
return builder.build();
114+
}
115+
});
76116
}
77117

78118
public static JdbcCatalogSchema create(
@@ -103,34 +143,25 @@ public static JdbcCatalogSchema create(
103143
return new JdbcCatalogSchema(dataSource, dialect, convention, catalog);
104144
}
105145

106-
private SubSchemaMap computeSubSchemaMap() {
107-
final ImmutableMap.Builder<String, Schema> builder =
108-
ImmutableMap.builder();
109-
@Nullable String defaultSchemaName;
110-
try (Connection connection = dataSource.getConnection();
111-
ResultSet resultSet =
112-
connection.getMetaData().getSchemas(catalog, null)) {
113-
defaultSchemaName = connection.getSchema();
114-
while (resultSet.next()) {
115-
final String schemaName =
116-
requireNonNull(resultSet.getString(1),
117-
"got null schemaName from the database");
118-
builder.put(schemaName,
119-
new JdbcSchema(dataSource, dialect, convention, catalog, schemaName));
120-
}
146+
@Override public Lookup<Table> tables() {
147+
return Lookup.empty();
148+
}
149+
150+
@Override public Lookup<? extends Schema> subSchemas() {
151+
return subSchemas;
152+
}
153+
154+
private @Nullable String computeDefaultSchemaName() {
155+
try (Connection connection = dataSource.getConnection()) {
156+
return connection.getSchema();
121157
} catch (SQLException e) {
122158
throw new RuntimeException(e);
123159
}
124-
return new SubSchemaMap(defaultSchemaName, builder.build());
125-
}
126-
127-
@Override protected Map<String, Schema> getSubSchemaMap() {
128-
return subSchemaMapSupplier.get().map;
129160
}
130161

131162
/** Returns the name of the default sub-schema. */
132163
public @Nullable String getDefaultSubSchemaName() {
133-
return subSchemaMapSupplier.get().defaultSchemaName;
164+
return defaultSchemaName.get().orElse(null);
134165
}
135166

136167
/** Returns the data source. */
@@ -148,16 +179,4 @@ public DataSource getDataSource() {
148179
}
149180
return null;
150181
}
151-
152-
/** Contains sub-schemas by name, and the name of the default schema. */
153-
private static class SubSchemaMap {
154-
final @Nullable String defaultSchemaName;
155-
final ImmutableMap<String, Schema> map;
156-
157-
private SubSchemaMap(@Nullable String defaultSchemaName,
158-
ImmutableMap<String, Schema> map) {
159-
this.defaultSchemaName = defaultSchemaName;
160-
this.map = map;
161-
}
162-
}
163182
}

0 commit comments

Comments
 (0)