diff --git a/presto-analyzer/pom.xml b/presto-analyzer/pom.xml
index b78afbf40e555..c3f07d1c2bb1f 100644
--- a/presto-analyzer/pom.xml
+++ b/presto-analyzer/pom.xml
@@ -47,11 +47,6 @@
true
-
- com.google.inject
- guice
-
-
javax.inject
javax.inject
diff --git a/presto-analyzer/src/main/java/com/facebook/presto/sql/analyzer/BuiltInQueryAnalysis.java b/presto-analyzer/src/main/java/com/facebook/presto/sql/analyzer/BuiltInQueryAnalysis.java
new file mode 100644
index 0000000000000..62984ecd0303e
--- /dev/null
+++ b/presto-analyzer/src/main/java/com/facebook/presto/sql/analyzer/BuiltInQueryAnalysis.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed 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 com.facebook.presto.sql.analyzer;
+
+import com.facebook.presto.spi.analyzer.QueryAnalysis;
+import com.facebook.presto.spi.function.FunctionKind;
+
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+
+public class BuiltInQueryAnalysis
+ implements QueryAnalysis
+{
+ private final Analysis analysis;
+
+ public BuiltInQueryAnalysis(Analysis analysis)
+ {
+ this.analysis = analysis;
+ }
+
+ public Analysis getAnalysis()
+ {
+ return analysis;
+ }
+
+ @Override
+ public String getUpdateType()
+ {
+ return analysis.getUpdateType();
+ }
+
+ @Override
+ public Optional getExpandedQuery()
+ {
+ return analysis.getExpandedQuery();
+ }
+
+ @Override
+ public Map> getInvokedFunctions()
+ {
+ return analysis.getInvokedFunctions();
+ }
+}
diff --git a/presto-main/src/main/java/com/facebook/presto/dispatcher/DispatchManager.java b/presto-main/src/main/java/com/facebook/presto/dispatcher/DispatchManager.java
index 7c6115b137ca3..160247037382c 100644
--- a/presto-main/src/main/java/com/facebook/presto/dispatcher/DispatchManager.java
+++ b/presto-main/src/main/java/com/facebook/presto/dispatcher/DispatchManager.java
@@ -308,6 +308,7 @@ private void createQueryInternal(QueryId queryId, String slug, int retryCoun
DispatchQuery dispatchQuery = dispatchQueryFactory.createDispatchQuery(
session,
+ analyzerProvider,
query,
preparedQuery,
slug,
diff --git a/presto-main/src/main/java/com/facebook/presto/dispatcher/DispatchQueryFactory.java b/presto-main/src/main/java/com/facebook/presto/dispatcher/DispatchQueryFactory.java
index b4f9c4dd17d31..0e19219b6728d 100644
--- a/presto-main/src/main/java/com/facebook/presto/dispatcher/DispatchQueryFactory.java
+++ b/presto-main/src/main/java/com/facebook/presto/dispatcher/DispatchQueryFactory.java
@@ -17,6 +17,7 @@
import com.facebook.presto.common.analyzer.PreparedQuery;
import com.facebook.presto.common.resourceGroups.QueryType;
import com.facebook.presto.spi.WarningCollector;
+import com.facebook.presto.spi.analyzer.AnalyzerProvider;
import com.facebook.presto.spi.resourceGroups.ResourceGroupId;
import java.util.Optional;
@@ -31,6 +32,7 @@ public interface DispatchQueryFactory
* This interface API is defined to setting up all preparation works for query before it being executed.
*
* @param session the session
+ * @param analyzerProvider the analyzer provider
* @param query the query
* @param preparedQuery the prepared query
* @param slug the unique query slug for each {@code Query} object
@@ -43,6 +45,7 @@ public interface DispatchQueryFactory
*/
DispatchQuery createDispatchQuery(
Session session,
+ AnalyzerProvider analyzerProvider,
String query,
PreparedQuery preparedQuery,
String slug,
diff --git a/presto-main/src/main/java/com/facebook/presto/dispatcher/LocalDispatchQueryFactory.java b/presto-main/src/main/java/com/facebook/presto/dispatcher/LocalDispatchQueryFactory.java
index 853137d11de44..57f8aa4438c7d 100644
--- a/presto-main/src/main/java/com/facebook/presto/dispatcher/LocalDispatchQueryFactory.java
+++ b/presto-main/src/main/java/com/facebook/presto/dispatcher/LocalDispatchQueryFactory.java
@@ -27,9 +27,9 @@
import com.facebook.presto.metadata.Metadata;
import com.facebook.presto.spi.PrestoException;
import com.facebook.presto.spi.WarningCollector;
+import com.facebook.presto.spi.analyzer.AnalyzerProvider;
import com.facebook.presto.spi.resourceGroups.ResourceGroupId;
import com.facebook.presto.spi.security.AccessControl;
-import com.facebook.presto.sql.analyzer.BuiltInQueryPreparer;
import com.facebook.presto.tracing.NoopTracerProvider;
import com.facebook.presto.tracing.QueryStateTracingListener;
import com.facebook.presto.transaction.TransactionManager;
@@ -43,7 +43,6 @@
import java.util.function.Consumer;
import static com.facebook.presto.spi.StandardErrorCode.NOT_SUPPORTED;
-import static com.google.common.base.Preconditions.checkState;
import static java.util.Objects.requireNonNull;
/**
@@ -118,6 +117,7 @@ public LocalDispatchQueryFactory(
* to the {@link ResourceGroupManager}. This is no-op for no disaggregated coordinator setup
*
* @param session the session
+ * @param analyzerProvider the analyzer provider
* @param query the query
* @param preparedQuery the prepared query
* @param slug the unique query slug for each {@code Query} object
@@ -131,6 +131,7 @@ public LocalDispatchQueryFactory(
@Override
public DispatchQuery createDispatchQuery(
Session session,
+ AnalyzerProvider analyzerProvider,
String query,
PreparedQuery preparedQuery,
String slug,
@@ -163,9 +164,7 @@ public DispatchQuery createDispatchQuery(
throw new PrestoException(NOT_SUPPORTED, "Unsupported statement type: " + preparedQuery.getStatementClass().getSimpleName());
}
- //TODO: PreparedQuery should be passed all the way to analyzer
- checkState(preparedQuery instanceof BuiltInQueryPreparer.BuiltInPreparedQuery, "Unsupported prepared query type: %s", preparedQuery.getClass().getSimpleName());
- return queryExecutionFactory.createQueryExecution((BuiltInQueryPreparer.BuiltInPreparedQuery) preparedQuery, stateMachine, slug, retryCount, warningCollector, queryType);
+ return queryExecutionFactory.createQueryExecution(analyzerProvider, preparedQuery, stateMachine, slug, retryCount, warningCollector, queryType);
});
return new LocalDispatchQuery(
diff --git a/presto-main/src/main/java/com/facebook/presto/execution/DDLDefinitionExecution.java b/presto-main/src/main/java/com/facebook/presto/execution/DDLDefinitionExecution.java
index 910de3cadd378..f621dfd8d4246 100644
--- a/presto-main/src/main/java/com/facebook/presto/execution/DDLDefinitionExecution.java
+++ b/presto-main/src/main/java/com/facebook/presto/execution/DDLDefinitionExecution.java
@@ -13,10 +13,12 @@
*/
package com.facebook.presto.execution;
+import com.facebook.presto.common.analyzer.PreparedQuery;
import com.facebook.presto.common.resourceGroups.QueryType;
import com.facebook.presto.metadata.Metadata;
import com.facebook.presto.metadata.MetadataManager;
import com.facebook.presto.spi.WarningCollector;
+import com.facebook.presto.spi.analyzer.AnalyzerProvider;
import com.facebook.presto.spi.security.AccessControl;
import com.facebook.presto.sql.analyzer.BuiltInQueryPreparer;
import com.facebook.presto.sql.tree.Expression;
@@ -31,6 +33,7 @@
import java.util.Optional;
import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkState;
import static java.util.Objects.requireNonNull;
public class DDLDefinitionExecution
@@ -82,14 +85,19 @@ public DDLDefinitionExecutionFactory(
@Override
public DDLDefinitionExecution> createQueryExecution(
- BuiltInQueryPreparer.BuiltInPreparedQuery preparedQuery,
+ AnalyzerProvider analyzerProvider,
+ PreparedQuery preparedQuery,
QueryStateMachine stateMachine,
String slug,
int retryCount,
WarningCollector warningCollector,
Optional queryType)
{
- return createDDLDefinitionExecution(preparedQuery.getStatement(), preparedQuery.getParameters(), stateMachine, slug, retryCount);
+ //TODO: PreparedQuery should be passed all the way to analyzer
+ checkState(preparedQuery instanceof BuiltInQueryPreparer.BuiltInPreparedQuery, "Unsupported prepared query type: %s", preparedQuery.getClass().getSimpleName());
+ BuiltInQueryPreparer.BuiltInPreparedQuery builtInQueryPreparer = (BuiltInQueryPreparer.BuiltInPreparedQuery) preparedQuery;
+
+ return createDDLDefinitionExecution(builtInQueryPreparer.getStatement(), builtInQueryPreparer.getParameters(), stateMachine, slug, retryCount);
}
private DDLDefinitionExecution createDDLDefinitionExecution(
diff --git a/presto-main/src/main/java/com/facebook/presto/execution/QueryExecution.java b/presto-main/src/main/java/com/facebook/presto/execution/QueryExecution.java
index 51e5b36c38168..52acd2ef275bd 100644
--- a/presto-main/src/main/java/com/facebook/presto/execution/QueryExecution.java
+++ b/presto-main/src/main/java/com/facebook/presto/execution/QueryExecution.java
@@ -13,6 +13,7 @@
*/
package com.facebook.presto.execution;
+import com.facebook.presto.common.analyzer.PreparedQuery;
import com.facebook.presto.common.resourceGroups.QueryType;
import com.facebook.presto.common.type.Type;
import com.facebook.presto.execution.QueryTracker.TrackedQuery;
@@ -20,8 +21,8 @@
import com.facebook.presto.memory.VersionedMemoryPoolId;
import com.facebook.presto.server.BasicQueryInfo;
import com.facebook.presto.spi.WarningCollector;
+import com.facebook.presto.spi.analyzer.AnalyzerProvider;
import com.facebook.presto.spi.resourceGroups.ResourceGroupQueryLimits;
-import com.facebook.presto.sql.analyzer.BuiltInQueryPreparer.BuiltInPreparedQuery;
import com.facebook.presto.sql.planner.Plan;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
@@ -103,7 +104,8 @@ public interface QueryExecution
interface QueryExecutionFactory
{
T createQueryExecution(
- BuiltInPreparedQuery preparedQuery,
+ AnalyzerProvider analyzerProvider,
+ PreparedQuery preparedQuery,
QueryStateMachine stateMachine,
String slug,
int retryCount,
diff --git a/presto-main/src/main/java/com/facebook/presto/execution/SessionDefinitionExecution.java b/presto-main/src/main/java/com/facebook/presto/execution/SessionDefinitionExecution.java
index b27fc8364385a..d05d1f34bf6fd 100644
--- a/presto-main/src/main/java/com/facebook/presto/execution/SessionDefinitionExecution.java
+++ b/presto-main/src/main/java/com/facebook/presto/execution/SessionDefinitionExecution.java
@@ -13,10 +13,12 @@
*/
package com.facebook.presto.execution;
+import com.facebook.presto.common.analyzer.PreparedQuery;
import com.facebook.presto.common.resourceGroups.QueryType;
import com.facebook.presto.metadata.Metadata;
import com.facebook.presto.metadata.MetadataManager;
import com.facebook.presto.spi.WarningCollector;
+import com.facebook.presto.spi.analyzer.AnalyzerProvider;
import com.facebook.presto.spi.security.AccessControl;
import com.facebook.presto.sql.analyzer.BuiltInQueryPreparer;
import com.facebook.presto.sql.tree.Expression;
@@ -31,6 +33,7 @@
import java.util.Optional;
import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkState;
import static java.util.Objects.requireNonNull;
public class SessionDefinitionExecution
@@ -82,14 +85,18 @@ public SessionDefinitionExecutionFactory(
@Override
public SessionDefinitionExecution> createQueryExecution(
- BuiltInQueryPreparer.BuiltInPreparedQuery preparedQuery,
+ AnalyzerProvider analyzerProvider,
+ PreparedQuery preparedQuery,
QueryStateMachine stateMachine,
String slug,
int retryCount,
WarningCollector warningCollector,
Optional queryType)
{
- return createSessionDefinitionExecution(preparedQuery.getStatement(), preparedQuery.getParameters(), stateMachine, slug, retryCount);
+ //TODO: PreparedQuery should be passed all the way to analyzer
+ checkState(preparedQuery instanceof BuiltInQueryPreparer.BuiltInPreparedQuery, "Unsupported prepared query type: %s", preparedQuery.getClass().getSimpleName());
+ BuiltInQueryPreparer.BuiltInPreparedQuery builtInQueryPreparer = (BuiltInQueryPreparer.BuiltInPreparedQuery) preparedQuery;
+ return createSessionDefinitionExecution(builtInQueryPreparer.getStatement(), builtInQueryPreparer.getParameters(), stateMachine, slug, retryCount);
}
private SessionDefinitionExecution createSessionDefinitionExecution(
diff --git a/presto-main/src/main/java/com/facebook/presto/execution/SqlQueryExecution.java b/presto-main/src/main/java/com/facebook/presto/execution/SqlQueryExecution.java
index 6c5abac27c48f..3dac2c91a16bf 100644
--- a/presto-main/src/main/java/com/facebook/presto/execution/SqlQueryExecution.java
+++ b/presto-main/src/main/java/com/facebook/presto/execution/SqlQueryExecution.java
@@ -15,6 +15,7 @@
import com.facebook.airlift.concurrent.SetThreadName;
import com.facebook.presto.Session;
+import com.facebook.presto.common.analyzer.PreparedQuery;
import com.facebook.presto.common.resourceGroups.QueryType;
import com.facebook.presto.cost.CostCalculator;
import com.facebook.presto.cost.HistoryBasedPlanStatisticsManager;
@@ -35,8 +36,11 @@
import com.facebook.presto.spi.ConnectorId;
import com.facebook.presto.spi.PrestoException;
import com.facebook.presto.spi.QueryId;
-import com.facebook.presto.spi.TableHandle;
import com.facebook.presto.spi.WarningCollector;
+import com.facebook.presto.spi.analyzer.AnalyzerContext;
+import com.facebook.presto.spi.analyzer.AnalyzerProvider;
+import com.facebook.presto.spi.analyzer.QueryAnalysis;
+import com.facebook.presto.spi.analyzer.QueryAnalyzer;
import com.facebook.presto.spi.function.FunctionKind;
import com.facebook.presto.spi.plan.PlanNode;
import com.facebook.presto.spi.plan.PlanNodeIdAllocator;
@@ -45,13 +49,9 @@
import com.facebook.presto.split.CloseableSplitSourceProvider;
import com.facebook.presto.split.SplitManager;
import com.facebook.presto.sql.Optimizer;
-import com.facebook.presto.sql.analyzer.Analysis;
-import com.facebook.presto.sql.analyzer.Analyzer;
-import com.facebook.presto.sql.analyzer.BuiltInQueryPreparer.BuiltInPreparedQuery;
import com.facebook.presto.sql.analyzer.QueryExplainer;
import com.facebook.presto.sql.parser.SqlParser;
import com.facebook.presto.sql.planner.InputExtractor;
-import com.facebook.presto.sql.planner.LogicalPlanner;
import com.facebook.presto.sql.planner.OutputExtractor;
import com.facebook.presto.sql.planner.PartitioningHandle;
import com.facebook.presto.sql.planner.Plan;
@@ -64,7 +64,6 @@
import com.facebook.presto.sql.planner.optimizations.PlanOptimizer;
import com.facebook.presto.sql.planner.plan.OutputNode;
import com.facebook.presto.sql.planner.sanity.PlanChecker;
-import com.facebook.presto.sql.tree.Explain;
import com.google.common.collect.ImmutableSet;
import com.google.common.util.concurrent.ListenableFuture;
import io.airlift.units.DataSize;
@@ -96,8 +95,8 @@
import static com.facebook.presto.execution.buffer.OutputBuffers.createSpoolingOutputBuffers;
import static com.facebook.presto.spi.StandardErrorCode.NOT_SUPPORTED;
import static com.facebook.presto.sql.Optimizer.PlanStage.OPTIMIZED_AND_VALIDATED;
-import static com.facebook.presto.sql.analyzer.utils.ParameterUtils.parameterExtractor;
import static com.facebook.presto.sql.planner.PlanNodeCanonicalInfo.getCanonicalInfo;
+import static com.facebook.presto.util.AnalyzerUtil.getAnalyzerContext;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Throwables.throwIfInstanceOf;
import static io.airlift.units.DataSize.Unit.BYTE;
@@ -111,6 +110,7 @@ public class SqlQueryExecution
{
private static final OutputBufferId OUTPUT_BUFFER_ID = new OutputBufferId(0);
+ private final QueryAnalyzer queryAnalyzer;
private final QueryStateMachine stateMachine;
private final String slug;
private final int retryCount;
@@ -131,7 +131,6 @@ public class SqlQueryExecution
private final AtomicReference queryPlan = new AtomicReference<>();
private final ExecutionPolicy executionPolicy;
private final SplitSchedulerStats schedulerStats;
- private final Analysis analysis;
private final StatsCalculator statsCalculator;
private final CostCalculator costCalculator;
private final PlanChecker planChecker;
@@ -140,9 +139,12 @@ public class SqlQueryExecution
private final PartialResultQueryManager partialResultQueryManager;
private final AtomicReference> resourceGroupQueryLimits = new AtomicReference<>(Optional.empty());
private final PlanCanonicalInfoProvider planCanonicalInfoProvider;
+ private final QueryAnalysis queryAnalysis;
+ private final AnalyzerContext analyzerContext;
private SqlQueryExecution(
- BuiltInPreparedQuery preparedQuery,
+ QueryAnalyzer queryAnalyzer,
+ PreparedQuery preparedQuery,
QueryStateMachine stateMachine,
String slug,
int retryCount,
@@ -170,6 +172,7 @@ private SqlQueryExecution(
PlanCanonicalInfoProvider planCanonicalInfoProvider)
{
try (SetThreadName ignored = new SetThreadName("Query-%s", stateMachine.getQueryId())) {
+ this.queryAnalyzer = requireNonNull(queryAnalyzer, "queryAnalyzer is null");
this.slug = requireNonNull(slug, "slug is null");
this.retryCount = retryCount;
this.metadata = requireNonNull(metadata, "metadata is null");
@@ -190,32 +193,25 @@ private SqlQueryExecution(
this.stateMachine = requireNonNull(stateMachine, "stateMachine is null");
this.planChecker = requireNonNull(planChecker, "planChecker is null");
this.planCanonicalInfoProvider = requireNonNull(planCanonicalInfoProvider, "planCanonicalInfoProvider is null");
+ this.analyzerContext = getAnalyzerContext(queryAnalyzer, idAllocator, new PlanVariableAllocator(), stateMachine.getSession());
// analyze query
requireNonNull(preparedQuery, "preparedQuery is null");
stateMachine.beginSemanticAnalyzing();
- Analyzer analyzer = new Analyzer(
- stateMachine.getSession(),
- metadata,
- sqlParser,
- accessControl,
- Optional.of(queryExplainer),
- preparedQuery.getParameters(),
- parameterExtractor(preparedQuery.getStatement(), preparedQuery.getParameters()),
- warningCollector);
try (TimeoutThread unused = new TimeoutThread(
Thread.currentThread(),
timeoutThreadExecutor,
getQueryAnalyzerTimeout(getSession()))) {
- this.analysis = analyzer.analyzeSemantic(preparedQuery.getStatement(), false);
+ this.queryAnalysis = queryAnalyzer.analyze(analyzerContext, preparedQuery);
}
- stateMachine.setUpdateType(analysis.getUpdateType());
- stateMachine.setExpandedQuery(analysis.getExpandedQuery());
+
+ stateMachine.setUpdateType(queryAnalysis.getUpdateType());
+ stateMachine.setExpandedQuery(queryAnalysis.getExpandedQuery());
stateMachine.beginColumnAccessPermissionChecking();
- analyzer.checkColumnAccessPermissions(this.analysis);
+ queryAnalyzer.checkAccessPermissions(analyzerContext, queryAnalysis);
stateMachine.endColumnAccessPermissionChecking();
// when the query finishes cache the final query info, and clear the reference to the output stage
@@ -236,7 +232,7 @@ private SqlQueryExecution(
this.partialResultQueryManager = requireNonNull(partialResultQueryManager, "partialResultQueryManager is null");
if (isLogInvokedFunctionNamesEnabled(getSession())) {
- for (Map.Entry> entry : analysis.getInvokedFunctions().entrySet()) {
+ for (Map.Entry> entry : queryAnalysis.getInvokedFunctions().entrySet()) {
switch (entry.getKey()) {
case SCALAR:
stateMachine.setScalarFunctions(entry.getValue());
@@ -454,7 +450,7 @@ public void start()
timeoutThreadExecutor,
getQueryAnalyzerTimeout(getSession()))) {
// create logical plan for the query
- plan = createLogicalPlan();
+ plan = createLogicalPlanAndOptimize();
}
metadata.beginQuery(getSession(), plan.getConnectors());
@@ -520,23 +516,15 @@ public void addFinalQueryInfoListener(StateChangeListener stateChange
stateMachine.addQueryInfoStateChangeListener(stateChangeListener);
}
- private PlanRoot createLogicalPlan()
+ private PlanRoot createLogicalPlanAndOptimize()
{
try {
// time analysis phase
stateMachine.beginAnalysis();
- // plan query
- final PlanVariableAllocator planVariableAllocator = new PlanVariableAllocator();
- LogicalPlanner logicalPlanner = new LogicalPlanner(
- stateMachine.getSession(),
- idAllocator,
- metadata,
- planVariableAllocator);
-
- PlanNode planNode = getSession().getRuntimeStats().profileNanos(
+ PlanNode planNode = stateMachine.getSession().getRuntimeStats().profileNanos(
LOGICAL_PLANNER_TIME_NANOS,
- () -> logicalPlanner.plan(analysis));
+ () -> queryAnalyzer.plan(this.analyzerContext, queryAnalysis));
Optimizer optimizer = new Optimizer(
stateMachine.getSession(),
@@ -544,7 +532,7 @@ private PlanRoot createLogicalPlan()
planOptimizers,
planChecker,
sqlParser,
- planVariableAllocator,
+ analyzerContext.getVariableAllocator(),
idAllocator,
stateMachine.getWarningCollector(),
statsCalculator,
@@ -577,30 +565,14 @@ private PlanRoot createLogicalPlan()
// record analysis time
stateMachine.endAnalysis();
- boolean explainAnalyze = analysis.getStatement() instanceof Explain && ((Explain) analysis.getStatement()).isAnalyze();
- return new PlanRoot(fragmentedPlan, !explainAnalyze, extractConnectors(analysis));
+ boolean explainAnalyze = queryAnalyzer.isExplainAnalyzeQuery(queryAnalysis);
+ return new PlanRoot(fragmentedPlan, !explainAnalyze, queryAnalyzer.extractConnectors(queryAnalysis));
}
catch (StackOverflowError e) {
throw new PrestoException(NOT_SUPPORTED, "statement is too large (stack overflow during analysis)", e);
}
}
- private static Set extractConnectors(Analysis analysis)
- {
- ImmutableSet.Builder connectors = ImmutableSet.builder();
-
- for (TableHandle tableHandle : analysis.getTables()) {
- connectors.add(tableHandle.getConnectorId());
- }
-
- if (analysis.getInsert().isPresent()) {
- TableHandle target = analysis.getInsert().get().getTarget();
- connectors.add(target.getConnectorId());
- }
-
- return connectors.build();
- }
-
private void planDistribution(PlanRoot plan)
{
CloseableSplitSourceProvider splitSourceProvider = new CloseableSplitSourceProvider(splitManager::getSplits);
@@ -940,7 +912,8 @@ public static class SqlQueryExecutionFactory
@Override
public QueryExecution createQueryExecution(
- BuiltInPreparedQuery preparedQuery,
+ AnalyzerProvider analyzerProvider,
+ PreparedQuery preparedQuery,
QueryStateMachine stateMachine,
String slug,
int retryCount,
@@ -952,6 +925,7 @@ public QueryExecution createQueryExecution(
checkArgument(executionPolicy != null, "No execution policy %s", executionPolicy);
return new SqlQueryExecution(
+ analyzerProvider.getQueryAnalyzer(),
preparedQuery,
stateMachine,
slug,
diff --git a/presto-main/src/main/java/com/facebook/presto/server/ServerMainModule.java b/presto-main/src/main/java/com/facebook/presto/server/ServerMainModule.java
index b0b6431c5092e..dadb3597d284a 100644
--- a/presto-main/src/main/java/com/facebook/presto/server/ServerMainModule.java
+++ b/presto-main/src/main/java/com/facebook/presto/server/ServerMainModule.java
@@ -174,9 +174,11 @@
import com.facebook.presto.sql.SqlEnvironmentConfig;
import com.facebook.presto.sql.analyzer.AnalyzerProviderManager;
import com.facebook.presto.sql.analyzer.BuiltInAnalyzerProvider;
+import com.facebook.presto.sql.analyzer.BuiltInQueryAnalyzer;
import com.facebook.presto.sql.analyzer.BuiltInQueryPreparer;
import com.facebook.presto.sql.analyzer.FeaturesConfig;
import com.facebook.presto.sql.analyzer.FeaturesConfig.SingleStreamSpillerChoice;
+import com.facebook.presto.sql.analyzer.QueryExplainer;
import com.facebook.presto.sql.analyzer.ViewDefinition;
import com.facebook.presto.sql.gen.ExpressionCompiler;
import com.facebook.presto.sql.gen.JoinCompiler;
@@ -302,6 +304,8 @@ else if (serverConfig.isCoordinator()) {
// analyzer
binder.bind(BuiltInQueryPreparer.class).in(Scopes.SINGLETON);
+ newOptionalBinder(binder, QueryExplainer.class);
+ binder.bind(BuiltInQueryAnalyzer.class).in(Scopes.SINGLETON);
binder.bind(BuiltInAnalyzerProvider.class).in(Scopes.SINGLETON);
binder.bind(AnalyzerProviderManager.class).in(Scopes.SINGLETON);
diff --git a/presto-main/src/main/java/com/facebook/presto/sql/Optimizer.java b/presto-main/src/main/java/com/facebook/presto/sql/Optimizer.java
index 525b6bced2542..db8b137051dde 100644
--- a/presto-main/src/main/java/com/facebook/presto/sql/Optimizer.java
+++ b/presto-main/src/main/java/com/facebook/presto/sql/Optimizer.java
@@ -23,6 +23,7 @@
import com.facebook.presto.cost.StatsCalculator;
import com.facebook.presto.cost.StatsProvider;
import com.facebook.presto.metadata.Metadata;
+import com.facebook.presto.spi.VariableAllocator;
import com.facebook.presto.spi.WarningCollector;
import com.facebook.presto.spi.plan.PlanNode;
import com.facebook.presto.spi.plan.PlanNodeIdAllocator;
@@ -43,6 +44,7 @@
import static com.facebook.presto.common.RuntimeUnit.NANO;
import static com.facebook.presto.sql.Optimizer.PlanStage.OPTIMIZED;
import static com.facebook.presto.sql.Optimizer.PlanStage.OPTIMIZED_AND_VALIDATED;
+import static com.google.common.base.Preconditions.checkState;
import static java.lang.String.format;
import static java.util.Objects.requireNonNull;
@@ -71,7 +73,7 @@ public Optimizer(
List planOptimizers,
PlanChecker planChecker,
SqlParser sqlParser,
- PlanVariableAllocator variableAllocator,
+ VariableAllocator variableAllocator,
PlanNodeIdAllocator idAllocator,
WarningCollector warningCollector,
StatsCalculator statsCalculator,
@@ -83,7 +85,11 @@ public Optimizer(
this.planChecker = requireNonNull(planChecker, "planChecker is null");
this.metadata = requireNonNull(metadata, "metadata is null");
this.sqlParser = requireNonNull(sqlParser, "sqlParser is null");
- this.variableAllocator = requireNonNull(variableAllocator, "variableAllocator is null");
+ requireNonNull(variableAllocator, "variableAllocator is null");
+ checkState(variableAllocator instanceof PlanVariableAllocator, "variableAllocator must be an instance of PlanVariableAllocator");
+
+ // TODO: We should cleanup redundancy between VariableAllocator and PlanVariableAllocator.
+ this.variableAllocator = (PlanVariableAllocator) variableAllocator;
this.idAllocator = requireNonNull(idAllocator, "idAllocator is null");
this.warningCollector = requireNonNull(warningCollector, "warningCollector is null");
this.statsCalculator = requireNonNull(statsCalculator, "statsCalculator is null");
diff --git a/presto-main/src/main/java/com/facebook/presto/sql/analyzer/Analyzer.java b/presto-main/src/main/java/com/facebook/presto/sql/analyzer/Analyzer.java
index cd435c9bf5e9f..4c3d0d6298091 100644
--- a/presto-main/src/main/java/com/facebook/presto/sql/analyzer/Analyzer.java
+++ b/presto-main/src/main/java/com/facebook/presto/sql/analyzer/Analyzer.java
@@ -55,7 +55,8 @@ public class Analyzer
private final Map, Expression> parameterLookup;
private final WarningCollector warningCollector;
- public Analyzer(Session session,
+ public Analyzer(
+ Session session,
Metadata metadata,
SqlParser sqlParser,
AccessControl accessControl,
@@ -69,8 +70,8 @@ public Analyzer(Session session,
this.sqlParser = requireNonNull(sqlParser, "sqlParser is null");
this.accessControl = requireNonNull(accessControl, "accessControl is null");
this.queryExplainer = requireNonNull(queryExplainer, "query explainer is null");
- this.parameters = parameters;
- this.parameterLookup = parameterLookup;
+ this.parameters = requireNonNull(parameters, "parameters is null");
+ this.parameterLookup = requireNonNull(parameterLookup, "parameterLookup is null");
this.warningCollector = requireNonNull(warningCollector, "warningCollector is null");
}
@@ -79,6 +80,7 @@ public Analysis analyze(Statement statement)
return analyze(statement, false);
}
+ // TODO: Remove this method once all calls are moved to analyzer interface, as this call is overloaded with analyze and columnCheckPermissions
public Analysis analyze(Statement statement, boolean isDescribe)
{
Analysis analysis = analyzeSemantic(statement, isDescribe);
diff --git a/presto-analyzer/src/main/java/com/facebook/presto/sql/analyzer/AnalyzerProviderManager.java b/presto-main/src/main/java/com/facebook/presto/sql/analyzer/AnalyzerProviderManager.java
similarity index 100%
rename from presto-analyzer/src/main/java/com/facebook/presto/sql/analyzer/AnalyzerProviderManager.java
rename to presto-main/src/main/java/com/facebook/presto/sql/analyzer/AnalyzerProviderManager.java
diff --git a/presto-main/src/main/java/com/facebook/presto/sql/analyzer/BuiltInAnalyzerContext.java b/presto-main/src/main/java/com/facebook/presto/sql/analyzer/BuiltInAnalyzerContext.java
new file mode 100644
index 0000000000000..465ca9523c69f
--- /dev/null
+++ b/presto-main/src/main/java/com/facebook/presto/sql/analyzer/BuiltInAnalyzerContext.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed 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 com.facebook.presto.sql.analyzer;
+
+import com.facebook.presto.Session;
+import com.facebook.presto.spi.VariableAllocator;
+import com.facebook.presto.spi.analyzer.AnalyzerContext;
+import com.facebook.presto.spi.plan.PlanNodeIdAllocator;
+
+public class BuiltInAnalyzerContext
+ extends AnalyzerContext
+{
+ private final Session session;
+
+ public BuiltInAnalyzerContext(PlanNodeIdAllocator idAllocator, VariableAllocator variableAllocator, Session session)
+ {
+ super(idAllocator, variableAllocator);
+ this.session = session;
+ }
+
+ public Session getSession()
+ {
+ return session;
+ }
+}
diff --git a/presto-analyzer/src/main/java/com/facebook/presto/sql/analyzer/BuiltInAnalyzerProvider.java b/presto-main/src/main/java/com/facebook/presto/sql/analyzer/BuiltInAnalyzerProvider.java
similarity index 79%
rename from presto-analyzer/src/main/java/com/facebook/presto/sql/analyzer/BuiltInAnalyzerProvider.java
rename to presto-main/src/main/java/com/facebook/presto/sql/analyzer/BuiltInAnalyzerProvider.java
index e0c7ca5dfba83..9f879593bd26a 100644
--- a/presto-analyzer/src/main/java/com/facebook/presto/sql/analyzer/BuiltInAnalyzerProvider.java
+++ b/presto-main/src/main/java/com/facebook/presto/sql/analyzer/BuiltInAnalyzerProvider.java
@@ -14,6 +14,7 @@
package com.facebook.presto.sql.analyzer;
import com.facebook.presto.spi.analyzer.AnalyzerProvider;
+import com.facebook.presto.spi.analyzer.QueryAnalyzer;
import com.facebook.presto.spi.analyzer.QueryPreparer;
import com.google.inject.Inject;
@@ -24,11 +25,13 @@ public class BuiltInAnalyzerProvider
{
private static final String PROVIDER_NAME = "BUILTIN";
private final BuiltInQueryPreparer queryPreparer;
+ private final BuiltInQueryAnalyzer queryAnalyzer;
@Inject
- public BuiltInAnalyzerProvider(BuiltInQueryPreparer queryPreparer)
+ public BuiltInAnalyzerProvider(BuiltInQueryPreparer queryPreparer, BuiltInQueryAnalyzer queryAnalyzer)
{
this.queryPreparer = requireNonNull(queryPreparer, "queryPreparer is null");
+ this.queryAnalyzer = requireNonNull(queryAnalyzer, "queryAnalyzer is null");
}
@Override
@@ -42,4 +45,10 @@ public QueryPreparer getQueryPreparer()
{
return queryPreparer;
}
+
+ @Override
+ public QueryAnalyzer getQueryAnalyzer()
+ {
+ return queryAnalyzer;
+ }
}
diff --git a/presto-main/src/main/java/com/facebook/presto/sql/analyzer/BuiltInQueryAnalyzer.java b/presto-main/src/main/java/com/facebook/presto/sql/analyzer/BuiltInQueryAnalyzer.java
new file mode 100644
index 0000000000000..fbc0184b2d5a4
--- /dev/null
+++ b/presto-main/src/main/java/com/facebook/presto/sql/analyzer/BuiltInQueryAnalyzer.java
@@ -0,0 +1,138 @@
+/*
+ * Licensed 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 com.facebook.presto.sql.analyzer;
+
+import com.facebook.presto.Session;
+import com.facebook.presto.common.analyzer.PreparedQuery;
+import com.facebook.presto.metadata.Metadata;
+import com.facebook.presto.spi.ConnectorId;
+import com.facebook.presto.spi.TableHandle;
+import com.facebook.presto.spi.VariableAllocator;
+import com.facebook.presto.spi.analyzer.AnalyzerContext;
+import com.facebook.presto.spi.analyzer.QueryAnalysis;
+import com.facebook.presto.spi.analyzer.QueryAnalyzer;
+import com.facebook.presto.spi.plan.PlanNode;
+import com.facebook.presto.spi.plan.PlanNodeIdAllocator;
+import com.facebook.presto.spi.security.AccessControl;
+import com.facebook.presto.sql.parser.SqlParser;
+import com.facebook.presto.sql.planner.LogicalPlanner;
+import com.facebook.presto.sql.tree.Explain;
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Inject;
+
+import java.util.Optional;
+import java.util.Set;
+
+import static com.facebook.presto.SystemSessionProperties.isCheckAccessControlOnUtilizedColumnsOnly;
+import static com.facebook.presto.SystemSessionProperties.isCheckAccessControlWithSubfields;
+import static com.facebook.presto.sql.analyzer.utils.ParameterUtils.parameterExtractor;
+import static com.google.common.base.Preconditions.checkState;
+import static java.util.Objects.requireNonNull;
+
+public class BuiltInQueryAnalyzer
+ implements QueryAnalyzer
+{
+ private final Metadata metadata;
+ private final SqlParser sqlParser;
+ private final AccessControl accessControl;
+ private final Optional queryExplainer;
+
+ @Inject
+ public BuiltInQueryAnalyzer(Metadata metadata, SqlParser sqlParser, AccessControl accessControl, Optional queryExplainer)
+ {
+ this.metadata = requireNonNull(metadata, "metadata is null");
+ this.sqlParser = requireNonNull(sqlParser, "sqlParser is null");
+ this.accessControl = requireNonNull(accessControl, "accessControl is null");
+ this.queryExplainer = requireNonNull(queryExplainer, "query explainer is null");
+ }
+
+ public static BuiltInAnalyzerContext getBuiltInAnalyzerContext(PlanNodeIdAllocator idAllocator, VariableAllocator variableAllocator, Session session)
+ {
+ return new BuiltInAnalyzerContext(idAllocator, variableAllocator, session);
+ }
+
+ @Override
+ public QueryAnalysis analyze(AnalyzerContext analyzerContext, PreparedQuery preparedQuery)
+ {
+ requireNonNull(preparedQuery, "preparedQuery is null");
+
+ checkState(analyzerContext instanceof BuiltInAnalyzerContext, "analyzerContext should be an instance of BuiltInAnalyzerContext");
+ checkState(preparedQuery instanceof BuiltInQueryPreparer.BuiltInPreparedQuery, "Unsupported prepared query type: %s", preparedQuery.getClass().getSimpleName());
+
+ BuiltInQueryPreparer.BuiltInPreparedQuery builtInPreparedQuery = (BuiltInQueryPreparer.BuiltInPreparedQuery) preparedQuery;
+ Session session = ((BuiltInAnalyzerContext) analyzerContext).getSession();
+
+ Analyzer analyzer = new Analyzer(
+ session,
+ metadata,
+ sqlParser,
+ accessControl,
+ queryExplainer,
+ builtInPreparedQuery.getParameters(),
+ parameterExtractor(builtInPreparedQuery.getStatement(), builtInPreparedQuery.getParameters()),
+ session.getWarningCollector());
+
+ Analysis analysis = analyzer.analyzeSemantic(((BuiltInQueryPreparer.BuiltInPreparedQuery) preparedQuery).getStatement(), false);
+ return new BuiltInQueryAnalysis(analysis);
+ }
+
+ @Override
+ public PlanNode plan(AnalyzerContext analyzerContext, QueryAnalysis queryAnalysis)
+ {
+ checkState(analyzerContext instanceof BuiltInAnalyzerContext, "analyzerContext should be an instance of BuiltInAnalyzerContext");
+ return new LogicalPlanner(((BuiltInAnalyzerContext) analyzerContext).getSession(), analyzerContext.getIdAllocator(), metadata, analyzerContext.getVariableAllocator()).plan(((BuiltInQueryAnalysis) queryAnalysis).getAnalysis());
+ }
+
+ @Override
+ public void checkAccessPermissions(AnalyzerContext analyzerContext, QueryAnalysis queryAnalysis)
+ {
+ checkState(analyzerContext instanceof BuiltInAnalyzerContext, "analyzerContext should be an instance of BuiltInAnalyzerContext");
+ Session session = ((BuiltInAnalyzerContext) analyzerContext).getSession();
+ BuiltInQueryAnalysis builtInQueryAnalysis = (BuiltInQueryAnalysis) queryAnalysis;
+ builtInQueryAnalysis.getAnalysis().getTableColumnAndSubfieldReferencesForAccessControl(isCheckAccessControlOnUtilizedColumnsOnly(session), isCheckAccessControlWithSubfields(session))
+ .forEach((accessControlInfo, tableColumnReferences) ->
+ tableColumnReferences.forEach((tableName, columns) ->
+ accessControlInfo.getAccessControl().checkCanSelectFromColumns(
+ session.getRequiredTransactionId(),
+ accessControlInfo.getIdentity(),
+ session.getAccessControlContext(),
+ tableName,
+ columns)));
+ }
+
+ @Override
+ public boolean isExplainAnalyzeQuery(QueryAnalysis queryAnalysis)
+ {
+ Analysis analysis = ((BuiltInQueryAnalysis) queryAnalysis).getAnalysis();
+ return analysis.getStatement() instanceof Explain && ((Explain) analysis.getStatement()).isAnalyze();
+ }
+
+ @Override
+ public Set extractConnectors(QueryAnalysis queryAnalysis)
+ {
+ Analysis analysis = ((BuiltInQueryAnalysis) queryAnalysis).getAnalysis();
+ ImmutableSet.Builder connectors = ImmutableSet.builder();
+
+ for (TableHandle tableHandle : analysis.getTables()) {
+ connectors.add(tableHandle.getConnectorId());
+ }
+
+ if (analysis.getInsert().isPresent()) {
+ TableHandle target = analysis.getInsert().get().getTarget();
+ connectors.add(target.getConnectorId());
+ }
+
+ return connectors.build();
+ }
+}
diff --git a/presto-main/src/main/java/com/facebook/presto/sql/planner/LogicalPlanner.java b/presto-main/src/main/java/com/facebook/presto/sql/planner/LogicalPlanner.java
index bf2de4623eeed..91fef1e31a14d 100644
--- a/presto-main/src/main/java/com/facebook/presto/sql/planner/LogicalPlanner.java
+++ b/presto-main/src/main/java/com/facebook/presto/sql/planner/LogicalPlanner.java
@@ -26,6 +26,7 @@
import com.facebook.presto.spi.PrestoException;
import com.facebook.presto.spi.TableHandle;
import com.facebook.presto.spi.TableMetadata;
+import com.facebook.presto.spi.VariableAllocator;
import com.facebook.presto.spi.plan.AggregationNode;
import com.facebook.presto.spi.plan.Assignments;
import com.facebook.presto.spi.plan.LimitNode;
@@ -113,13 +114,17 @@ public LogicalPlanner(
Session session,
PlanNodeIdAllocator idAllocator,
Metadata metadata,
- PlanVariableAllocator variableAllocator)
+ VariableAllocator variableAllocator)
{
this.session = requireNonNull(session, "session is null");
this.idAllocator = requireNonNull(idAllocator, "idAllocator is null");
this.metadata = requireNonNull(metadata, "metadata is null");
- this.variableAllocator = requireNonNull(variableAllocator, "variableAllocator is null");
- this.statisticsAggregationPlanner = new StatisticsAggregationPlanner(variableAllocator, metadata.getFunctionAndTypeManager().getFunctionAndTypeResolver());
+ requireNonNull(variableAllocator, "variableAllocator is null");
+ checkState(variableAllocator instanceof PlanVariableAllocator, "variableAllocator should be instance of PlanVariableAllocator");
+
+ // TODO: We should cleanup redundancy between VariableAllocator and PlanVariableAllocator.
+ this.variableAllocator = (PlanVariableAllocator) variableAllocator;
+ this.statisticsAggregationPlanner = new StatisticsAggregationPlanner(this.variableAllocator, metadata.getFunctionAndTypeManager().getFunctionAndTypeResolver());
}
public PlanNode plan(Analysis analysis)
diff --git a/presto-main/src/main/java/com/facebook/presto/testing/LocalQueryRunner.java b/presto-main/src/main/java/com/facebook/presto/testing/LocalQueryRunner.java
index bc9328d75881c..464f19c02896f 100644
--- a/presto-main/src/main/java/com/facebook/presto/testing/LocalQueryRunner.java
+++ b/presto-main/src/main/java/com/facebook/presto/testing/LocalQueryRunner.java
@@ -127,7 +127,9 @@
import com.facebook.presto.spi.PageSorter;
import com.facebook.presto.spi.Plugin;
import com.facebook.presto.spi.WarningCollector;
+import com.facebook.presto.spi.analyzer.AnalyzerContext;
import com.facebook.presto.spi.analyzer.AnalyzerOptions;
+import com.facebook.presto.spi.analyzer.QueryAnalysis;
import com.facebook.presto.spi.connector.ConnectorFactory;
import com.facebook.presto.spi.connector.ConnectorSplitManager.SplitSchedulingStrategy;
import com.facebook.presto.spi.eventlistener.EventListener;
@@ -149,10 +151,9 @@
import com.facebook.presto.split.SplitManager;
import com.facebook.presto.split.SplitSource;
import com.facebook.presto.sql.Optimizer;
-import com.facebook.presto.sql.analyzer.Analysis;
-import com.facebook.presto.sql.analyzer.Analyzer;
import com.facebook.presto.sql.analyzer.AnalyzerProviderManager;
import com.facebook.presto.sql.analyzer.BuiltInAnalyzerProvider;
+import com.facebook.presto.sql.analyzer.BuiltInQueryAnalyzer;
import com.facebook.presto.sql.analyzer.BuiltInQueryPreparer;
import com.facebook.presto.sql.analyzer.BuiltInQueryPreparer.BuiltInPreparedQuery;
import com.facebook.presto.sql.analyzer.FeaturesConfig;
@@ -169,7 +170,6 @@
import com.facebook.presto.sql.planner.ConnectorPlanOptimizerManager;
import com.facebook.presto.sql.planner.LocalExecutionPlanner;
import com.facebook.presto.sql.planner.LocalExecutionPlanner.LocalExecutionPlan;
-import com.facebook.presto.sql.planner.LogicalPlanner;
import com.facebook.presto.sql.planner.NodePartitioningManager;
import com.facebook.presto.sql.planner.PartitioningProviderManager;
import com.facebook.presto.sql.planner.Plan;
@@ -259,7 +259,6 @@
import static com.facebook.presto.spi.connector.ConnectorSplitManager.SplitSchedulingStrategy.UNGROUPED_SCHEDULING;
import static com.facebook.presto.spi.connector.NotPartitionedPartitionHandle.NOT_PARTITIONED;
import static com.facebook.presto.sql.Optimizer.PlanStage.OPTIMIZED_AND_VALIDATED;
-import static com.facebook.presto.sql.analyzer.utils.ParameterUtils.parameterExtractor;
import static com.facebook.presto.sql.planner.optimizations.PlanNodeSearcher.searchFrom;
import static com.facebook.presto.sql.testing.TreeAssertions.assertFormattedSql;
import static com.facebook.presto.testing.TestingSession.TESTING_CATALOG;
@@ -267,6 +266,7 @@
import static com.facebook.presto.transaction.TransactionBuilder.transaction;
import static com.facebook.presto.util.AnalyzerUtil.createAnalyzerOptions;
import static com.facebook.presto.util.AnalyzerUtil.createParsingOptions;
+import static com.facebook.presto.util.AnalyzerUtil.getAnalyzerContext;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.base.Verify.verify;
@@ -476,13 +476,16 @@ private LocalQueryRunner(Session defaultSession, FeaturesConfig featuresConfig,
new TransactionsSystemTable(metadata.getFunctionAndTypeManager(), transactionManager)),
ImmutableSet.of());
+ BuiltInQueryAnalyzer queryAnalyzer = new BuiltInQueryAnalyzer(metadata, sqlParser, accessControl, Optional.empty());
+ BuiltInAnalyzerProvider analyzerProvider = new BuiltInAnalyzerProvider(new BuiltInQueryPreparer(sqlParser), queryAnalyzer);
+
this.pluginManager = new PluginManager(
nodeInfo,
new PluginManagerConfig(),
connectorManager,
metadata,
new NoOpResourceGroupManager(),
- new AnalyzerProviderManager(new BuiltInAnalyzerProvider(new BuiltInQueryPreparer(sqlParser))),
+ new AnalyzerProviderManager(analyzerProvider),
accessControl,
new PasswordAuthenticatorManager(),
new EventListenerManager(),
@@ -1056,20 +1059,17 @@ public Plan createPlan(Session session, @Language("SQL") String sql, List logicalPlanner.plan(analysis));
+ () -> queryAnalyzer.plan(analyzerContext, queryAnalysis));
Optimizer optimizer = new Optimizer(
session,
@@ -1077,7 +1077,7 @@ public Plan createPlan(Session session, @Language("SQL") String sql, List getExpandedQuery();
+
+ /**
+ * Returns function names based on the kinds (scalar, aggregate and window).
+ */
+ Map> getInvokedFunctions();
+}
diff --git a/presto-spi/src/main/java/com/facebook/presto/spi/analyzer/QueryAnalyzer.java b/presto-spi/src/main/java/com/facebook/presto/spi/analyzer/QueryAnalyzer.java
new file mode 100644
index 0000000000000..a7d0ac33ab0c8
--- /dev/null
+++ b/presto-spi/src/main/java/com/facebook/presto/spi/analyzer/QueryAnalyzer.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed 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 com.facebook.presto.spi.analyzer;
+
+import com.facebook.presto.common.analyzer.PreparedQuery;
+import com.facebook.presto.spi.ConnectorId;
+import com.facebook.presto.spi.plan.PlanNode;
+
+import java.util.Set;
+
+/**
+ * The QueryAnalyzer interface should be implemented by respective analyzer to provide various analyzer related functionalities.
+ */
+public interface QueryAnalyzer
+{
+ /**
+ * Analyzes a prepared query in the given analyzer context.
+ *
+ * @param analyzerContext analyzer context which stores various information used by analyzer
+ * @param preparedQuery prepared query which needs to be analyzed
+ * @return Query analysis object which stores various semantic analysis of the query
+ */
+ QueryAnalysis analyze(AnalyzerContext analyzerContext, PreparedQuery preparedQuery);
+
+ /**
+ * Check access permission for the various tables and columns used in the query.
+ *
+ * @param analyzerContext analyzerContext analyzer context which stores various information used by analyzer
+ * @param queryAnalysis query analysis on which the access permissions needs to be checked
+ */
+ void checkAccessPermissions(AnalyzerContext analyzerContext, QueryAnalysis queryAnalysis);
+
+ /**
+ * Create logical plan for a given query analysis.
+ *
+ * @param analyzerContext analyzerContext analyzer context which stores various information used by analyzer
+ * @param queryAnalysis query analysis for which logical plan needs to be created
+ * @return root logical plan node created from the given query analysis
+ */
+ PlanNode plan(AnalyzerContext analyzerContext, QueryAnalysis queryAnalysis);
+
+ /**
+ * Returns whether the given QueryAnalysis represents an "EXPLAIN ANALYZE" query.
+ */
+ boolean isExplainAnalyzeQuery(QueryAnalysis queryAnalysis);
+
+ /**
+ * Extracts the set of ConnectorIds used in the given QueryAnalysis.
+ */
+ Set extractConnectors(QueryAnalysis queryAnalysis);
+}
diff --git a/presto-spi/src/main/java/com/facebook/presto/spi/analyzer/QueryPreparer.java b/presto-spi/src/main/java/com/facebook/presto/spi/analyzer/QueryPreparer.java
index e15aa8137d32b..0e1167bc2da27 100644
--- a/presto-spi/src/main/java/com/facebook/presto/spi/analyzer/QueryPreparer.java
+++ b/presto-spi/src/main/java/com/facebook/presto/spi/analyzer/QueryPreparer.java
@@ -29,7 +29,7 @@ public interface QueryPreparer
* @param query query string which needs to be prepared
* @param preparedStatements existing prepared query statements
* @param warningCollector Warning collector to collect various warnings
- * @return preared query object
+ * @return prepared query object
*/
PreparedQuery prepareQuery(AnalyzerOptions analyzerOptions, String query, Map preparedStatements, WarningCollector warningCollector);
}