This is an automated email from the ASF dual-hosted git repository.
cwylie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/druid.git
The following commit(s) were added to refs/heads/master by this push:
new 392f0ca refactor sql authorization to get resource type from schema,
resource type to be string (#11692)
392f0ca is described below
commit 392f0ca1b52ee66aa8b3affed58eb117bb44d910
Author: Clint Wylie <[email protected]>
AuthorDate: Fri Sep 17 09:53:25 2021 -0700
refactor sql authorization to get resource type from schema, resource type
to be string (#11692)
* refactor sql authorization to get resource type from schema, refactor
resource type from enum to string
* information schema auth filtering adjustments
* refactor
* minor stuff
* Update SqlResourceCollectorShuttle.java
---
.../apache/druid/benchmark/query/SqlBenchmark.java | 4 +-
.../benchmark/query/SqlExpressionBenchmark.java | 4 +-
.../benchmark/query/SqlVsNativeBenchmark.java | 4 +-
.../authorization/BasicRoleBasedAuthorizer.java | 3 +-
.../apache/druid/security/BasicAuthUtilsTest.java | 16 +--
.../ranger/authorizer/RangerAuthorizer.java | 2 +-
.../druid/server/security/AuthorizationUtils.java | 61 +++------
.../org/apache/druid/server/security/Resource.java | 14 +--
.../apache/druid/server/security/ResourceType.java | 48 +++++--
.../server/security/AuthorizationUtilsTest.java | 15 ++-
.../druid/sql/calcite/planner/DruidPlanner.java | 2 +-
.../druid/sql/calcite/planner/PlannerContext.java | 13 ++
.../druid/sql/calcite/planner/PlannerFactory.java | 7 +-
.../planner/SqlResourceCollectorShuttle.java | 15 ++-
.../calcite/schema/DruidCalciteSchemaModule.java | 7 +-
.../sql/calcite/schema/DruidSchemaCatalog.java | 138 +++++++++++++++++++++
.../sql/calcite/schema/InformationSchema.java | 72 ++++++-----
.../druid/sql/calcite/schema/NamedDruidSchema.java | 11 +-
.../sql/calcite/schema/NamedLookupSchema.java | 4 +-
.../druid/sql/calcite/schema/NamedSchema.java | 13 ++
.../sql/calcite/schema/NamedSystemSchema.java | 6 +-
.../druid/sql/calcite/schema/NamedViewSchema.java | 9 +-
.../sql/calcite/schema/RootSchemaProvider.java | 31 ++---
.../druid/sql/avatica/DruidAvaticaHandlerTest.java | 15 ++-
.../druid/sql/avatica/DruidStatementTest.java | 4 +-
.../druid/sql/calcite/BaseCalciteQueryTest.java | 4 +-
.../calcite/SqlVectorizedExpressionSanityTest.java | 4 +-
.../calcite/expression/ExpressionTestHelper.java | 14 +++
.../calcite/planner/CalcitePlannerModuleTest.java | 12 +-
.../schema/DruidCalciteSchemaModuleTest.java | 17 ++-
.../sql/calcite/schema/RootSchemaProviderTest.java | 7 +-
.../druid/sql/calcite/util/CalciteTests.java | 69 +++++++----
.../org/apache/druid/sql/http/SqlResourceTest.java | 4 +-
33 files changed, 441 insertions(+), 208 deletions(-)
diff --git
a/benchmarks/src/test/java/org/apache/druid/benchmark/query/SqlBenchmark.java
b/benchmarks/src/test/java/org/apache/druid/benchmark/query/SqlBenchmark.java
index 7d9a55d..12b717e 100644
---
a/benchmarks/src/test/java/org/apache/druid/benchmark/query/SqlBenchmark.java
+++
b/benchmarks/src/test/java/org/apache/druid/benchmark/query/SqlBenchmark.java
@@ -21,7 +21,6 @@ package org.apache.druid.benchmark.query;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
-import org.apache.calcite.schema.SchemaPlus;
import org.apache.druid.common.config.NullHandling;
import org.apache.druid.java.util.common.granularity.Granularities;
import org.apache.druid.java.util.common.guava.Sequence;
@@ -46,6 +45,7 @@ import org.apache.druid.sql.calcite.planner.DruidPlanner;
import org.apache.druid.sql.calcite.planner.PlannerConfig;
import org.apache.druid.sql.calcite.planner.PlannerFactory;
import org.apache.druid.sql.calcite.planner.PlannerResult;
+import org.apache.druid.sql.calcite.schema.DruidSchemaCatalog;
import org.apache.druid.sql.calcite.util.CalciteTests;
import org.apache.druid.sql.calcite.util.SpecificSegmentsQuerySegmentWalker;
import org.apache.druid.timeline.DataSegment;
@@ -421,7 +421,7 @@ public class SqlBenchmark
);
closer.register(walker);
- final SchemaPlus rootSchema =
+ final DruidSchemaCatalog rootSchema =
CalciteTests.createMockRootSchema(conglomerate, walker, plannerConfig,
AuthTestUtils.TEST_AUTHORIZER_MAPPER);
plannerFactory = new PlannerFactory(
rootSchema,
diff --git
a/benchmarks/src/test/java/org/apache/druid/benchmark/query/SqlExpressionBenchmark.java
b/benchmarks/src/test/java/org/apache/druid/benchmark/query/SqlExpressionBenchmark.java
index cb5ce5f..3f99b24 100644
---
a/benchmarks/src/test/java/org/apache/druid/benchmark/query/SqlExpressionBenchmark.java
+++
b/benchmarks/src/test/java/org/apache/druid/benchmark/query/SqlExpressionBenchmark.java
@@ -21,7 +21,6 @@ package org.apache.druid.benchmark.query;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
-import org.apache.calcite.schema.SchemaPlus;
import org.apache.druid.common.config.NullHandling;
import org.apache.druid.java.util.common.granularity.Granularities;
import org.apache.druid.java.util.common.guava.Sequence;
@@ -42,6 +41,7 @@ import org.apache.druid.sql.calcite.planner.DruidPlanner;
import org.apache.druid.sql.calcite.planner.PlannerConfig;
import org.apache.druid.sql.calcite.planner.PlannerFactory;
import org.apache.druid.sql.calcite.planner.PlannerResult;
+import org.apache.druid.sql.calcite.schema.DruidSchemaCatalog;
import org.apache.druid.sql.calcite.util.CalciteTests;
import org.apache.druid.sql.calcite.util.SpecificSegmentsQuerySegmentWalker;
import org.apache.druid.timeline.DataSegment;
@@ -264,7 +264,7 @@ public class SqlExpressionBenchmark
);
closer.register(walker);
- final SchemaPlus rootSchema =
+ final DruidSchemaCatalog rootSchema =
CalciteTests.createMockRootSchema(conglomerate, walker, plannerConfig,
AuthTestUtils.TEST_AUTHORIZER_MAPPER);
plannerFactory = new PlannerFactory(
rootSchema,
diff --git
a/benchmarks/src/test/java/org/apache/druid/benchmark/query/SqlVsNativeBenchmark.java
b/benchmarks/src/test/java/org/apache/druid/benchmark/query/SqlVsNativeBenchmark.java
index dda14ff..9e805d8 100644
---
a/benchmarks/src/test/java/org/apache/druid/benchmark/query/SqlVsNativeBenchmark.java
+++
b/benchmarks/src/test/java/org/apache/druid/benchmark/query/SqlVsNativeBenchmark.java
@@ -19,7 +19,6 @@
package org.apache.druid.benchmark.query;
-import org.apache.calcite.schema.SchemaPlus;
import org.apache.druid.common.config.NullHandling;
import org.apache.druid.java.util.common.Intervals;
import org.apache.druid.java.util.common.granularity.Granularities;
@@ -43,6 +42,7 @@ import org.apache.druid.sql.calcite.planner.DruidPlanner;
import org.apache.druid.sql.calcite.planner.PlannerConfig;
import org.apache.druid.sql.calcite.planner.PlannerFactory;
import org.apache.druid.sql.calcite.planner.PlannerResult;
+import org.apache.druid.sql.calcite.schema.DruidSchemaCatalog;
import org.apache.druid.sql.calcite.util.CalciteTests;
import org.apache.druid.sql.calcite.util.SpecificSegmentsQuerySegmentWalker;
import org.apache.druid.timeline.DataSegment;
@@ -111,7 +111,7 @@ public class SqlVsNativeBenchmark
final PlannerConfig plannerConfig = new PlannerConfig();
this.walker = closer.register(new
SpecificSegmentsQuerySegmentWalker(conglomerate).add(dataSegment, index));
- final SchemaPlus rootSchema =
+ final DruidSchemaCatalog rootSchema =
CalciteTests.createMockRootSchema(conglomerate, walker, plannerConfig,
AuthTestUtils.TEST_AUTHORIZER_MAPPER);
plannerFactory = new PlannerFactory(
rootSchema,
diff --git
a/extensions-core/druid-basic-security/src/main/java/org/apache/druid/security/basic/authorization/BasicRoleBasedAuthorizer.java
b/extensions-core/druid-basic-security/src/main/java/org/apache/druid/security/basic/authorization/BasicRoleBasedAuthorizer.java
index f307b9e..206e895 100644
---
a/extensions-core/druid-basic-security/src/main/java/org/apache/druid/security/basic/authorization/BasicRoleBasedAuthorizer.java
+++
b/extensions-core/druid-basic-security/src/main/java/org/apache/druid/security/basic/authorization/BasicRoleBasedAuthorizer.java
@@ -36,6 +36,7 @@ import org.apache.druid.server.security.Resource;
import java.util.HashSet;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -116,7 +117,7 @@ public class BasicRoleBasedAuthorizer implements Authorizer
}
Resource permissionResource = permission.getResourceAction().getResource();
- if (permissionResource.getType() != resource.getType()) {
+ if (!Objects.equals(permissionResource.getType(), resource.getType())) {
return false;
}
diff --git
a/extensions-core/druid-basic-security/src/test/java/org/apache/druid/security/BasicAuthUtilsTest.java
b/extensions-core/druid-basic-security/src/test/java/org/apache/druid/security/BasicAuthUtilsTest.java
index 7bcb1e2..60235fb 100644
---
a/extensions-core/druid-basic-security/src/test/java/org/apache/druid/security/BasicAuthUtilsTest.java
+++
b/extensions-core/druid-basic-security/src/test/java/org/apache/druid/security/BasicAuthUtilsTest.java
@@ -60,6 +60,7 @@ public class BasicAuthUtilsTest
final String thirdRoleName = "third-role";
final ResourceAction fooRead = new ResourceAction(new Resource("foo",
ResourceType.DATASOURCE), Action.READ);
final ResourceAction barRead = new ResourceAction(new Resource("bar",
ResourceType.DATASOURCE), Action.READ);
+ final ResourceAction customRead = new ResourceAction(new Resource("bar",
"CUSTOM"), Action.READ);
final ObjectMapper mapper = TestHelper.makeJsonMapper();
mapper.registerModules(new BasicSecurityDruidModule().getJacksonModules());
@@ -76,7 +77,7 @@ public class BasicAuthUtilsTest
)
)
);
- // bad ResourceType
+ // custom ResourceType
rawMap.put(
otherRoleName,
ImmutableMap.of(
@@ -89,12 +90,7 @@ public class BasicAuthUtilsTest
"resourceNamePattern", "foo"
),
ImmutableMap.of(
- "resourceAction",
- ImmutableMap.of(
- "resource",
- ImmutableMap.of("name", "bar", "type", "UNKNOWN"),
- "action", "READ"
- ),
+ "resourceAction", customRead,
"resourceNamePattern", "bar"
)
)
@@ -141,11 +137,11 @@ public class BasicAuthUtilsTest
roleMap.get(someRoleName).getPermissions()
);
- // this one has an unknown ResourceType, expect only 1 permission to
deserialize correctly and failure ignored
+ // this one has custom resource type... this test is somewhat pointless,
it made more sense when type was an enum
Assert.assertTrue(roleMap.containsKey(otherRoleName));
- Assert.assertEquals(1, roleMap.get(otherRoleName).getPermissions().size());
+ Assert.assertEquals(2, roleMap.get(otherRoleName).getPermissions().size());
Assert.assertEquals(
-
BasicAuthorizerPermission.makePermissionList(ImmutableList.of(fooRead)),
+ BasicAuthorizerPermission.makePermissionList(ImmutableList.of(fooRead,
customRead)),
roleMap.get(otherRoleName).getPermissions()
);
diff --git
a/extensions-core/druid-ranger-security/src/main/java/org/apache/druid/security/ranger/authorizer/RangerAuthorizer.java
b/extensions-core/druid-ranger-security/src/main/java/org/apache/druid/security/ranger/authorizer/RangerAuthorizer.java
index 330a7c0..1d4bf15 100644
---
a/extensions-core/druid-ranger-security/src/main/java/org/apache/druid/security/ranger/authorizer/RangerAuthorizer.java
+++
b/extensions-core/druid-ranger-security/src/main/java/org/apache/druid/security/ranger/authorizer/RangerAuthorizer.java
@@ -126,7 +126,7 @@ class RangerDruidResource extends RangerAccessResourceImpl
{
public RangerDruidResource(Resource resource)
{
- setValue(resource.getType().name().toLowerCase(Locale.ENGLISH),
resource.getName());
+ setValue(resource.getType().toLowerCase(Locale.ENGLISH),
resource.getName());
}
}
diff --git
a/server/src/main/java/org/apache/druid/server/security/AuthorizationUtils.java
b/server/src/main/java/org/apache/druid/server/security/AuthorizationUtils.java
index 6ba34f6..2b44498 100644
---
a/server/src/main/java/org/apache/druid/server/security/AuthorizationUtils.java
+++
b/server/src/main/java/org/apache/druid/server/security/AuthorizationUtils.java
@@ -25,6 +25,7 @@ import com.google.common.collect.Lists;
import org.apache.druid.java.util.common.ISE;
import javax.servlet.http.HttpServletRequest;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -359,49 +360,27 @@ public class AuthorizationUtils
return filteredResources;
}
+ /**
+ * This method constructs a 'superuser' set of permissions composed of
{@link Action#READ} and {@link Action#WRITE}
+ * permissions for all known {@link ResourceType#knownTypes()} for any
{@link Authorizer} implementation which is
+ * built on pattern matching with a regex.
+ *
+ * Note that if any {@link Resource} exist that use custom types not
registered with
+ * {@link ResourceType#registerResourceType}, those permissions will not be
included in this list and will need to
+ * be added manually.
+ */
public static List<ResourceAction> makeSuperUserPermissions()
{
- ResourceAction datasourceR = new ResourceAction(
- new Resource(".*", ResourceType.DATASOURCE),
- Action.READ
- );
-
- ResourceAction datasourceW = new ResourceAction(
- new Resource(".*", ResourceType.DATASOURCE),
- Action.WRITE
- );
-
- ResourceAction viewR = new ResourceAction(
- new Resource(".*", ResourceType.VIEW),
- Action.READ
- );
-
- ResourceAction viewW = new ResourceAction(
- new Resource(".*", ResourceType.VIEW),
- Action.WRITE
- );
-
- ResourceAction configR = new ResourceAction(
- new Resource(".*", ResourceType.CONFIG),
- Action.READ
- );
-
- ResourceAction configW = new ResourceAction(
- new Resource(".*", ResourceType.CONFIG),
- Action.WRITE
- );
-
- ResourceAction stateR = new ResourceAction(
- new Resource(".*", ResourceType.STATE),
- Action.READ
- );
-
- ResourceAction stateW = new ResourceAction(
- new Resource(".*", ResourceType.STATE),
- Action.WRITE
- );
-
- return Lists.newArrayList(datasourceR, datasourceW, viewR, viewW, configR,
configW, stateR, stateW);
+ List<ResourceAction> allReadAndWrite = new
ArrayList<>(ResourceType.knownTypes().size() * 2);
+ for (String type : ResourceType.knownTypes()) {
+ allReadAndWrite.add(
+ new ResourceAction(new Resource(".*", type), Action.READ)
+ );
+ allReadAndWrite.add(
+ new ResourceAction(new Resource(".*", type), Action.WRITE)
+ );
+ }
+ return allReadAndWrite;
}
/**
diff --git
a/server/src/main/java/org/apache/druid/server/security/Resource.java
b/server/src/main/java/org/apache/druid/server/security/Resource.java
index 6770bda..710673f 100644
--- a/server/src/main/java/org/apache/druid/server/security/Resource.java
+++ b/server/src/main/java/org/apache/druid/server/security/Resource.java
@@ -22,17 +22,19 @@ package org.apache.druid.server.security;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.Objects;
+
public class Resource
{
public static final Resource STATE_RESOURCE = new Resource("STATE",
ResourceType.STATE);
private final String name;
- private final ResourceType type;
+ private final String type;
@JsonCreator
public Resource(
@JsonProperty("name") String name,
- @JsonProperty("type") ResourceType type
+ @JsonProperty("type") String type
)
{
this.name = name;
@@ -46,7 +48,7 @@ public class Resource
}
@JsonProperty
- public ResourceType getType()
+ public String getType()
{
return type;
}
@@ -66,16 +68,14 @@ public class Resource
if (!name.equals(resource.name)) {
return false;
}
- return type == resource.type;
+ return Objects.equals(type, resource.type);
}
@Override
public int hashCode()
{
- int result = name.hashCode();
- result = 31 * result + type.hashCode();
- return result;
+ return Objects.hash(name, type);
}
@Override
diff --git
a/server/src/main/java/org/apache/druid/server/security/ResourceType.java
b/server/src/main/java/org/apache/druid/server/security/ResourceType.java
index 04cf43a..0e02572 100644
--- a/server/src/main/java/org/apache/druid/server/security/ResourceType.java
+++ b/server/src/main/java/org/apache/druid/server/security/ResourceType.java
@@ -19,22 +19,44 @@
package org.apache.druid.server.security;
-import com.fasterxml.jackson.annotation.JsonCreator;
-import org.apache.druid.java.util.common.StringUtils;
+import com.google.common.collect.Sets;
-public enum ResourceType
+import java.util.Set;
+
+/**
+ * Set of built-in and 'registered' {@link Resource} types for use by {@link
Authorizer}
+ */
+public class ResourceType
{
- DATASOURCE,
- VIEW,
- CONFIG,
- STATE;
+ public static final String DATASOURCE = "DATASOURCE";
+ public static final String VIEW = "VIEW";
+ public static final String CONFIG = "CONFIG";
+ public static final String STATE = "STATE";
+
+ private static final Set<String> KNOWN_TYPES = Sets.newConcurrentHashSet();
+
+ // initialize built-ins
+ static {
+ registerResourceType(DATASOURCE);
+ registerResourceType(VIEW);
+ registerResourceType(CONFIG);
+ registerResourceType(STATE);
+ }
+
+ /**
+ * Set of 'known' {@link Resource} types which have been registered with
{@link #registerResourceType}, for use by
+ * utility methods looking to construct permission sets for all types (e.g.
'superuser' permission set)
+ */
+ public static Set<String> knownTypes()
+ {
+ return KNOWN_TYPES;
+ }
- @JsonCreator
- public static ResourceType fromString(String name)
+ /**
+ * 'register' a 'known' type of {@link Resource} to make available via
{@link #knownTypes()}
+ */
+ public static void registerResourceType(String type)
{
- if (name == null) {
- return null;
- }
- return valueOf(StringUtils.toUpperCase(name));
+ KNOWN_TYPES.add(type);
}
}
diff --git
a/server/src/test/java/org/apache/druid/server/security/AuthorizationUtilsTest.java
b/server/src/test/java/org/apache/druid/server/security/AuthorizationUtilsTest.java
index 8c6ec81..a9d87a4 100644
---
a/server/src/test/java/org/apache/druid/server/security/AuthorizationUtilsTest.java
+++
b/server/src/test/java/org/apache/druid/server/security/AuthorizationUtilsTest.java
@@ -30,6 +30,7 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
public class AuthorizationUtilsTest
{
@@ -88,16 +89,26 @@ public class AuthorizationUtilsTest
@Test
public void testMakeSuperuserPermissions()
{
+ final String customType = "CUSTOM";
+ ResourceType.registerResourceType(customType);
final List<ResourceAction> permissions =
AuthorizationUtils.makeSuperUserPermissions();
// every type and action should have a wildcard pattern
- for (ResourceType type : ResourceType.values()) {
+ for (String type : ResourceType.knownTypes()) {
for (Action action : Action.values()) {
Assert.assertTrue(
permissions.stream()
- .filter(ra -> type == ra.getResource().getType())
+ .filter(ra -> Objects.equals(type,
ra.getResource().getType()))
.anyMatch(ra -> action == ra.getAction() &&
".*".equals(ra.getResource().getName()))
);
}
}
+ // custom type should be there too
+ for (Action action : Action.values()) {
+ Assert.assertTrue(
+ permissions.stream()
+ .filter(ra -> Objects.equals(customType,
ra.getResource().getType()))
+ .anyMatch(ra -> action == ra.getAction() &&
".*".equals(ra.getResource().getName()))
+ );
+ }
}
}
diff --git
a/sql/src/main/java/org/apache/druid/sql/calcite/planner/DruidPlanner.java
b/sql/src/main/java/org/apache/druid/sql/calcite/planner/DruidPlanner.java
index 1618e61..a1b9149 100644
--- a/sql/src/main/java/org/apache/druid/sql/calcite/planner/DruidPlanner.java
+++ b/sql/src/main/java/org/apache/druid/sql/calcite/planner/DruidPlanner.java
@@ -120,7 +120,7 @@ public class DruidPlanner implements Closeable
throw new ValidationException(e);
}
SqlResourceCollectorShuttle resourceCollectorShuttle =
- new SqlResourceCollectorShuttle(validator,
frameworkConfig.getDefaultSchema().getName());
+ new SqlResourceCollectorShuttle(validator, plannerContext);
validated.accept(resourceCollectorShuttle);
plannerContext.setResources(resourceCollectorShuttle.getResources());
return new ValidationResult(resourceCollectorShuttle.getResources());
diff --git
a/sql/src/main/java/org/apache/druid/sql/calcite/planner/PlannerContext.java
b/sql/src/main/java/org/apache/druid/sql/calcite/planner/PlannerContext.java
index 59d4bd8..0ec442e 100644
--- a/sql/src/main/java/org/apache/druid/sql/calcite/planner/PlannerContext.java
+++ b/sql/src/main/java/org/apache/druid/sql/calcite/planner/PlannerContext.java
@@ -33,10 +33,12 @@ import org.apache.druid.math.expr.ExprMacroTable;
import org.apache.druid.server.security.Access;
import org.apache.druid.server.security.AuthenticationResult;
import org.apache.druid.server.security.Resource;
+import org.apache.druid.sql.calcite.schema.DruidSchemaCatalog;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.Interval;
+import javax.annotation.Nullable;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@@ -68,6 +70,7 @@ public class PlannerContext
private final ExprMacroTable macroTable;
private final PlannerConfig plannerConfig;
private final DateTime localNow;
+ private final DruidSchemaCatalog rootSchema;
private final Map<String, Object> queryContext;
private final String sqlQueryId;
private final boolean stringifyArrays;
@@ -87,12 +90,14 @@ public class PlannerContext
final PlannerConfig plannerConfig,
final DateTime localNow,
final boolean stringifyArrays,
+ final DruidSchemaCatalog rootSchema,
final Map<String, Object> queryContext
)
{
this.operatorTable = operatorTable;
this.macroTable = macroTable;
this.plannerConfig = Preconditions.checkNotNull(plannerConfig,
"plannerConfig");
+ this.rootSchema = rootSchema;
this.queryContext = queryContext != null ? new HashMap<>(queryContext) :
new HashMap<>();
this.localNow = Preconditions.checkNotNull(localNow, "localNow");
this.stringifyArrays = stringifyArrays;
@@ -109,6 +114,7 @@ public class PlannerContext
final DruidOperatorTable operatorTable,
final ExprMacroTable macroTable,
final PlannerConfig plannerConfig,
+ final DruidSchemaCatalog rootSchema,
final Map<String, Object> queryContext
)
{
@@ -150,6 +156,7 @@ public class PlannerContext
plannerConfig.withOverrides(queryContext),
utcNow.withZone(timeZone),
stringifyArrays,
+ rootSchema,
queryContext
);
}
@@ -179,6 +186,12 @@ public class PlannerContext
return localNow.getZone();
}
+ @Nullable
+ public String getSchemaResourceType(String schema, String resourceName)
+ {
+ return rootSchema.getResourceType(schema, resourceName);
+ }
+
public Map<String, Object> getQueryContext()
{
return queryContext;
diff --git
a/sql/src/main/java/org/apache/druid/sql/calcite/planner/PlannerFactory.java
b/sql/src/main/java/org/apache/druid/sql/calcite/planner/PlannerFactory.java
index 9f86eda..a96818e 100644
--- a/sql/src/main/java/org/apache/druid/sql/calcite/planner/PlannerFactory.java
+++ b/sql/src/main/java/org/apache/druid/sql/calcite/planner/PlannerFactory.java
@@ -29,7 +29,6 @@ import org.apache.calcite.config.CalciteConnectionConfigImpl;
import org.apache.calcite.plan.Context;
import org.apache.calcite.plan.ConventionTraitDef;
import org.apache.calcite.rel.RelCollationTraitDef;
-import org.apache.calcite.schema.SchemaPlus;
import org.apache.calcite.sql.parser.SqlParseException;
import org.apache.calcite.sql.parser.SqlParser;
import org.apache.calcite.sql.validate.SqlConformance;
@@ -44,6 +43,7 @@ import org.apache.druid.server.security.Access;
import org.apache.druid.server.security.AuthorizerMapper;
import org.apache.druid.server.security.NoopEscalator;
import org.apache.druid.sql.calcite.rel.QueryMaker;
+import org.apache.druid.sql.calcite.schema.DruidSchemaCatalog;
import org.apache.druid.sql.calcite.schema.DruidSchemaName;
import java.util.Map;
@@ -60,7 +60,7 @@ public class PlannerFactory
.setConformance(DruidConformance.instance())
.build();
- private final SchemaPlus rootSchema;
+ private final DruidSchemaCatalog rootSchema;
private final QueryLifecycleFactory queryLifecycleFactory;
private final DruidOperatorTable operatorTable;
private final ExprMacroTable macroTable;
@@ -71,7 +71,7 @@ public class PlannerFactory
@Inject
public PlannerFactory(
- final SchemaPlus rootSchema,
+ final DruidSchemaCatalog rootSchema,
final QueryLifecycleFactory queryLifecycleFactory,
final DruidOperatorTable operatorTable,
final ExprMacroTable macroTable,
@@ -100,6 +100,7 @@ public class PlannerFactory
operatorTable,
macroTable,
plannerConfig,
+ rootSchema,
queryContext
);
final QueryMaker queryMaker = new QueryMaker(queryLifecycleFactory,
plannerContext, jsonMapper);
diff --git
a/sql/src/main/java/org/apache/druid/sql/calcite/planner/SqlResourceCollectorShuttle.java
b/sql/src/main/java/org/apache/druid/sql/calcite/planner/SqlResourceCollectorShuttle.java
index aba6689..a333b03 100644
---
a/sql/src/main/java/org/apache/druid/sql/calcite/planner/SqlResourceCollectorShuttle.java
+++
b/sql/src/main/java/org/apache/druid/sql/calcite/planner/SqlResourceCollectorShuttle.java
@@ -28,7 +28,6 @@ import org.apache.calcite.sql.validate.SqlValidatorNamespace;
import org.apache.calcite.sql.validate.SqlValidatorTable;
import org.apache.druid.server.security.Resource;
import org.apache.druid.server.security.ResourceType;
-import org.apache.druid.sql.calcite.schema.NamedViewSchema;
import java.util.HashSet;
import java.util.List;
@@ -45,14 +44,14 @@ import java.util.Set;
public class SqlResourceCollectorShuttle extends SqlShuttle
{
private final Set<Resource> resources;
+ private final PlannerContext plannerContext;
private final SqlValidator validator;
- private final String druidSchemaName;
- public SqlResourceCollectorShuttle(SqlValidator validator, String
druidSchemaName)
+ public SqlResourceCollectorShuttle(SqlValidator validator, PlannerContext
plannerContext)
{
this.validator = validator;
this.resources = new HashSet<>();
- this.druidSchemaName = druidSchemaName;
+ this.plannerContext = plannerContext;
}
@Override
@@ -69,10 +68,10 @@ public class SqlResourceCollectorShuttle extends SqlShuttle
// 'schema'.'identifier'
if (qualifiedNameParts.size() == 2) {
final String schema = qualifiedNameParts.get(0);
- if (druidSchemaName.equals(schema)) {
- resources.add(new Resource(qualifiedNameParts.get(1),
ResourceType.DATASOURCE));
- } else if (NamedViewSchema.NAME.equals(schema)) {
- resources.add(new Resource(qualifiedNameParts.get(1),
ResourceType.VIEW));
+ final String resourceName = qualifiedNameParts.get(1);
+ final String resourceType =
plannerContext.getSchemaResourceType(schema, resourceName);
+ if (resourceType != null) {
+ resources.add(new Resource(resourceName, resourceType));
}
}
}
diff --git
a/sql/src/main/java/org/apache/druid/sql/calcite/schema/DruidCalciteSchemaModule.java
b/sql/src/main/java/org/apache/druid/sql/calcite/schema/DruidCalciteSchemaModule.java
index 43e8ad7..0a8de29 100644
---
a/sql/src/main/java/org/apache/druid/sql/calcite/schema/DruidCalciteSchemaModule.java
+++
b/sql/src/main/java/org/apache/druid/sql/calcite/schema/DruidCalciteSchemaModule.java
@@ -26,7 +26,6 @@ import com.google.inject.Scopes;
import com.google.inject.Singleton;
import com.google.inject.name.Named;
import com.google.inject.name.Names;
-import org.apache.calcite.schema.SchemaPlus;
import org.apache.druid.guice.LifecycleModule;
import org.apache.druid.sql.guice.SqlBindings;
@@ -45,7 +44,7 @@ public class DruidCalciteSchemaModule implements Module
binder.bind(String.class).annotatedWith(DruidSchemaName.class).toInstance(DRUID_SCHEMA_NAME);
// Should only be used by the information schema
- binder.bind(SchemaPlus.class)
+ binder.bind(DruidSchemaCatalog.class)
.annotatedWith(Names.named(INCOMPLETE_SCHEMA))
.toProvider(RootSchemaProvider.class)
.in(Scopes.SINGLETON);
@@ -65,9 +64,9 @@ public class DruidCalciteSchemaModule implements Module
@Provides
@Singleton
- private SchemaPlus getRootSchema(@Named(INCOMPLETE_SCHEMA) SchemaPlus
rootSchema, InformationSchema informationSchema)
+ private DruidSchemaCatalog getRootSchema(@Named(INCOMPLETE_SCHEMA)
DruidSchemaCatalog rootSchema, InformationSchema informationSchema)
{
- rootSchema.add(INFORMATION_SCHEMA_NAME, informationSchema);
+ rootSchema.getRootSchema().add(INFORMATION_SCHEMA_NAME, informationSchema);
return rootSchema;
}
}
diff --git
a/sql/src/main/java/org/apache/druid/sql/calcite/schema/DruidSchemaCatalog.java
b/sql/src/main/java/org/apache/druid/sql/calcite/schema/DruidSchemaCatalog.java
new file mode 100644
index 0000000..34f15af
--- /dev/null
+++
b/sql/src/main/java/org/apache/druid/sql/calcite/schema/DruidSchemaCatalog.java
@@ -0,0 +1,138 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.druid.sql.calcite.schema;
+
+import org.apache.calcite.schema.SchemaPlus;
+
+import javax.annotation.Nullable;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * The Druid 'catalog', containing information about all Druid schemas which
are available. This packages both the 'root
+ * level' Calcite {@link SchemaPlus} and a map of the {@link NamedSchema}
which were used to populate it, keyed by
+ * {@link NamedSchema#getSchemaName()}.
+ *
+ * The {@link #rootSchema} is a top level Calcite schema, which contains all
{@link NamedSchema#getSchema()} and
+ * {@link InformationSchema} added as sub-schemas, and this class provides
convenience methods to do things like
+ * fetch a specific {@link SchemaPlus} by name or list the set of all schemas
available, and is used during query
+ * planning and execution.
+ *
+ * {@link #namedSchemas} contains all {@link NamedSchema}, which should be
everything except {@link InformationSchema}.
+ * These are used primarily for {@link #getResourceType(String, String)},
which given the name of a table or function
+ * that belongs to some {@link NamedSchema}, lookup the most appropriate value
to use for
+ * {@link org.apache.druid.server.security.Resource#getType()} to use for
authorization.
+ */
+public class DruidSchemaCatalog
+{
+ private final SchemaPlus rootSchema;
+ private final Map<String, NamedSchema> namedSchemas;
+
+ public DruidSchemaCatalog(
+ SchemaPlus rootSchema,
+ Map<String, NamedSchema> schemas
+ )
+ {
+ this.rootSchema = rootSchema;
+ this.namedSchemas = schemas;
+ }
+
+ /**
+ * Root calcite schema, used to plan and execute queries
+ */
+ public SchemaPlus getRootSchema()
+ {
+ return rootSchema;
+ }
+
+ /**
+ * Get all {@link NamedSchema} which belong to the Druid catalog
+ */
+ public Map<String, NamedSchema> getNamedSchemas()
+ {
+ return namedSchemas;
+ }
+
+ /**
+ * Get a {@link NamedSchema} by {@link NamedSchema#getSchemaName()}
+ */
+ public NamedSchema getNamedSchema(String schemaName)
+ {
+ return namedSchemas.get(schemaName);
+ }
+
+ /**
+ * Get a specific {@link SchemaPlus} by {@link NamedSchema#getSchemaName()}
+ */
+ public SchemaPlus getSubSchema(String name)
+ {
+ return rootSchema.getSubSchema(name);
+ }
+
+ /**
+ * Get all sub-schemas defined on {@link #rootSchema}
+ */
+ public Set<String> getSubSchemaNames()
+ {
+ return rootSchema.getSubSchemaNames();
+ }
+
+ /**
+ * Given the name of a {@link NamedSchema} and the name of a table or
function that belongs to that schema, return
+ * the appropriate value to use for {@link
org.apache.druid.server.security.Resource#getType()} during authorization
+ */
+ @Nullable
+ public String getResourceType(String schema, String resourceName)
+ {
+ if (namedSchemas.containsKey(schema)) {
+ return namedSchemas.get(schema).getSchemaResourceType(resourceName);
+ }
+ return null;
+ }
+
+
+ @Override
+ public boolean equals(Object o)
+ {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ DruidSchemaCatalog that = (DruidSchemaCatalog) o;
+ return rootSchema.equals(that.rootSchema) &&
namedSchemas.equals(that.namedSchemas);
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return Objects.hash(rootSchema, namedSchemas);
+ }
+
+ @Override
+ public String toString()
+ {
+ return "DruidSchemaCatalog{" +
+ "schemas=" + getSubSchemaNames() +
+ '}';
+ }
+}
diff --git
a/sql/src/main/java/org/apache/druid/sql/calcite/schema/InformationSchema.java
b/sql/src/main/java/org/apache/druid/sql/calcite/schema/InformationSchema.java
index 9aa411b..96fe42c 100644
---
a/sql/src/main/java/org/apache/druid/sql/calcite/schema/InformationSchema.java
+++
b/sql/src/main/java/org/apache/druid/sql/calcite/schema/InformationSchema.java
@@ -23,7 +23,6 @@ import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicates;
import com.google.common.collect.FluentIterable;
-import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
@@ -49,9 +48,11 @@ import org.apache.calcite.sql.type.SqlTypeName;
import org.apache.druid.java.util.emitter.EmittingLogger;
import org.apache.druid.segment.column.RowSignature;
import org.apache.druid.segment.column.ValueType;
+import org.apache.druid.server.security.Action;
import org.apache.druid.server.security.AuthenticationResult;
import org.apache.druid.server.security.AuthorizationUtils;
import org.apache.druid.server.security.AuthorizerMapper;
+import org.apache.druid.server.security.Resource;
import org.apache.druid.server.security.ResourceAction;
import org.apache.druid.sql.calcite.planner.PlannerContext;
import org.apache.druid.sql.calcite.table.DruidTable;
@@ -111,26 +112,18 @@ public class InformationSchema extends AbstractSchema
.add("JDBC_TYPE", ValueType.LONG)
.build();
private static final RelDataTypeSystem TYPE_SYSTEM =
RelDataTypeSystem.DEFAULT;
- private static final Function<String, Iterable<ResourceAction>>
DRUID_TABLE_RA_GENERATOR = datasourceName -> {
- return
Collections.singletonList(AuthorizationUtils.DATASOURCE_READ_RA_GENERATOR.apply(datasourceName));
- };
- private static final Function<String, Iterable<ResourceAction>>
VIEW_TABLE_RA_GENERATOR = viewName -> {
- return
Collections.singletonList(AuthorizationUtils.VIEW_READ_RA_GENERATOR.apply(viewName));
- };
private static final String INFO_TRUE = "YES";
private static final String INFO_FALSE = "NO";
- private final SchemaPlus rootSchema;
+ private final DruidSchemaCatalog rootSchema;
private final Map<String, Table> tableMap;
private final AuthorizerMapper authorizerMapper;
- private final String druidSchemaName;
@Inject
public InformationSchema(
- @Named(DruidCalciteSchemaModule.INCOMPLETE_SCHEMA) final SchemaPlus
rootSchema,
- final AuthorizerMapper authorizerMapper,
- @DruidSchemaName String druidSchemaName
+ @Named(DruidCalciteSchemaModule.INCOMPLETE_SCHEMA) final
DruidSchemaCatalog rootSchema,
+ final AuthorizerMapper authorizerMapper
)
{
this.rootSchema = Preconditions.checkNotNull(rootSchema, "rootSchema");
@@ -140,7 +133,6 @@ public class InformationSchema extends AbstractSchema
COLUMNS_TABLE, new ColumnsTable()
);
this.authorizerMapper = authorizerMapper;
- this.druidSchemaName = druidSchemaName;
}
@Override
@@ -364,7 +356,7 @@ public class InformationSchema extends AbstractSchema
return generateColumnMetadata(
schemaName,
functionName,
-
viewMacro.apply(ImmutableList.of()),
+
viewMacro.apply(Collections.emptyList()),
typeFactory
);
}
@@ -483,20 +475,11 @@ public class InformationSchema extends AbstractSchema
final AuthenticationResult authenticationResult
)
{
- if (druidSchemaName.equals(subSchema.getName())) {
- // The "druid" schema's tables represent Druid datasources which require
authorization
- return ImmutableSet.copyOf(
- AuthorizationUtils.filterAuthorizedResources(
- authenticationResult,
- subSchema.getTableNames(),
- DRUID_TABLE_RA_GENERATOR,
- authorizerMapper
- )
- );
- } else {
- // for non "druid" schema, we don't filter anything
- return subSchema.getTableNames();
- }
+ return getAuthorizedNamesFromNamedSchema(
+ authenticationResult,
+ rootSchema.getNamedSchema(subSchema.getName()),
+ subSchema.getTableNames()
+ );
}
private Set<String> getAuthorizedFunctionNamesFromSubSchema(
@@ -504,19 +487,40 @@ public class InformationSchema extends AbstractSchema
final AuthenticationResult authenticationResult
)
{
- if (NamedViewSchema.NAME.equals(subSchema.getName())) {
- // The "view" subschema functions represent views on Druid datasources
+ return getAuthorizedNamesFromNamedSchema(
+ authenticationResult,
+ rootSchema.getNamedSchema(subSchema.getName()),
+ subSchema.getFunctionNames()
+ );
+ }
+
+ private Set<String> getAuthorizedNamesFromNamedSchema(
+ final AuthenticationResult authenticationResult,
+ final NamedSchema schema,
+ final Set<String> names
+ )
+ {
+ if (schema != null) {
return ImmutableSet.copyOf(
AuthorizationUtils.filterAuthorizedResources(
authenticationResult,
- subSchema.getFunctionNames(),
- VIEW_TABLE_RA_GENERATOR,
+ names,
+ name -> {
+ final String resoureType = schema.getSchemaResourceType(name);
+ if (resoureType != null) {
+ return Collections.singletonList(
+ new ResourceAction(new Resource(name, resoureType),
Action.READ)
+ );
+ } else {
+ return Collections.emptyList();
+ }
+ },
authorizerMapper
)
);
} else {
- // for non "druid" schema, we don't filter anything
- return subSchema.getFunctionNames();
+ // for schemas with no resource type, or that are not named schemas, we
don't filter anything
+ return names;
}
}
}
diff --git
a/sql/src/main/java/org/apache/druid/sql/calcite/schema/NamedDruidSchema.java
b/sql/src/main/java/org/apache/druid/sql/calcite/schema/NamedDruidSchema.java
index a48ccf2..2e8de70 100644
---
a/sql/src/main/java/org/apache/druid/sql/calcite/schema/NamedDruidSchema.java
+++
b/sql/src/main/java/org/apache/druid/sql/calcite/schema/NamedDruidSchema.java
@@ -21,17 +21,18 @@ package org.apache.druid.sql.calcite.schema;
import com.google.inject.Inject;
import org.apache.calcite.schema.Schema;
+import org.apache.druid.server.security.ResourceType;
/**
* The schema for Druid tables to be accessible via SQL.
*/
-class NamedDruidSchema implements NamedSchema
+public class NamedDruidSchema implements NamedSchema
{
private final DruidSchema druidSchema;
private final String druidSchemaName;
@Inject
- NamedDruidSchema(DruidSchema druidSchema, @DruidSchemaName String
druidSchemaName)
+ public NamedDruidSchema(DruidSchema druidSchema, @DruidSchemaName String
druidSchemaName)
{
this.druidSchema = druidSchema;
this.druidSchemaName = druidSchemaName;
@@ -44,6 +45,12 @@ class NamedDruidSchema implements NamedSchema
}
@Override
+ public String getSchemaResourceType(String resourceName)
+ {
+ return ResourceType.DATASOURCE;
+ }
+
+ @Override
public Schema getSchema()
{
return druidSchema;
diff --git
a/sql/src/main/java/org/apache/druid/sql/calcite/schema/NamedLookupSchema.java
b/sql/src/main/java/org/apache/druid/sql/calcite/schema/NamedLookupSchema.java
index a144866..eb91949 100644
---
a/sql/src/main/java/org/apache/druid/sql/calcite/schema/NamedLookupSchema.java
+++
b/sql/src/main/java/org/apache/druid/sql/calcite/schema/NamedLookupSchema.java
@@ -27,12 +27,12 @@ import org.apache.calcite.schema.Schema;
*/
public class NamedLookupSchema implements NamedSchema
{
- private static final String NAME = "lookup";
+ public static final String NAME = "lookup";
private final LookupSchema lookupSchema;
@Inject
- NamedLookupSchema(LookupSchema lookupSchema)
+ public NamedLookupSchema(LookupSchema lookupSchema)
{
this.lookupSchema = lookupSchema;
}
diff --git
a/sql/src/main/java/org/apache/druid/sql/calcite/schema/NamedSchema.java
b/sql/src/main/java/org/apache/druid/sql/calcite/schema/NamedSchema.java
index c4ba827..da951aa 100644
--- a/sql/src/main/java/org/apache/druid/sql/calcite/schema/NamedSchema.java
+++ b/sql/src/main/java/org/apache/druid/sql/calcite/schema/NamedSchema.java
@@ -21,6 +21,8 @@ package org.apache.druid.sql.calcite.schema;
import org.apache.calcite.schema.Schema;
+import javax.annotation.Nullable;
+
/**
* This interface provides everything that is needed to register a {@link
Schema} as a sub schema to the root schema
* of Druid SQL. The {@link #getSchemaName()} will be used to access the
provided {@link Schema} via SQL.
@@ -33,6 +35,17 @@ public interface NamedSchema
String getSchemaName();
/**
+ * For a given name of a table, function, etc of this schema, return the
value most appropriate to use for
+ * {@link org.apache.druid.server.security.Resource#getType()} for the
resource, used during authorization. If this
+ * method returns null then the resource does not need any authorization.
+ */
+ @Nullable
+ default String getSchemaResourceType(String resourceName)
+ {
+ return null;
+ }
+
+ /**
* @return The Schema that Calcite should use.
*/
Schema getSchema();
diff --git
a/sql/src/main/java/org/apache/druid/sql/calcite/schema/NamedSystemSchema.java
b/sql/src/main/java/org/apache/druid/sql/calcite/schema/NamedSystemSchema.java
index 1bb0223..3d42f47 100644
---
a/sql/src/main/java/org/apache/druid/sql/calcite/schema/NamedSystemSchema.java
+++
b/sql/src/main/java/org/apache/druid/sql/calcite/schema/NamedSystemSchema.java
@@ -25,14 +25,14 @@ import org.apache.calcite.schema.Schema;
/**
* The schema for Druid system tables to be accessible via SQL.
*/
-class NamedSystemSchema implements NamedSchema
+public class NamedSystemSchema implements NamedSchema
{
- private static final String NAME = "sys";
+ public static final String NAME = "sys";
private final SystemSchema systemSchema;
@Inject
- NamedSystemSchema(SystemSchema systemSchema)
+ public NamedSystemSchema(SystemSchema systemSchema)
{
this.systemSchema = systemSchema;
}
diff --git
a/sql/src/main/java/org/apache/druid/sql/calcite/schema/NamedViewSchema.java
b/sql/src/main/java/org/apache/druid/sql/calcite/schema/NamedViewSchema.java
index 06959af..fb6ae9c 100644
--- a/sql/src/main/java/org/apache/druid/sql/calcite/schema/NamedViewSchema.java
+++ b/sql/src/main/java/org/apache/druid/sql/calcite/schema/NamedViewSchema.java
@@ -21,6 +21,7 @@ package org.apache.druid.sql.calcite.schema;
import com.google.inject.Inject;
import org.apache.calcite.schema.Schema;
+import org.apache.druid.server.security.ResourceType;
public class NamedViewSchema implements NamedSchema
{
@@ -28,7 +29,7 @@ public class NamedViewSchema implements NamedSchema
private final ViewSchema viewSchema;
@Inject
- NamedViewSchema(ViewSchema viewSchema)
+ public NamedViewSchema(ViewSchema viewSchema)
{
this.viewSchema = viewSchema;
}
@@ -40,6 +41,12 @@ public class NamedViewSchema implements NamedSchema
}
@Override
+ public String getSchemaResourceType(String resourceName)
+ {
+ return ResourceType.VIEW;
+ }
+
+ @Override
public Schema getSchema()
{
return viewSchema;
diff --git
a/sql/src/main/java/org/apache/druid/sql/calcite/schema/RootSchemaProvider.java
b/sql/src/main/java/org/apache/druid/sql/calcite/schema/RootSchemaProvider.java
index 595e7ae..0c61763 100644
---
a/sql/src/main/java/org/apache/druid/sql/calcite/schema/RootSchemaProvider.java
+++
b/sql/src/main/java/org/apache/druid/sql/calcite/schema/RootSchemaProvider.java
@@ -19,14 +19,15 @@
package org.apache.druid.sql.calcite.schema;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
import com.google.inject.Inject;
import com.google.inject.Provider;
import org.apache.calcite.jdbc.CalciteSchema;
import org.apache.calcite.schema.SchemaPlus;
import org.apache.druid.java.util.common.ISE;
-import java.util.HashSet;
-import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
@@ -37,7 +38,7 @@ import java.util.stream.Collectors;
*
* All the provided schema are added to the rootSchema.
*/
-public class RootSchemaProvider implements Provider<SchemaPlus>
+public class RootSchemaProvider implements Provider<DruidSchemaCatalog>
{
private final Set<NamedSchema> namedSchemas;
@@ -48,18 +49,20 @@ public class RootSchemaProvider implements
Provider<SchemaPlus>
}
@Override
- public SchemaPlus get()
+ public DruidSchemaCatalog get()
{
- SchemaPlus rootSchema = CalciteSchema.createRootSchema(false,
false).plus();
- List<String> schemaNames = namedSchemas.stream()
- .map(NamedSchema::getSchemaName)
- .collect(Collectors.toList());
- Set<String> uniqueSchemaNames = new HashSet<>(schemaNames);
- if (uniqueSchemaNames.size() < schemaNames.size()) {
- throw new ISE("Found multiple schemas registered to the same name. "
- + "The list of registered schemas are %s", schemaNames);
+ final SchemaPlus rootSchema = CalciteSchema.createRootSchema(false,
false).plus();
+ final Map<String, NamedSchema> schemasByName =
Maps.newHashMapWithExpectedSize(namedSchemas.size());
+ for (NamedSchema schema : namedSchemas) {
+ if (schemasByName.containsKey(schema.getSchemaName())) {
+ throw new ISE(
+ "Found multiple schemas registered to the same name. The list of
registered schemas are %s",
+
namedSchemas.stream().map(NamedSchema::getSchemaName).collect(Collectors.toList())
+ );
+ }
+ schemasByName.put(schema.getSchemaName(), schema);
+ rootSchema.add(schema.getSchemaName(), schema.getSchema());
}
- namedSchemas.forEach(schema -> rootSchema.add(schema.getSchemaName(),
schema.getSchema()));
- return rootSchema;
+ return new DruidSchemaCatalog(rootSchema,
ImmutableMap.copyOf(schemasByName));
}
}
diff --git
a/sql/src/test/java/org/apache/druid/sql/avatica/DruidAvaticaHandlerTest.java
b/sql/src/test/java/org/apache/druid/sql/avatica/DruidAvaticaHandlerTest.java
index 3278bb6..3934665 100644
---
a/sql/src/test/java/org/apache/druid/sql/avatica/DruidAvaticaHandlerTest.java
+++
b/sql/src/test/java/org/apache/druid/sql/avatica/DruidAvaticaHandlerTest.java
@@ -30,13 +30,13 @@ import com.google.common.util.concurrent.MoreExecutors;
import com.google.inject.Binder;
import com.google.inject.Injector;
import com.google.inject.Module;
+import com.google.inject.multibindings.Multibinder;
import com.google.inject.name.Names;
import org.apache.calcite.avatica.AvaticaClientRuntimeException;
import org.apache.calcite.avatica.Meta;
import org.apache.calcite.avatica.MissingResultsException;
import org.apache.calcite.avatica.NoSuchStatementException;
import org.apache.calcite.avatica.server.AbstractAvaticaHandler;
-import org.apache.calcite.schema.SchemaPlus;
import org.apache.druid.common.config.NullHandling;
import org.apache.druid.guice.GuiceInjectors;
import org.apache.druid.guice.LazySingleton;
@@ -64,7 +64,9 @@ import org.apache.druid.sql.calcite.planner.Calcites;
import org.apache.druid.sql.calcite.planner.DruidOperatorTable;
import org.apache.druid.sql.calcite.planner.PlannerConfig;
import org.apache.druid.sql.calcite.planner.PlannerFactory;
+import org.apache.druid.sql.calcite.schema.DruidSchemaCatalog;
import org.apache.druid.sql.calcite.schema.DruidSchemaName;
+import org.apache.druid.sql.calcite.schema.NamedSchema;
import org.apache.druid.sql.calcite.util.CalciteTestBase;
import org.apache.druid.sql.calcite.util.CalciteTests;
import org.apache.druid.sql.calcite.util.QueryLogHook;
@@ -168,7 +170,7 @@ public abstract class DruidAvaticaHandlerTest extends
CalciteTestBase
final PlannerConfig plannerConfig = new PlannerConfig();
final DruidOperatorTable operatorTable =
CalciteTests.createOperatorTable();
final ExprMacroTable macroTable = CalciteTests.createExprMacroTable();
- final SchemaPlus rootSchema =
+ final DruidSchemaCatalog rootSchema =
CalciteTests.createMockRootSchema(conglomerate, walker, plannerConfig,
CalciteTests.TEST_AUTHORIZER_MAPPER);
testRequestLogger = new TestRequestLogger();
@@ -187,7 +189,10 @@ public abstract class DruidAvaticaHandlerTest extends
CalciteTestBase
binder.bind(AuthorizerMapper.class).toInstance(CalciteTests.TEST_AUTHORIZER_MAPPER);
binder.bind(Escalator.class).toInstance(CalciteTests.TEST_AUTHENTICATOR_ESCALATOR);
binder.bind(RequestLogger.class).toInstance(testRequestLogger);
- binder.bind(SchemaPlus.class).toInstance(rootSchema);
+ binder.bind(DruidSchemaCatalog.class).toInstance(rootSchema);
+ for (NamedSchema schema :
rootSchema.getNamedSchemas().values()) {
+ Multibinder.newSetBinder(binder,
NamedSchema.class).addBinding().toInstance(schema);
+ }
binder.bind(QueryLifecycleFactory.class)
.toInstance(CalciteTests.createMockQueryLifecycleFactory(walker, conglomerate));
binder.bind(DruidOperatorTable.class).toInstance(operatorTable);
@@ -865,7 +870,7 @@ public abstract class DruidAvaticaHandlerTest extends
CalciteTestBase
final DruidOperatorTable operatorTable =
CalciteTests.createOperatorTable();
final ExprMacroTable macroTable = CalciteTests.createExprMacroTable();
final List<Meta.Frame> frames = new ArrayList<>();
- SchemaPlus rootSchema =
+ DruidSchemaCatalog rootSchema =
CalciteTests.createMockRootSchema(conglomerate, walker, plannerConfig,
AuthTestUtils.TEST_AUTHORIZER_MAPPER);
DruidMeta smallFrameDruidMeta = new DruidMeta(
CalciteTests.createSqlLifecycleFactory(
@@ -954,7 +959,7 @@ public abstract class DruidAvaticaHandlerTest extends
CalciteTestBase
final DruidOperatorTable operatorTable =
CalciteTests.createOperatorTable();
final ExprMacroTable macroTable = CalciteTests.createExprMacroTable();
final List<Meta.Frame> frames = new ArrayList<>();
- SchemaPlus rootSchema =
+ DruidSchemaCatalog rootSchema =
CalciteTests.createMockRootSchema(conglomerate, walker, plannerConfig,
AuthTestUtils.TEST_AUTHORIZER_MAPPER);
DruidMeta smallFrameDruidMeta = new DruidMeta(
CalciteTests.createSqlLifecycleFactory(
diff --git
a/sql/src/test/java/org/apache/druid/sql/avatica/DruidStatementTest.java
b/sql/src/test/java/org/apache/druid/sql/avatica/DruidStatementTest.java
index 4400286..fbfc2f1 100644
--- a/sql/src/test/java/org/apache/druid/sql/avatica/DruidStatementTest.java
+++ b/sql/src/test/java/org/apache/druid/sql/avatica/DruidStatementTest.java
@@ -23,7 +23,6 @@ import com.google.common.base.Function;
import com.google.common.collect.Lists;
import org.apache.calcite.avatica.ColumnMetaData;
import org.apache.calcite.avatica.Meta;
-import org.apache.calcite.schema.SchemaPlus;
import org.apache.druid.common.config.NullHandling;
import org.apache.druid.java.util.common.DateTimes;
import org.apache.druid.java.util.common.io.Closer;
@@ -36,6 +35,7 @@ import org.apache.druid.sql.SqlLifecycleFactory;
import org.apache.druid.sql.calcite.planner.DruidOperatorTable;
import org.apache.druid.sql.calcite.planner.PlannerConfig;
import org.apache.druid.sql.calcite.planner.PlannerFactory;
+import org.apache.druid.sql.calcite.schema.DruidSchemaCatalog;
import org.apache.druid.sql.calcite.util.CalciteTestBase;
import org.apache.druid.sql.calcite.util.CalciteTests;
import org.apache.druid.sql.calcite.util.QueryLogHook;
@@ -87,7 +87,7 @@ public class DruidStatementTest extends CalciteTestBase
final PlannerConfig plannerConfig = new PlannerConfig();
final DruidOperatorTable operatorTable =
CalciteTests.createOperatorTable();
final ExprMacroTable macroTable = CalciteTests.createExprMacroTable();
- SchemaPlus rootSchema =
+ DruidSchemaCatalog rootSchema =
CalciteTests.createMockRootSchema(conglomerate, walker, plannerConfig,
AuthTestUtils.TEST_AUTHORIZER_MAPPER);
final PlannerFactory plannerFactory = new PlannerFactory(
rootSchema,
diff --git
a/sql/src/test/java/org/apache/druid/sql/calcite/BaseCalciteQueryTest.java
b/sql/src/test/java/org/apache/druid/sql/calcite/BaseCalciteQueryTest.java
index 876ea5c..45f0eb1 100644
--- a/sql/src/test/java/org/apache/druid/sql/calcite/BaseCalciteQueryTest.java
+++ b/sql/src/test/java/org/apache/druid/sql/calcite/BaseCalciteQueryTest.java
@@ -23,7 +23,6 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import org.apache.calcite.plan.RelOptPlanner;
-import org.apache.calcite.schema.SchemaPlus;
import org.apache.druid.annotations.UsedByJUnitParamsRunner;
import org.apache.druid.common.config.NullHandling;
import org.apache.druid.hll.VersionOneHyperLogLogCollector;
@@ -80,6 +79,7 @@ import
org.apache.druid.sql.calcite.planner.DruidOperatorTable;
import org.apache.druid.sql.calcite.planner.PlannerConfig;
import org.apache.druid.sql.calcite.planner.PlannerContext;
import org.apache.druid.sql.calcite.planner.PlannerFactory;
+import org.apache.druid.sql.calcite.schema.DruidSchemaCatalog;
import org.apache.druid.sql.calcite.util.CalciteTestBase;
import org.apache.druid.sql.calcite.util.CalciteTests;
import org.apache.druid.sql.calcite.util.QueryLogHook;
@@ -896,7 +896,7 @@ public class BaseCalciteQueryTest extends CalciteTestBase
{
final InProcessViewManager viewManager =
new InProcessViewManager(CalciteTests.TEST_AUTHENTICATOR_ESCALATOR,
CalciteTests.DRUID_VIEW_MACRO_FACTORY);
- SchemaPlus rootSchema = CalciteTests.createMockRootSchema(
+ DruidSchemaCatalog rootSchema = CalciteTests.createMockRootSchema(
conglomerate,
walker,
plannerConfig,
diff --git
a/sql/src/test/java/org/apache/druid/sql/calcite/SqlVectorizedExpressionSanityTest.java
b/sql/src/test/java/org/apache/druid/sql/calcite/SqlVectorizedExpressionSanityTest.java
index de788fa..337ffd2 100644
---
a/sql/src/test/java/org/apache/druid/sql/calcite/SqlVectorizedExpressionSanityTest.java
+++
b/sql/src/test/java/org/apache/druid/sql/calcite/SqlVectorizedExpressionSanityTest.java
@@ -21,7 +21,6 @@ package org.apache.druid.sql.calcite;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
-import org.apache.calcite.schema.SchemaPlus;
import org.apache.calcite.sql.parser.SqlParseException;
import org.apache.calcite.tools.RelConversionException;
import org.apache.calcite.tools.ValidationException;
@@ -45,6 +44,7 @@ import org.apache.druid.sql.calcite.planner.DruidPlanner;
import org.apache.druid.sql.calcite.planner.PlannerConfig;
import org.apache.druid.sql.calcite.planner.PlannerFactory;
import org.apache.druid.sql.calcite.planner.PlannerResult;
+import org.apache.druid.sql.calcite.schema.DruidSchemaCatalog;
import org.apache.druid.sql.calcite.util.CalciteTests;
import org.apache.druid.sql.calcite.util.SpecificSegmentsQuerySegmentWalker;
import org.apache.druid.testing.InitializedNullHandlingTest;
@@ -128,7 +128,7 @@ public class SqlVectorizedExpressionSanityTest extends
InitializedNullHandlingTe
CLOSER.register(WALKER);
final PlannerConfig plannerConfig = new PlannerConfig();
- final SchemaPlus rootSchema =
+ final DruidSchemaCatalog rootSchema =
CalciteTests.createMockRootSchema(CONGLOMERATE, WALKER, plannerConfig,
AuthTestUtils.TEST_AUTHORIZER_MAPPER);
PLANNER_FACTORY = new PlannerFactory(
rootSchema,
diff --git
a/sql/src/test/java/org/apache/druid/sql/calcite/expression/ExpressionTestHelper.java
b/sql/src/test/java/org/apache/druid/sql/calcite/expression/ExpressionTestHelper.java
index dc56fe7..3c049b4 100644
---
a/sql/src/test/java/org/apache/druid/sql/calcite/expression/ExpressionTestHelper.java
+++
b/sql/src/test/java/org/apache/druid/sql/calcite/expression/ExpressionTestHelper.java
@@ -26,6 +26,7 @@ import org.apache.calcite.rel.type.RelDataTypeFactory;
import org.apache.calcite.rex.RexBuilder;
import org.apache.calcite.rex.RexLiteral;
import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.schema.SchemaPlus;
import org.apache.calcite.sql.SqlIntervalQualifier;
import org.apache.calcite.sql.SqlOperator;
import org.apache.calcite.sql.type.SqlTypeName;
@@ -45,8 +46,14 @@ import org.apache.druid.sql.calcite.planner.Calcites;
import org.apache.druid.sql.calcite.planner.PlannerConfig;
import org.apache.druid.sql.calcite.planner.PlannerContext;
import org.apache.druid.sql.calcite.rel.VirtualColumnRegistry;
+import org.apache.druid.sql.calcite.schema.DruidSchema;
+import org.apache.druid.sql.calcite.schema.DruidSchemaCatalog;
+import org.apache.druid.sql.calcite.schema.NamedDruidSchema;
+import org.apache.druid.sql.calcite.schema.NamedViewSchema;
+import org.apache.druid.sql.calcite.schema.ViewSchema;
import org.apache.druid.sql.calcite.table.RowSignatures;
import org.apache.druid.sql.calcite.util.CalciteTests;
+import org.easymock.EasyMock;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.junit.Assert;
@@ -67,6 +74,13 @@ class ExpressionTestHelper
CalciteTests.createOperatorTable(),
CalciteTests.createExprMacroTable(),
new PlannerConfig(),
+ new DruidSchemaCatalog(
+ EasyMock.createMock(SchemaPlus.class),
+ ImmutableMap.of(
+ "druid", new
NamedDruidSchema(EasyMock.createMock(DruidSchema.class), "druid"),
+ NamedViewSchema.NAME, new
NamedViewSchema(EasyMock.createMock(ViewSchema.class))
+ )
+ ),
ImmutableMap.of()
);
diff --git
a/sql/src/test/java/org/apache/druid/sql/calcite/planner/CalcitePlannerModuleTest.java
b/sql/src/test/java/org/apache/druid/sql/calcite/planner/CalcitePlannerModuleTest.java
index e081e1f..90dfcba 100644
---
a/sql/src/test/java/org/apache/druid/sql/calcite/planner/CalcitePlannerModuleTest.java
+++
b/sql/src/test/java/org/apache/druid/sql/calcite/planner/CalcitePlannerModuleTest.java
@@ -26,14 +26,15 @@ import com.google.inject.Key;
import com.google.inject.Scopes;
import com.google.inject.TypeLiteral;
import org.apache.calcite.schema.Schema;
-import org.apache.calcite.schema.SchemaPlus;
import org.apache.druid.guice.LazySingleton;
import org.apache.druid.jackson.JacksonModule;
import org.apache.druid.math.expr.ExprMacroTable;
import org.apache.druid.server.QueryLifecycleFactory;
import org.apache.druid.server.security.AuthorizerMapper;
+import org.apache.druid.server.security.ResourceType;
import org.apache.druid.sql.calcite.aggregation.SqlAggregator;
import org.apache.druid.sql.calcite.expression.SqlOperatorConversion;
+import org.apache.druid.sql.calcite.schema.DruidSchemaCatalog;
import org.apache.druid.sql.calcite.schema.DruidSchemaName;
import org.apache.druid.sql.calcite.schema.NamedSchema;
import org.apache.druid.sql.calcite.util.CalciteTestBase;
@@ -71,11 +72,10 @@ public class CalcitePlannerModuleTest extends
CalciteTestBase
@Mock
private AuthorizerMapper authorizerMapper;
@Mock
- private SchemaPlus rootSchema;
+ private DruidSchemaCatalog rootSchema;
private Set<SqlAggregator> aggregators;
private Set<SqlOperatorConversion> operatorConversions;
- private Set<NamedSchema> calciteSchemas;
private CalcitePlannerModule target;
private Injector injector;
@@ -87,8 +87,9 @@ public class CalcitePlannerModuleTest extends CalciteTestBase
EasyMock.expect(druidSchema2.getSchema()).andStubReturn(schema2);
EasyMock.expect(druidSchema1.getSchemaName()).andStubReturn(SCHEMA_1);
EasyMock.expect(druidSchema2.getSchemaName()).andStubReturn(SCHEMA_2);
+
EasyMock.expect(druidSchema1.getSchemaResourceType(EasyMock.anyString())).andStubReturn(ResourceType.DATASOURCE);
+
EasyMock.expect(druidSchema2.getSchemaResourceType(EasyMock.anyString())).andStubReturn("test");
EasyMock.replay(druidSchema1, druidSchema2);
- calciteSchemas = ImmutableSet.of(druidSchema1, druidSchema2);
aggregators = ImmutableSet.of();
operatorConversions = ImmutableSet.of();
target = new CalcitePlannerModule();
@@ -97,14 +98,13 @@ public class CalcitePlannerModuleTest extends
CalciteTestBase
binder -> {
binder.bind(Validator.class).toInstance(Validation.buildDefaultValidatorFactory().getValidator());
binder.bindScope(LazySingleton.class, Scopes.SINGLETON);
- binder.bind(Key.get(new
TypeLiteral<Set<NamedSchema>>(){})).toInstance(calciteSchemas);
binder.bind(QueryLifecycleFactory.class).toInstance(queryLifecycleFactory);
binder.bind(ExprMacroTable.class).toInstance(macroTable);
binder.bind(AuthorizerMapper.class).toInstance(authorizerMapper);
binder.bind(String.class).annotatedWith(DruidSchemaName.class).toInstance(DRUID_SCHEMA_NAME);
binder.bind(Key.get(new
TypeLiteral<Set<SqlAggregator>>(){})).toInstance(aggregators);
binder.bind(Key.get(new
TypeLiteral<Set<SqlOperatorConversion>>(){})).toInstance(operatorConversions);
- binder.bind(SchemaPlus.class).toInstance(rootSchema);
+ binder.bind(DruidSchemaCatalog.class).toInstance(rootSchema);
},
target
);
diff --git
a/sql/src/test/java/org/apache/druid/sql/calcite/schema/DruidCalciteSchemaModuleTest.java
b/sql/src/test/java/org/apache/druid/sql/calcite/schema/DruidCalciteSchemaModuleTest.java
index f225fe6..451e16f 100644
---
a/sql/src/test/java/org/apache/druid/sql/calcite/schema/DruidCalciteSchemaModuleTest.java
+++
b/sql/src/test/java/org/apache/druid/sql/calcite/schema/DruidCalciteSchemaModuleTest.java
@@ -28,7 +28,6 @@ import com.google.inject.Key;
import com.google.inject.Scopes;
import com.google.inject.TypeLiteral;
import com.google.inject.name.Names;
-import org.apache.calcite.schema.SchemaPlus;
import org.apache.druid.client.InventoryView;
import org.apache.druid.client.TimelineServerView;
import org.apache.druid.client.coordinator.Coordinator;
@@ -203,12 +202,12 @@ public class DruidCalciteSchemaModuleTest extends
CalciteTestBase
@Test
public void testRootSchemaAnnotatedIsInjectedAsSingleton()
{
- SchemaPlus rootSchema = injector.getInstance(
- Key.get(SchemaPlus.class,
Names.named(DruidCalciteSchemaModule.INCOMPLETE_SCHEMA))
+ DruidSchemaCatalog rootSchema = injector.getInstance(
+ Key.get(DruidSchemaCatalog.class,
Names.named(DruidCalciteSchemaModule.INCOMPLETE_SCHEMA))
);
Assert.assertNotNull(rootSchema);
- SchemaPlus other = injector.getInstance(
- Key.get(SchemaPlus.class,
Names.named(DruidCalciteSchemaModule.INCOMPLETE_SCHEMA))
+ DruidSchemaCatalog other = injector.getInstance(
+ Key.get(DruidSchemaCatalog.class,
Names.named(DruidCalciteSchemaModule.INCOMPLETE_SCHEMA))
);
Assert.assertSame(other, rootSchema);
}
@@ -216,10 +215,10 @@ public class DruidCalciteSchemaModuleTest extends
CalciteTestBase
@Test
public void testRootSchemaIsInjectedAsSingleton()
{
- SchemaPlus rootSchema = injector.getInstance(Key.get(SchemaPlus.class));
+ DruidSchemaCatalog rootSchema =
injector.getInstance(Key.get(DruidSchemaCatalog.class));
Assert.assertNotNull(rootSchema);
- SchemaPlus other = injector.getInstance(
- Key.get(SchemaPlus.class,
Names.named(DruidCalciteSchemaModule.INCOMPLETE_SCHEMA))
+ DruidSchemaCatalog other = injector.getInstance(
+ Key.get(DruidSchemaCatalog.class,
Names.named(DruidCalciteSchemaModule.INCOMPLETE_SCHEMA))
);
Assert.assertSame(other, rootSchema);
}
@@ -227,7 +226,7 @@ public class DruidCalciteSchemaModuleTest extends
CalciteTestBase
@Test
public void testRootSchemaIsInjectedAndHasInformationSchema()
{
- SchemaPlus rootSchema = injector.getInstance(Key.get(SchemaPlus.class));
+ DruidSchemaCatalog rootSchema =
injector.getInstance(Key.get(DruidSchemaCatalog.class));
InformationSchema expectedSchema =
injector.getInstance(InformationSchema.class);
Assert.assertNotNull(rootSchema);
Assert.assertSame(expectedSchema,
rootSchema.getSubSchema("INFORMATION_SCHEMA").unwrap(InformationSchema.class));
diff --git
a/sql/src/test/java/org/apache/druid/sql/calcite/schema/RootSchemaProviderTest.java
b/sql/src/test/java/org/apache/druid/sql/calcite/schema/RootSchemaProviderTest.java
index 71f1169..6cfe3f2 100644
---
a/sql/src/test/java/org/apache/druid/sql/calcite/schema/RootSchemaProviderTest.java
+++
b/sql/src/test/java/org/apache/druid/sql/calcite/schema/RootSchemaProviderTest.java
@@ -21,7 +21,6 @@ package org.apache.druid.sql.calcite.schema;
import com.google.common.collect.ImmutableSet;
import org.apache.calcite.schema.Schema;
-import org.apache.calcite.schema.SchemaPlus;
import org.apache.druid.java.util.common.ISE;
import org.apache.druid.sql.calcite.util.CalciteTestBase;
import org.easymock.EasyMock;
@@ -72,9 +71,9 @@ public class RootSchemaProviderTest extends CalciteTestBase
@Test
public void testGetShouldReturnRootSchemaWithProvidedSchemasRegistered()
{
- SchemaPlus rootSchema = target.get();
- Assert.assertEquals("", rootSchema.getName());
- Assert.assertFalse(rootSchema.isCacheEnabled());
+ DruidSchemaCatalog rootSchema = target.get();
+ Assert.assertEquals("", rootSchema.getRootSchema().getName());
+ Assert.assertFalse(rootSchema.getRootSchema().isCacheEnabled());
// metadata schema should not be added
Assert.assertEquals(druidSchemas.size(),
rootSchema.getSubSchemaNames().size());
diff --git
a/sql/src/test/java/org/apache/druid/sql/calcite/util/CalciteTests.java
b/sql/src/test/java/org/apache/druid/sql/calcite/util/CalciteTests.java
index 4e39482..a5e493d 100644
--- a/sql/src/test/java/org/apache/druid/sql/calcite/util/CalciteTests.java
+++ b/sql/src/test/java/org/apache/druid/sql/calcite/util/CalciteTests.java
@@ -115,9 +115,15 @@ import
org.apache.druid.sql.calcite.planner.DruidOperatorTable;
import org.apache.druid.sql.calcite.planner.PlannerConfig;
import org.apache.druid.sql.calcite.planner.PlannerFactory;
import org.apache.druid.sql.calcite.schema.DruidSchema;
+import org.apache.druid.sql.calcite.schema.DruidSchemaCatalog;
import org.apache.druid.sql.calcite.schema.InformationSchema;
import org.apache.druid.sql.calcite.schema.LookupSchema;
import org.apache.druid.sql.calcite.schema.MetadataSegmentView;
+import org.apache.druid.sql.calcite.schema.NamedDruidSchema;
+import org.apache.druid.sql.calcite.schema.NamedLookupSchema;
+import org.apache.druid.sql.calcite.schema.NamedSchema;
+import org.apache.druid.sql.calcite.schema.NamedSystemSchema;
+import org.apache.druid.sql.calcite.schema.NamedViewSchema;
import org.apache.druid.sql.calcite.schema.SystemSchema;
import org.apache.druid.sql.calcite.schema.ViewSchema;
import org.apache.druid.sql.calcite.view.DruidViewMacroFactory;
@@ -131,7 +137,6 @@ import org.joda.time.Duration;
import org.joda.time.chrono.ISOChronology;
import javax.annotation.Nullable;
-
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
@@ -165,9 +170,6 @@ public class CalciteTests
public static final String USERVISITDATASOURCE = "visits";
public static final String DRUID_SCHEMA_NAME = "druid";
public static final String INFORMATION_SCHEMA_NAME = "INFORMATION_SCHEMA";
- public static final String SYSTEM_SCHEMA_NAME = "sys";
- public static final String LOOKUP_SCHEMA_NAME = "lookup";
- public static final String VIEW_SCHEMA_NAME = "view";
public static final String TEST_SUPERUSER_NAME = "testSuperuser";
public static final AuthorizerMapper TEST_AUTHORIZER_MAPPER = new
AuthorizerMapper(null)
@@ -180,9 +182,9 @@ public class CalciteTests
return Access.OK;
}
- if (resource.getType() == ResourceType.DATASOURCE &&
resource.getName().equals(FORBIDDEN_DATASOURCE)) {
+ if (ResourceType.DATASOURCE.equals(resource.getType()) &&
resource.getName().equals(FORBIDDEN_DATASOURCE)) {
return new Access(false);
- } else if (resource.getType() == ResourceType.VIEW &&
resource.getName().equals("forbiddenView")) {
+ } else if (ResourceType.VIEW.equals(resource.getType()) &&
resource.getName().equals("forbiddenView")) {
return new Access(false);
} else {
return Access.OK;
@@ -1123,7 +1125,7 @@ public class CalciteTests
);
}
- public static SchemaPlus createMockRootSchema(
+ public static DruidSchemaCatalog createMockRootSchema(
final QueryRunnerFactoryConglomerate conglomerate,
final SpecificSegmentsQuerySegmentWalker walker,
final PlannerConfig plannerConfig,
@@ -1134,22 +1136,31 @@ public class CalciteTests
SystemSchema systemSchema =
CalciteTests.createMockSystemSchema(druidSchema, walker,
plannerConfig, authorizerMapper);
+ LookupSchema lookupSchema = CalciteTests.createMockLookupSchema();
SchemaPlus rootSchema = CalciteSchema.createRootSchema(false,
false).plus();
+ Set<NamedSchema> namedSchemas = ImmutableSet.of(
+ new NamedDruidSchema(druidSchema, CalciteTests.DRUID_SCHEMA_NAME),
+ new NamedSystemSchema(systemSchema),
+ new NamedLookupSchema(lookupSchema)
+ );
+ DruidSchemaCatalog catalog = new DruidSchemaCatalog(
+ rootSchema,
+
namedSchemas.stream().collect(Collectors.toMap(NamedSchema::getSchemaName, x ->
x))
+ );
InformationSchema informationSchema =
new InformationSchema(
- rootSchema,
- authorizerMapper,
- CalciteTests.DRUID_SCHEMA_NAME
+ catalog,
+ authorizerMapper
);
- LookupSchema lookupSchema = CalciteTests.createMockLookupSchema();
rootSchema.add(CalciteTests.DRUID_SCHEMA_NAME, druidSchema);
rootSchema.add(CalciteTests.INFORMATION_SCHEMA_NAME, informationSchema);
- rootSchema.add(CalciteTests.SYSTEM_SCHEMA_NAME, systemSchema);
- rootSchema.add(CalciteTests.LOOKUP_SCHEMA_NAME, lookupSchema);
- return rootSchema;
+ rootSchema.add(NamedSystemSchema.NAME, systemSchema);
+ rootSchema.add(NamedLookupSchema.NAME, lookupSchema);
+
+ return catalog;
}
- public static SchemaPlus createMockRootSchema(
+ public static DruidSchemaCatalog createMockRootSchema(
final QueryRunnerFactoryConglomerate conglomerate,
final SpecificSegmentsQuerySegmentWalker walker,
final PlannerConfig plannerConfig,
@@ -1160,20 +1171,32 @@ public class CalciteTests
DruidSchema druidSchema = createMockSchema(conglomerate, walker,
plannerConfig, viewManager);
SystemSchema systemSchema =
CalciteTests.createMockSystemSchema(druidSchema, walker,
plannerConfig, authorizerMapper);
+
+ LookupSchema lookupSchema = CalciteTests.createMockLookupSchema();
+ ViewSchema viewSchema = new ViewSchema(viewManager);
+
SchemaPlus rootSchema = CalciteSchema.createRootSchema(false,
false).plus();
+ Set<NamedSchema> namedSchemas = ImmutableSet.of(
+ new NamedDruidSchema(druidSchema, CalciteTests.DRUID_SCHEMA_NAME),
+ new NamedSystemSchema(systemSchema),
+ new NamedLookupSchema(lookupSchema),
+ new NamedViewSchema(viewSchema)
+ );
+ DruidSchemaCatalog catalog = new DruidSchemaCatalog(
+ rootSchema,
+
namedSchemas.stream().collect(Collectors.toMap(NamedSchema::getSchemaName, x ->
x))
+ );
InformationSchema informationSchema =
new InformationSchema(
- rootSchema,
- authorizerMapper,
- CalciteTests.DRUID_SCHEMA_NAME
+ catalog,
+ authorizerMapper
);
- LookupSchema lookupSchema = CalciteTests.createMockLookupSchema();
rootSchema.add(CalciteTests.DRUID_SCHEMA_NAME, druidSchema);
rootSchema.add(CalciteTests.INFORMATION_SCHEMA_NAME, informationSchema);
- rootSchema.add(CalciteTests.SYSTEM_SCHEMA_NAME, systemSchema);
- rootSchema.add(CalciteTests.LOOKUP_SCHEMA_NAME, lookupSchema);
- rootSchema.add(CalciteTests.VIEW_SCHEMA_NAME, new ViewSchema(viewManager));
- return rootSchema;
+ rootSchema.add(NamedSystemSchema.NAME, systemSchema);
+ rootSchema.add(NamedLookupSchema.NAME, lookupSchema);
+ rootSchema.add(NamedViewSchema.NAME, viewSchema);
+ return catalog;
}
/**
diff --git a/sql/src/test/java/org/apache/druid/sql/http/SqlResourceTest.java
b/sql/src/test/java/org/apache/druid/sql/http/SqlResourceTest.java
index 870342a..c7387ac 100644
--- a/sql/src/test/java/org/apache/druid/sql/http/SqlResourceTest.java
+++ b/sql/src/test/java/org/apache/druid/sql/http/SqlResourceTest.java
@@ -28,7 +28,6 @@ import com.google.common.collect.Maps;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import org.apache.calcite.avatica.SqlType;
-import org.apache.calcite.schema.SchemaPlus;
import org.apache.calcite.tools.RelConversionException;
import org.apache.druid.common.config.NullHandling;
import org.apache.druid.common.guava.SettableSupplier;
@@ -71,6 +70,7 @@ import
org.apache.druid.sql.calcite.planner.DruidOperatorTable;
import org.apache.druid.sql.calcite.planner.PlannerConfig;
import org.apache.druid.sql.calcite.planner.PlannerContext;
import org.apache.druid.sql.calcite.planner.PlannerFactory;
+import org.apache.druid.sql.calcite.schema.DruidSchemaCatalog;
import org.apache.druid.sql.calcite.util.CalciteTestBase;
import org.apache.druid.sql.calcite.util.CalciteTests;
import org.apache.druid.sql.calcite.util.QueryLogHook;
@@ -184,7 +184,7 @@ public class SqlResourceTest extends CalciteTestBase
return false;
}
};
- final SchemaPlus rootSchema = CalciteTests.createMockRootSchema(
+ final DruidSchemaCatalog rootSchema = CalciteTests.createMockRootSchema(
conglomerate,
walker,
plannerConfig,
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]