diff --git a/core/trino-main/src/main/java/io/trino/execution/CreateMaterializedViewTask.java b/core/trino-main/src/main/java/io/trino/execution/CreateMaterializedViewTask.java index 8b9933aa12a1..1ef593a3aacb 100644 --- a/core/trino-main/src/main/java/io/trino/execution/CreateMaterializedViewTask.java +++ b/core/trino-main/src/main/java/io/trino/execution/CreateMaterializedViewTask.java @@ -16,16 +16,14 @@ import com.google.common.util.concurrent.ListenableFuture; import io.trino.Session; import io.trino.connector.CatalogName; -import io.trino.cost.StatsCalculator; import io.trino.execution.warnings.WarningCollector; import io.trino.metadata.MaterializedViewDefinition; import io.trino.metadata.Metadata; import io.trino.metadata.QualifiedObjectName; import io.trino.metadata.ViewColumn; import io.trino.security.AccessControl; -import io.trino.spi.security.GroupProvider; import io.trino.sql.analyzer.Analysis; -import io.trino.sql.analyzer.Analyzer; +import io.trino.sql.analyzer.AnalyzerFactory; import io.trino.sql.parser.SqlParser; import io.trino.sql.tree.CreateMaterializedView; import io.trino.sql.tree.Expression; @@ -53,17 +51,15 @@ public class CreateMaterializedViewTask private final Metadata metadata; private final AccessControl accessControl; private final SqlParser sqlParser; - private final GroupProvider groupProvider; - private final StatsCalculator statsCalculator; + private final AnalyzerFactory analyzerFactory; @Inject - public CreateMaterializedViewTask(Metadata metadata, AccessControl accessControl, SqlParser sqlParser, GroupProvider groupProvider, StatsCalculator statsCalculator) + public CreateMaterializedViewTask(Metadata metadata, AccessControl accessControl, SqlParser sqlParser, AnalyzerFactory analyzerFactory) { this.metadata = requireNonNull(metadata, "metadata is null"); this.accessControl = requireNonNull(accessControl, "accessControl is null"); this.sqlParser = requireNonNull(sqlParser, "sqlParser is null"); - this.groupProvider = requireNonNull(groupProvider, "groupProvider is null"); - this.statsCalculator = requireNonNull(statsCalculator, "statsCalculator is null"); + this.analyzerFactory = requireNonNull(analyzerFactory, "analyzerFactory is null"); } @Override @@ -85,7 +81,7 @@ public ListenableFuture execute( String sql = getFormattedSql(statement.getQuery(), sqlParser); - Analysis analysis = new Analyzer(session, metadata, sqlParser, groupProvider, accessControl, Optional.empty(), parameters, parameterLookup, stateMachine.getWarningCollector(), statsCalculator) + Analysis analysis = analyzerFactory.createAnalyzer(session, parameters, parameterLookup, stateMachine.getWarningCollector()) .analyze(statement); List columns = analysis.getOutputDescriptor(statement.getQuery()) diff --git a/core/trino-main/src/main/java/io/trino/execution/CreateViewTask.java b/core/trino-main/src/main/java/io/trino/execution/CreateViewTask.java index c8c050c830e0..904da886bf90 100644 --- a/core/trino-main/src/main/java/io/trino/execution/CreateViewTask.java +++ b/core/trino-main/src/main/java/io/trino/execution/CreateViewTask.java @@ -15,17 +15,15 @@ import com.google.common.util.concurrent.ListenableFuture; import io.trino.Session; -import io.trino.cost.StatsCalculator; import io.trino.execution.warnings.WarningCollector; import io.trino.metadata.Metadata; import io.trino.metadata.QualifiedObjectName; import io.trino.metadata.ViewColumn; import io.trino.metadata.ViewDefinition; import io.trino.security.AccessControl; -import io.trino.spi.security.GroupProvider; import io.trino.spi.security.Identity; import io.trino.sql.analyzer.Analysis; -import io.trino.sql.analyzer.Analyzer; +import io.trino.sql.analyzer.AnalyzerFactory; import io.trino.sql.parser.SqlParser; import io.trino.sql.tree.CreateView; import io.trino.sql.tree.Expression; @@ -49,17 +47,15 @@ public class CreateViewTask private final Metadata metadata; private final AccessControl accessControl; private final SqlParser sqlParser; - private final GroupProvider groupProvider; - private final StatsCalculator statsCalculator; + private final AnalyzerFactory analyzerFactory; @Inject - public CreateViewTask(Metadata metadata, AccessControl accessControl, SqlParser sqlParser, GroupProvider groupProvider, StatsCalculator statsCalculator) + public CreateViewTask(Metadata metadata, AccessControl accessControl, SqlParser sqlParser, AnalyzerFactory analyzerFactory) { this.metadata = requireNonNull(metadata, "metadata is null"); this.accessControl = requireNonNull(accessControl, "accessControl is null"); this.sqlParser = requireNonNull(sqlParser, "sqlParser is null"); - this.groupProvider = requireNonNull(groupProvider, "groupProvider is null"); - this.statsCalculator = requireNonNull(statsCalculator, "statsCalculator is null"); + this.analyzerFactory = requireNonNull(analyzerFactory, "analyzerFactory is null"); } @Override @@ -82,7 +78,7 @@ public ListenableFuture execute( String sql = getFormattedSql(statement.getQuery(), sqlParser); - Analysis analysis = new Analyzer(session, metadata, sqlParser, groupProvider, accessControl, Optional.empty(), parameters, parameterExtractor(statement, parameters), stateMachine.getWarningCollector(), statsCalculator) + Analysis analysis = analyzerFactory.createAnalyzer(session, parameters, parameterExtractor(statement, parameters), stateMachine.getWarningCollector()) .analyze(statement); List columns = analysis.getOutputDescriptor(statement.getQuery()) diff --git a/core/trino-main/src/main/java/io/trino/execution/SetTimeZoneTask.java b/core/trino-main/src/main/java/io/trino/execution/SetTimeZoneTask.java index d4e3bf5db620..e75bb177dcdb 100644 --- a/core/trino-main/src/main/java/io/trino/execution/SetTimeZoneTask.java +++ b/core/trino-main/src/main/java/io/trino/execution/SetTimeZoneTask.java @@ -17,7 +17,6 @@ import com.google.common.util.concurrent.ListenableFuture; import io.airlift.slice.Slice; import io.trino.Session; -import io.trino.cost.StatsCalculator; import io.trino.execution.warnings.WarningCollector; import io.trino.metadata.Metadata; import io.trino.metadata.ResolvedFunction; @@ -28,7 +27,7 @@ import io.trino.spi.type.Type; import io.trino.spi.type.VarcharType; import io.trino.sql.analyzer.Analysis; -import io.trino.sql.analyzer.Analyzer; +import io.trino.sql.analyzer.AnalyzerFactory; import io.trino.sql.analyzer.CorrelationSupport; import io.trino.sql.analyzer.ExpressionAnalysis; import io.trino.sql.analyzer.ExpressionAnalyzer; @@ -49,7 +48,6 @@ import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.TimeZone; import static com.google.common.base.Preconditions.checkArgument; @@ -70,17 +68,17 @@ public class SetTimeZoneTask private final Metadata metadata; private final AccessControl accessControl; private final SqlParser sqlParser; + private final AnalyzerFactory analyzerFactory; private final GroupProvider groupProvider; - private final StatsCalculator statsCalculator; @Inject - public SetTimeZoneTask(Metadata metadata, AccessControl accessControl, SqlParser sqlParser, GroupProvider groupProvider, StatsCalculator statsCalculator) + public SetTimeZoneTask(Metadata metadata, AccessControl accessControl, SqlParser sqlParser, AnalyzerFactory analyzerFactory, GroupProvider groupProvider) { this.metadata = requireNonNull(metadata, "metadata is null"); this.accessControl = requireNonNull(accessControl, "accessControl is null"); this.sqlParser = requireNonNull(sqlParser, "sqlParser is null"); + this.analyzerFactory = requireNonNull(analyzerFactory, "analyzerFactory is null"); this.groupProvider = requireNonNull(groupProvider, "groupProvider is null"); - this.statsCalculator = requireNonNull(statsCalculator, "statsCalculator is null"); } @Override @@ -112,7 +110,7 @@ private String getTimeZoneId( WarningCollector warningCollector) { Session session = stateMachine.getSession(); - Analysis analysis = analyzeStatement(statement, metadata, accessControl, stateMachine, parameters, session); + Analysis analysis = analyzeStatement(statement, stateMachine, parameters, session); Scope scope = Scope.builder() .withRelationType(RelationId.anonymous(), new RelationType()) .build(); @@ -154,23 +152,15 @@ else if (timeZoneValue instanceof Long) { private Analysis analyzeStatement( SetTimeZone statement, - Metadata metadata, - AccessControl accessControl, QueryStateMachine stateMachine, List parameters, Session session) { - return new Analyzer( + return analyzerFactory.createAnalyzer( session, - metadata, - sqlParser, - groupProvider, - accessControl, - Optional.empty(), parameters, parameterExtractor(statement, parameters), - stateMachine.getWarningCollector(), - statsCalculator) + stateMachine.getWarningCollector()) .analyze(statement); } diff --git a/core/trino-main/src/main/java/io/trino/execution/SqlQueryExecution.java b/core/trino-main/src/main/java/io/trino/execution/SqlQueryExecution.java index 80d26e94502f..b9e706c79c0f 100644 --- a/core/trino-main/src/main/java/io/trino/execution/SqlQueryExecution.java +++ b/core/trino-main/src/main/java/io/trino/execution/SqlQueryExecution.java @@ -37,20 +37,17 @@ import io.trino.metadata.Metadata; import io.trino.metadata.TableHandle; import io.trino.operator.ForScheduler; -import io.trino.security.AccessControl; import io.trino.server.BasicQueryInfo; import io.trino.server.DynamicFilterService; import io.trino.server.protocol.Slug; import io.trino.spi.QueryId; import io.trino.spi.TrinoException; -import io.trino.spi.security.GroupProvider; import io.trino.spi.type.TypeOperators; import io.trino.split.SplitManager; import io.trino.split.SplitSource; import io.trino.sql.analyzer.Analysis; import io.trino.sql.analyzer.Analyzer; -import io.trino.sql.analyzer.QueryExplainer; -import io.trino.sql.parser.SqlParser; +import io.trino.sql.analyzer.AnalyzerFactory; import io.trino.sql.planner.DistributedExecutionPlanner; import io.trino.sql.planner.InputExtractor; import io.trino.sql.planner.LogicalPlanner; @@ -140,9 +137,7 @@ private SqlQueryExecution( Slug slug, Metadata metadata, TypeOperators typeOperators, - GroupProvider groupProvider, - AccessControl accessControl, - SqlParser sqlParser, + AnalyzerFactory analyzerFactory, SplitManager splitManager, NodePartitioningManager nodePartitioningManager, NodeScheduler nodeScheduler, @@ -154,7 +149,6 @@ private SqlQueryExecution( ScheduledExecutorService schedulerExecutor, FailureDetector failureDetector, NodeTaskMap nodeTaskMap, - QueryExplainer queryExplainer, ExecutionPolicy executionPolicy, SplitSchedulerStats schedulerStats, StatsCalculator statsCalculator, @@ -190,7 +184,7 @@ private SqlQueryExecution( this.stateMachine = requireNonNull(stateMachine, "stateMachine is null"); // analyze query - this.analysis = analyze(preparedQuery, stateMachine, metadata, groupProvider, accessControl, sqlParser, queryExplainer, warningCollector); + this.analysis = analyze(preparedQuery, stateMachine, warningCollector, analyzerFactory); stateMachine.addStateChangeListener(state -> { if (!state.isDone()) { @@ -246,30 +240,20 @@ private synchronized void unregisterDynamicFilteringQuery(DynamicFiltersStats fi dynamicFilterService.removeQuery(stateMachine.getQueryId()); } - private Analysis analyze( + private static Analysis analyze( PreparedQuery preparedQuery, QueryStateMachine stateMachine, - Metadata metadata, - GroupProvider groupProvider, - AccessControl accessControl, - SqlParser sqlParser, - QueryExplainer queryExplainer, - WarningCollector warningCollector) + WarningCollector warningCollector, + AnalyzerFactory analyzerFactory) { stateMachine.beginAnalysis(); requireNonNull(preparedQuery, "preparedQuery is null"); - Analyzer analyzer = new Analyzer( + Analyzer analyzer = analyzerFactory.createAnalyzer( stateMachine.getSession(), - metadata, - sqlParser, - groupProvider, - accessControl, - Optional.of(queryExplainer), preparedQuery.getParameters(), parameterExtractor(preparedQuery.getStatement(), preparedQuery.getParameters()), - warningCollector, - statsCalculator); + warningCollector); Analysis analysis; try { analysis = analyzer.analyze(preparedQuery.getStatement()); @@ -732,16 +716,13 @@ public static class SqlQueryExecutionFactory private final int scheduleSplitBatchSize; private final Metadata metadata; private final TypeOperators typeOperators; - private final GroupProvider groupProvider; - private final AccessControl accessControl; - private final SqlParser sqlParser; + private final AnalyzerFactory analyzerFactory; private final SplitManager splitManager; private final NodePartitioningManager nodePartitioningManager; private final NodeScheduler nodeScheduler; private final List planOptimizers; private final PlanFragmenter planFragmenter; private final RemoteTaskFactory remoteTaskFactory; - private final QueryExplainer queryExplainer; private final ExecutorService queryExecutor; private final ScheduledExecutorService schedulerExecutor; private final FailureDetector failureDetector; @@ -758,9 +739,7 @@ public static class SqlQueryExecutionFactory QueryManagerConfig config, Metadata metadata, TypeOperators typeOperators, - GroupProvider groupProvider, - AccessControl accessControl, - SqlParser sqlParser, + AnalyzerFactory analyzerFactory, SplitManager splitManager, NodePartitioningManager nodePartitioningManager, NodeScheduler nodeScheduler, @@ -771,7 +750,6 @@ public static class SqlQueryExecutionFactory @ForScheduler ScheduledExecutorService schedulerExecutor, FailureDetector failureDetector, NodeTaskMap nodeTaskMap, - QueryExplainer queryExplainer, Map executionPolicies, SplitSchedulerStats schedulerStats, StatsCalculator statsCalculator, @@ -785,9 +763,7 @@ public static class SqlQueryExecutionFactory this.scheduleSplitBatchSize = config.getScheduleSplitBatchSize(); this.metadata = requireNonNull(metadata, "metadata is null"); this.typeOperators = requireNonNull(typeOperators, "typeOperators is null"); - this.groupProvider = requireNonNull(groupProvider, "groupProvider is null"); - this.accessControl = requireNonNull(accessControl, "accessControl is null"); - this.sqlParser = requireNonNull(sqlParser, "sqlParser is null"); + this.analyzerFactory = requireNonNull(analyzerFactory, "analyzerFactory is null"); this.splitManager = requireNonNull(splitManager, "splitManager is null"); this.nodePartitioningManager = requireNonNull(nodePartitioningManager, "nodePartitioningManager is null"); this.nodeScheduler = requireNonNull(nodeScheduler, "nodeScheduler is null"); @@ -797,7 +773,6 @@ public static class SqlQueryExecutionFactory this.schedulerExecutor = requireNonNull(schedulerExecutor, "schedulerExecutor is null"); this.failureDetector = requireNonNull(failureDetector, "failureDetector is null"); this.nodeTaskMap = requireNonNull(nodeTaskMap, "nodeTaskMap is null"); - this.queryExplainer = requireNonNull(queryExplainer, "queryExplainer is null"); this.executionPolicies = requireNonNull(executionPolicies, "executionPolicies is null"); this.planOptimizers = requireNonNull(planOptimizersFactory, "planOptimizersFactory is null").get(); this.statsCalculator = requireNonNull(statsCalculator, "statsCalculator is null"); @@ -824,9 +799,7 @@ public QueryExecution createQueryExecution( slug, metadata, typeOperators, - groupProvider, - accessControl, - sqlParser, + analyzerFactory, splitManager, nodePartitioningManager, nodeScheduler, @@ -838,7 +811,6 @@ public QueryExecution createQueryExecution( schedulerExecutor, failureDetector, nodeTaskMap, - queryExplainer, executionPolicy, schedulerStats, statsCalculator, diff --git a/core/trino-main/src/main/java/io/trino/server/CoordinatorModule.java b/core/trino-main/src/main/java/io/trino/server/CoordinatorModule.java index 01d61dc02c8a..427cc4487c5d 100644 --- a/core/trino-main/src/main/java/io/trino/server/CoordinatorModule.java +++ b/core/trino-main/src/main/java/io/trino/server/CoordinatorModule.java @@ -18,6 +18,7 @@ import com.google.inject.Provides; import com.google.inject.Scopes; import com.google.inject.multibindings.MapBinder; +import com.google.inject.multibindings.Multibinder; import io.airlift.concurrent.BoundedExecutor; import io.airlift.configuration.AbstractConfigurationAwareModule; import io.airlift.http.server.HttpServerConfig; @@ -82,12 +83,20 @@ import io.trino.server.ui.WorkerResource; import io.trino.spi.VersionEmbedder; import io.trino.spi.memory.ClusterMemoryPoolManager; -import io.trino.sql.analyzer.QueryExplainer; +import io.trino.sql.analyzer.AnalyzerFactory; +import io.trino.sql.analyzer.QueryExplainerFactory; import io.trino.sql.planner.OptimizerStatsMBeanExporter; import io.trino.sql.planner.PlanFragmenter; import io.trino.sql.planner.PlanOptimizers; import io.trino.sql.planner.PlanOptimizersFactory; import io.trino.sql.planner.RuleStatsRecorder; +import io.trino.sql.rewrite.DescribeInputRewrite; +import io.trino.sql.rewrite.DescribeOutputRewrite; +import io.trino.sql.rewrite.ExplainRewrite; +import io.trino.sql.rewrite.ShowQueriesRewrite; +import io.trino.sql.rewrite.ShowStatsRewrite; +import io.trino.sql.rewrite.StatementRewrite; +import io.trino.sql.rewrite.StatementRewrite.Rewrite; import io.trino.transaction.ForTransactionManager; import io.trino.transaction.InMemoryTransactionManager; import io.trino.transaction.TransactionManager; @@ -102,6 +111,7 @@ import java.util.concurrent.ScheduledExecutorService; import static com.google.inject.multibindings.MapBinder.newMapBinder; +import static com.google.inject.multibindings.Multibinder.newSetBinder; import static com.google.inject.multibindings.OptionalBinder.newOptionalBinder; import static io.airlift.concurrent.Threads.daemonThreadsNamed; import static io.airlift.concurrent.Threads.threadsNamed; @@ -210,6 +220,18 @@ protected void setup(Binder binder) // dynamic filtering service binder.bind(DynamicFilterService.class).in(Scopes.SINGLETON); + // analyzer + binder.bind(AnalyzerFactory.class).in(Scopes.SINGLETON); + + // statement rewriter + binder.bind(StatementRewrite.class).in(Scopes.SINGLETON); + Multibinder rewriteBinder = newSetBinder(binder, Rewrite.class); + rewriteBinder.addBinding().to(DescribeInputRewrite.class).in(Scopes.SINGLETON); + rewriteBinder.addBinding().to(DescribeOutputRewrite.class).in(Scopes.SINGLETON); + rewriteBinder.addBinding().to(ShowQueriesRewrite.class).in(Scopes.SINGLETON); + rewriteBinder.addBinding().to(ShowStatsRewrite.class).in(Scopes.SINGLETON); + rewriteBinder.addBinding().to(ExplainRewrite.class).in(Scopes.SINGLETON); + // planner binder.bind(PlanFragmenter.class).in(Scopes.SINGLETON); newOptionalBinder(binder, PlanOptimizersFactory.class) @@ -220,7 +242,7 @@ protected void setup(Binder binder) binder.bind(OptimizerStatsMBeanExporter.class).in(Scopes.SINGLETON); // query explainer - binder.bind(QueryExplainer.class).in(Scopes.SINGLETON); + binder.bind(QueryExplainerFactory.class).in(Scopes.SINGLETON); // explain analyze binder.bind(ExplainAnalyzeContext.class).in(Scopes.SINGLETON); diff --git a/core/trino-main/src/main/java/io/trino/server/testing/TestingTrinoServer.java b/core/trino-main/src/main/java/io/trino/server/testing/TestingTrinoServer.java index 8dceaeac2795..654c34e450db 100644 --- a/core/trino-main/src/main/java/io/trino/server/testing/TestingTrinoServer.java +++ b/core/trino-main/src/main/java/io/trino/server/testing/TestingTrinoServer.java @@ -75,6 +75,7 @@ import io.trino.spi.security.SystemAccessControl; import io.trino.split.PageSourceManager; import io.trino.split.SplitManager; +import io.trino.sql.analyzer.AnalyzerFactory; import io.trino.sql.planner.NodePartitioningManager; import io.trino.sql.planner.Plan; import io.trino.testing.ProcedureTester; @@ -140,6 +141,7 @@ public static Builder builder() private final CatalogManager catalogManager; private final TransactionManager transactionManager; private final Metadata metadata; + private final AnalyzerFactory analyzerFactory; private final StatsCalculator statsCalculator; private final TestingAccessControlManager accessControl; private final TestingGroupProvider groupProvider; @@ -293,6 +295,7 @@ private TestingTrinoServer( splitManager = injector.getInstance(SplitManager.class); pageSourceManager = injector.getInstance(PageSourceManager.class); if (coordinator) { + analyzerFactory = injector.getInstance(AnalyzerFactory.class); dispatchManager = injector.getInstance(DispatchManager.class); queryManager = (SqlQueryManager) injector.getInstance(QueryManager.class); resourceGroupManager = Optional.of((InternalResourceGroupManager) injector.getInstance(InternalResourceGroupManager.class)); @@ -303,6 +306,7 @@ private TestingTrinoServer( injector.getInstance(CertificateAuthenticatorManager.class).useDefaultAuthenticator(); } else { + analyzerFactory = null; dispatchManager = null; queryManager = null; resourceGroupManager = Optional.empty(); @@ -437,6 +441,11 @@ public Metadata getMetadata() return metadata; } + public AnalyzerFactory getAnalyzerFactory() + { + return analyzerFactory; + } + public StatsCalculator getStatsCalculator() { checkState(coordinator, "not a coordinator"); diff --git a/core/trino-main/src/main/java/io/trino/sql/analyzer/Analyzer.java b/core/trino-main/src/main/java/io/trino/sql/analyzer/Analyzer.java index 72d034bed3f6..b2b68ec7e894 100644 --- a/core/trino-main/src/main/java/io/trino/sql/analyzer/Analyzer.java +++ b/core/trino-main/src/main/java/io/trino/sql/analyzer/Analyzer.java @@ -16,7 +16,6 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; import io.trino.Session; -import io.trino.cost.StatsCalculator; import io.trino.execution.warnings.WarningCollector; import io.trino.metadata.Metadata; import io.trino.security.AccessControl; @@ -46,37 +45,37 @@ public class Analyzer { private final Metadata metadata; private final SqlParser sqlParser; + private final AnalyzerFactory analyzerFactory; private final AccessControl accessControl; private final GroupProvider groupProvider; private final Session session; - private final Optional queryExplainer; private final List parameters; private final Map, Expression> parameterLookup; private final WarningCollector warningCollector; - private final StatsCalculator statsCalculator; + private final StatementRewrite statementRewrite; - public Analyzer( + Analyzer( Session session, Metadata metadata, SqlParser sqlParser, + AnalyzerFactory analyzerFactory, GroupProvider groupProvider, AccessControl accessControl, - Optional queryExplainer, List parameters, Map, Expression> parameterLookup, WarningCollector warningCollector, - StatsCalculator statsCalculator) + StatementRewrite statementRewrite) { this.session = requireNonNull(session, "session is null"); this.metadata = requireNonNull(metadata, "metadata is null"); this.sqlParser = requireNonNull(sqlParser, "sqlParser is null"); + this.analyzerFactory = requireNonNull(analyzerFactory, "analyzerFactory is null"); this.groupProvider = requireNonNull(groupProvider, "groupProvider is null"); this.accessControl = requireNonNull(accessControl, "accessControl is null"); - this.queryExplainer = requireNonNull(queryExplainer, "queryExplainer is null"); this.parameters = parameters; this.parameterLookup = parameterLookup; this.warningCollector = requireNonNull(warningCollector, "warningCollector is null"); - this.statsCalculator = requireNonNull(statsCalculator, "statsCalculator is null"); + this.statementRewrite = requireNonNull(statementRewrite, "statementRewrite is null"); } public Analysis analyze(Statement statement) @@ -86,7 +85,7 @@ public Analysis analyze(Statement statement) public Analysis analyze(Statement statement, QueryType queryType) { - Statement rewrittenStatement = StatementRewrite.rewrite(session, metadata, sqlParser, queryExplainer, statement, parameters, parameterLookup, groupProvider, accessControl, warningCollector, statsCalculator); + Statement rewrittenStatement = statementRewrite.rewrite(analyzerFactory, session, statement, parameters, parameterLookup, warningCollector); Analysis analysis = new Analysis(rewrittenStatement, parameterLookup, queryType); StatementAnalyzer analyzer = new StatementAnalyzer(analysis, metadata, sqlParser, groupProvider, accessControl, session, warningCollector, CorrelationSupport.ALLOWED); analyzer.analyze(rewrittenStatement, Optional.empty()); diff --git a/core/trino-main/src/main/java/io/trino/sql/analyzer/AnalyzerFactory.java b/core/trino-main/src/main/java/io/trino/sql/analyzer/AnalyzerFactory.java new file mode 100644 index 000000000000..a5043b5dbde0 --- /dev/null +++ b/core/trino-main/src/main/java/io/trino/sql/analyzer/AnalyzerFactory.java @@ -0,0 +1,75 @@ +/* + * 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 io.trino.sql.analyzer; + +import io.trino.Session; +import io.trino.execution.warnings.WarningCollector; +import io.trino.metadata.Metadata; +import io.trino.security.AccessControl; +import io.trino.spi.security.GroupProvider; +import io.trino.sql.parser.SqlParser; +import io.trino.sql.rewrite.StatementRewrite; +import io.trino.sql.tree.Expression; +import io.trino.sql.tree.NodeRef; +import io.trino.sql.tree.Parameter; + +import javax.inject.Inject; + +import java.util.List; +import java.util.Map; + +import static java.util.Objects.requireNonNull; + +public class AnalyzerFactory +{ + private final Metadata metadata; + private final SqlParser sqlParser; + private final AccessControl accessControl; + private final GroupProvider groupProvider; + private final StatementRewrite statementRewrite; + + @Inject + public AnalyzerFactory( + Metadata metadata, + SqlParser sqlParser, + AccessControl accessControl, + GroupProvider groupProvider, + StatementRewrite statementRewrite) + { + this.metadata = requireNonNull(metadata, "metadata is null"); + this.sqlParser = requireNonNull(sqlParser, "sqlParser is null"); + this.accessControl = requireNonNull(accessControl, "accessControl is null"); + this.groupProvider = requireNonNull(groupProvider, "groupProvider is null"); + this.statementRewrite = requireNonNull(statementRewrite, "statementRewrite is null"); + } + + public Analyzer createAnalyzer( + Session session, + List parameters, + Map, Expression> parameterLookup, + WarningCollector warningCollector) + { + return new Analyzer( + session, + metadata, + sqlParser, + this, + groupProvider, + accessControl, + parameters, + parameterLookup, + warningCollector, + statementRewrite); + } +} diff --git a/core/trino-main/src/main/java/io/trino/sql/analyzer/QueryExplainer.java b/core/trino-main/src/main/java/io/trino/sql/analyzer/QueryExplainer.java index 67b72cfb7abf..d9d52eead871 100644 --- a/core/trino-main/src/main/java/io/trino/sql/analyzer/QueryExplainer.java +++ b/core/trino-main/src/main/java/io/trino/sql/analyzer/QueryExplainer.java @@ -18,9 +18,7 @@ import io.trino.cost.StatsCalculator; import io.trino.execution.warnings.WarningCollector; import io.trino.metadata.Metadata; -import io.trino.security.AccessControl; import io.trino.spi.TrinoException; -import io.trino.spi.security.GroupProvider; import io.trino.spi.type.TypeOperators; import io.trino.sql.SqlFormatter; import io.trino.sql.parser.SqlParser; @@ -43,8 +41,6 @@ import io.trino.sql.tree.Prepare; import io.trino.sql.tree.Statement; -import javax.inject.Inject; - import java.util.List; import java.util.Optional; @@ -63,62 +59,34 @@ public class QueryExplainer private final PlanFragmenter planFragmenter; private final Metadata metadata; private final TypeOperators typeOperators; - private final GroupProvider groupProvider; - private final AccessControl accessControl; private final SqlParser sqlParser; + private final AnalyzerFactory analyzerFactory; private final StatsCalculator statsCalculator; private final CostCalculator costCalculator; - @Inject - public QueryExplainer( + QueryExplainer( PlanOptimizersFactory planOptimizersFactory, PlanFragmenter planFragmenter, Metadata metadata, TypeOperators typeOperators, - GroupProvider groupProvider, - AccessControl accessControl, - SqlParser sqlParser, - StatsCalculator statsCalculator, - CostCalculator costCalculator) - { - this( - planOptimizersFactory.get(), - planFragmenter, - metadata, - typeOperators, - groupProvider, - accessControl, - sqlParser, - statsCalculator, - costCalculator); - } - - public QueryExplainer( - List planOptimizers, - PlanFragmenter planFragmenter, - Metadata metadata, - TypeOperators typeOperators, - GroupProvider groupProvider, - AccessControl accessControl, SqlParser sqlParser, + AnalyzerFactory analyzerFactory, StatsCalculator statsCalculator, CostCalculator costCalculator) { - this.planOptimizers = requireNonNull(planOptimizers, "planOptimizers is null"); + this.planOptimizers = requireNonNull(planOptimizersFactory.get(), "planOptimizers is null"); this.planFragmenter = requireNonNull(planFragmenter, "planFragmenter is null"); this.metadata = requireNonNull(metadata, "metadata is null"); this.typeOperators = requireNonNull(typeOperators, "typeOperators is null"); - this.groupProvider = requireNonNull(groupProvider, "groupProvider is null"); - this.accessControl = requireNonNull(accessControl, "accessControl is null"); this.sqlParser = requireNonNull(sqlParser, "sqlParser is null"); + this.analyzerFactory = requireNonNull(analyzerFactory, "analyzerFactory is null"); this.statsCalculator = requireNonNull(statsCalculator, "statsCalculator is null"); this.costCalculator = requireNonNull(costCalculator, "costCalculator is null"); } - public Analysis analyze(Session session, Statement statement, List parameters, WarningCollector warningCollector) + public void validate(Session session, Statement statement, List parameters, WarningCollector warningCollector) { - Analyzer analyzer = new Analyzer(session, metadata, sqlParser, groupProvider, accessControl, Optional.of(this), parameters, parameterExtractor(statement, parameters), warningCollector, statsCalculator); - return analyzer.analyze(statement, EXPLAIN); + analyze(session, statement, parameters, warningCollector); } public String getPlan(Session session, Statement statement, Type planType, List parameters, WarningCollector warningCollector) @@ -208,6 +176,12 @@ public Plan getLogicalPlan(Session session, Statement statement, List parameters, WarningCollector warningCollector) + { + Analyzer analyzer = analyzerFactory.createAnalyzer(session, parameters, parameterExtractor(statement, parameters), warningCollector); + return analyzer.analyze(statement, EXPLAIN); + } + private SubPlan getDistributedPlan(Session session, Statement statement, List parameters, WarningCollector warningCollector) { Plan plan = getLogicalPlan(session, statement, parameters, warningCollector); diff --git a/core/trino-main/src/main/java/io/trino/sql/analyzer/QueryExplainerFactory.java b/core/trino-main/src/main/java/io/trino/sql/analyzer/QueryExplainerFactory.java new file mode 100644 index 000000000000..de7c05f2ac36 --- /dev/null +++ b/core/trino-main/src/main/java/io/trino/sql/analyzer/QueryExplainerFactory.java @@ -0,0 +1,69 @@ +/* + * 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 io.trino.sql.analyzer; + +import io.trino.cost.CostCalculator; +import io.trino.cost.StatsCalculator; +import io.trino.metadata.Metadata; +import io.trino.spi.type.TypeOperators; +import io.trino.sql.parser.SqlParser; +import io.trino.sql.planner.PlanFragmenter; +import io.trino.sql.planner.PlanOptimizersFactory; + +import javax.inject.Inject; + +import static java.util.Objects.requireNonNull; + +public class QueryExplainerFactory +{ + private final PlanOptimizersFactory planOptimizersFactory; + private final PlanFragmenter planFragmenter; + private final Metadata metadata; + private final TypeOperators typeOperators; + private final SqlParser sqlParser; + private final StatsCalculator statsCalculator; + private final CostCalculator costCalculator; + + @Inject + public QueryExplainerFactory( + PlanOptimizersFactory planOptimizersFactory, + PlanFragmenter planFragmenter, + Metadata metadata, + TypeOperators typeOperators, + SqlParser sqlParser, + StatsCalculator statsCalculator, + CostCalculator costCalculator) + { + this.planOptimizersFactory = requireNonNull(planOptimizersFactory, "planOptimizersFactory is null"); + this.planFragmenter = requireNonNull(planFragmenter, "planFragmenter is null"); + this.metadata = requireNonNull(metadata, "metadata is null"); + this.typeOperators = requireNonNull(typeOperators, "typeOperators is null"); + this.sqlParser = requireNonNull(sqlParser, "sqlParser is null"); + this.statsCalculator = requireNonNull(statsCalculator, "statsCalculator is null"); + this.costCalculator = requireNonNull(costCalculator, "costCalculator is null"); + } + + public QueryExplainer createQueryExplainer(AnalyzerFactory analyzerFactory) + { + return new QueryExplainer( + planOptimizersFactory, + planFragmenter, + metadata, + typeOperators, + sqlParser, + analyzerFactory, + statsCalculator, + costCalculator); + } +} diff --git a/core/trino-main/src/main/java/io/trino/sql/planner/PlanOptimizersFactory.java b/core/trino-main/src/main/java/io/trino/sql/planner/PlanOptimizersFactory.java index b7fb0e017dee..b25870547499 100644 --- a/core/trino-main/src/main/java/io/trino/sql/planner/PlanOptimizersFactory.java +++ b/core/trino-main/src/main/java/io/trino/sql/planner/PlanOptimizersFactory.java @@ -13,6 +13,7 @@ */ package io.trino.sql.planner; +import com.google.common.collect.ImmutableMap; import io.trino.sql.planner.iterative.RuleStats; import io.trino.sql.planner.optimizations.OptimizerStats; import io.trino.sql.planner.optimizations.PlanOptimizer; @@ -24,7 +25,13 @@ public interface PlanOptimizersFactory { List get(); - Map, OptimizerStats> getOptimizerStats(); + default Map, OptimizerStats> getOptimizerStats() + { + return ImmutableMap.of(); + } - Map, RuleStats> getRuleStats(); + default Map, RuleStats> getRuleStats() + { + return ImmutableMap.of(); + } } diff --git a/core/trino-main/src/main/java/io/trino/sql/rewrite/DescribeInputRewrite.java b/core/trino-main/src/main/java/io/trino/sql/rewrite/DescribeInputRewrite.java index 80a73808ac63..52ae3ad9a630 100644 --- a/core/trino-main/src/main/java/io/trino/sql/rewrite/DescribeInputRewrite.java +++ b/core/trino-main/src/main/java/io/trino/sql/rewrite/DescribeInputRewrite.java @@ -15,15 +15,11 @@ import com.google.common.collect.ImmutableList; import io.trino.Session; -import io.trino.cost.StatsCalculator; import io.trino.execution.warnings.WarningCollector; -import io.trino.metadata.Metadata; -import io.trino.security.AccessControl; -import io.trino.spi.security.GroupProvider; import io.trino.spi.type.Type; import io.trino.sql.analyzer.Analysis; import io.trino.sql.analyzer.Analyzer; -import io.trino.sql.analyzer.QueryExplainer; +import io.trino.sql.analyzer.AnalyzerFactory; import io.trino.sql.parser.SqlParser; import io.trino.sql.tree.AstVisitor; import io.trino.sql.tree.DescribeInput; @@ -38,6 +34,8 @@ import io.trino.sql.tree.Statement; import io.trino.sql.tree.StringLiteral; +import javax.inject.Inject; + import java.util.List; import java.util.Map; import java.util.Optional; @@ -58,24 +56,27 @@ import static io.trino.type.UnknownType.UNKNOWN; import static java.util.Objects.requireNonNull; -final class DescribeInputRewrite +public final class DescribeInputRewrite implements StatementRewrite.Rewrite { + private final SqlParser parser; + + @Inject + public DescribeInputRewrite(SqlParser parser) + { + this.parser = requireNonNull(parser, "parser is null"); + } + @Override public Statement rewrite( + AnalyzerFactory analyzerFactory, Session session, - Metadata metadata, - SqlParser parser, - Optional queryExplainer, Statement node, List parameters, Map, Expression> parameterLookup, - GroupProvider groupProvider, - AccessControl accessControl, - WarningCollector warningCollector, - StatsCalculator statsCalculator) + WarningCollector warningCollector) { - return (Statement) new Visitor(session, parser, metadata, queryExplainer, parameters, parameterLookup, groupProvider, accessControl, warningCollector, statsCalculator).process(node, null); + return (Statement) new Visitor(session, parser, analyzerFactory, parameters, parameterLookup, warningCollector).process(node, null); } private static final class Visitor @@ -83,37 +84,25 @@ private static final class Visitor { private final Session session; private final SqlParser parser; - private final Metadata metadata; - private final Optional queryExplainer; + private final AnalyzerFactory analyzerFactory; private final List parameters; private final Map, Expression> parameterLookup; - private final GroupProvider groupProvider; - private final AccessControl accessControl; private final WarningCollector warningCollector; - private final StatsCalculator statsCalculator; public Visitor( Session session, SqlParser parser, - Metadata metadata, - Optional queryExplainer, + AnalyzerFactory analyzerFactory, List parameters, Map, Expression> parameterLookup, - GroupProvider groupProvider, - AccessControl accessControl, - WarningCollector warningCollector, - StatsCalculator statsCalculator) + WarningCollector warningCollector) { this.session = requireNonNull(session, "session is null"); - this.parser = parser; - this.metadata = metadata; - this.queryExplainer = queryExplainer; - this.groupProvider = requireNonNull(groupProvider, "groupProvider is null"); - this.accessControl = accessControl; + this.parser = requireNonNull(parser, "parser is null"); + this.analyzerFactory = requireNonNull(analyzerFactory, "analyzerFactory is null"); this.parameters = parameters; this.parameterLookup = parameterLookup; this.warningCollector = requireNonNull(warningCollector, "warningCollector is null"); - this.statsCalculator = requireNonNull(statsCalculator, "statsCalculator is null"); } @Override @@ -123,7 +112,7 @@ protected Node visitDescribeInput(DescribeInput node, Void context) Statement statement = parser.createStatement(sqlString, createParsingOptions(session)); // create analysis for the query we are describing. - Analyzer analyzer = new Analyzer(session, metadata, parser, groupProvider, accessControl, queryExplainer, parameters, parameterLookup, warningCollector, statsCalculator); + Analyzer analyzer = analyzerFactory.createAnalyzer(session, parameters, parameterLookup, warningCollector); Analysis analysis = analyzer.analyze(statement, DESCRIBE); // get all parameters in query diff --git a/core/trino-main/src/main/java/io/trino/sql/rewrite/DescribeOutputRewrite.java b/core/trino-main/src/main/java/io/trino/sql/rewrite/DescribeOutputRewrite.java index 99ebfc6d3871..46dd3d379384 100644 --- a/core/trino-main/src/main/java/io/trino/sql/rewrite/DescribeOutputRewrite.java +++ b/core/trino-main/src/main/java/io/trino/sql/rewrite/DescribeOutputRewrite.java @@ -15,17 +15,13 @@ import com.google.common.collect.ImmutableList; import io.trino.Session; -import io.trino.cost.StatsCalculator; import io.trino.execution.warnings.WarningCollector; -import io.trino.metadata.Metadata; import io.trino.metadata.QualifiedObjectName; -import io.trino.security.AccessControl; -import io.trino.spi.security.GroupProvider; import io.trino.spi.type.FixedWidthType; import io.trino.sql.analyzer.Analysis; import io.trino.sql.analyzer.Analyzer; +import io.trino.sql.analyzer.AnalyzerFactory; import io.trino.sql.analyzer.Field; -import io.trino.sql.analyzer.QueryExplainer; import io.trino.sql.parser.SqlParser; import io.trino.sql.tree.AstVisitor; import io.trino.sql.tree.BooleanLiteral; @@ -41,6 +37,8 @@ import io.trino.sql.tree.Statement; import io.trino.sql.tree.StringLiteral; +import javax.inject.Inject; + import java.util.List; import java.util.Map; import java.util.Optional; @@ -57,24 +55,27 @@ import static io.trino.type.TypeUtils.getDisplayLabel; import static java.util.Objects.requireNonNull; -final class DescribeOutputRewrite +public final class DescribeOutputRewrite implements StatementRewrite.Rewrite { + private final SqlParser parser; + + @Inject + public DescribeOutputRewrite(SqlParser parser) + { + this.parser = requireNonNull(parser, "parser is null"); + } + @Override public Statement rewrite( + AnalyzerFactory analyzerFactory, Session session, - Metadata metadata, - SqlParser parser, - Optional queryExplainer, Statement node, List parameters, Map, Expression> parameterLookup, - GroupProvider groupProvider, - AccessControl accessControl, - WarningCollector warningCollector, - StatsCalculator statsCalculator) + WarningCollector warningCollector) { - return (Statement) new Visitor(session, parser, metadata, queryExplainer, parameters, parameterLookup, groupProvider, accessControl, warningCollector, statsCalculator).process(node, null); + return (Statement) new Visitor(session, parser, analyzerFactory, parameters, parameterLookup, warningCollector).process(node, null); } private static final class Visitor @@ -82,37 +83,25 @@ private static final class Visitor { private final Session session; private final SqlParser parser; - private final Metadata metadata; - private final Optional queryExplainer; + private final AnalyzerFactory analyzerFactory; private final List parameters; private final Map, Expression> parameterLookup; - private final GroupProvider groupProvider; - private final AccessControl accessControl; private final WarningCollector warningCollector; - private final StatsCalculator statsCalculator; public Visitor( Session session, SqlParser parser, - Metadata metadata, - Optional queryExplainer, + AnalyzerFactory analyzerFactory, List parameters, Map, Expression> parameterLookup, - GroupProvider groupProvider, - AccessControl accessControl, - WarningCollector warningCollector, - StatsCalculator statsCalculator) + WarningCollector warningCollector) { this.session = requireNonNull(session, "session is null"); - this.parser = parser; - this.metadata = metadata; - this.queryExplainer = queryExplainer; + this.parser = requireNonNull(parser, "parser is null"); + this.analyzerFactory = analyzerFactory; this.parameters = parameters; this.parameterLookup = parameterLookup; - this.groupProvider = requireNonNull(groupProvider, "groupProvider is null"); - this.accessControl = accessControl; this.warningCollector = requireNonNull(warningCollector, "warningCollector is null"); - this.statsCalculator = requireNonNull(statsCalculator, "statsCalculator is null"); } @Override @@ -121,7 +110,7 @@ protected Node visitDescribeOutput(DescribeOutput node, Void context) String sqlString = session.getPreparedStatement(node.getName().getValue()); Statement statement = parser.createStatement(sqlString, createParsingOptions(session)); - Analyzer analyzer = new Analyzer(session, metadata, parser, groupProvider, accessControl, queryExplainer, parameters, parameterLookup, warningCollector, statsCalculator); + Analyzer analyzer = analyzerFactory.createAnalyzer(session, parameters, parameterLookup, warningCollector); Analysis analysis = analyzer.analyze(statement, DESCRIBE); Optional limit = Optional.empty(); diff --git a/core/trino-main/src/main/java/io/trino/sql/rewrite/ExplainRewrite.java b/core/trino-main/src/main/java/io/trino/sql/rewrite/ExplainRewrite.java index 5aa35368e6a6..5d2b187f3156 100644 --- a/core/trino-main/src/main/java/io/trino/sql/rewrite/ExplainRewrite.java +++ b/core/trino-main/src/main/java/io/trino/sql/rewrite/ExplainRewrite.java @@ -14,15 +14,12 @@ package io.trino.sql.rewrite; import io.trino.Session; -import io.trino.cost.StatsCalculator; import io.trino.execution.QueryPreparer; import io.trino.execution.QueryPreparer.PreparedQuery; import io.trino.execution.warnings.WarningCollector; -import io.trino.metadata.Metadata; -import io.trino.security.AccessControl; -import io.trino.spi.security.GroupProvider; +import io.trino.sql.analyzer.AnalyzerFactory; import io.trino.sql.analyzer.QueryExplainer; -import io.trino.sql.parser.SqlParser; +import io.trino.sql.analyzer.QueryExplainerFactory; import io.trino.sql.tree.AstVisitor; import io.trino.sql.tree.Explain; import io.trino.sql.tree.ExplainAnalyze; @@ -35,9 +32,10 @@ import io.trino.sql.tree.Parameter; import io.trino.sql.tree.Statement; +import javax.inject.Inject; + import java.util.List; import java.util.Map; -import java.util.Optional; import static io.trino.sql.QueryUtil.singleValueQuery; import static io.trino.sql.tree.ExplainFormat.Type.JSON; @@ -47,24 +45,29 @@ import static io.trino.sql.tree.ExplainType.Type.VALIDATE; import static java.util.Objects.requireNonNull; -final class ExplainRewrite +public final class ExplainRewrite implements StatementRewrite.Rewrite { + private final QueryExplainerFactory queryExplainerFactory; + private final QueryPreparer queryPreparer; + + @Inject + public ExplainRewrite(QueryExplainerFactory queryExplainerFactory, QueryPreparer queryPreparer) + { + this.queryExplainerFactory = requireNonNull(queryExplainerFactory, "queryExplainerFactory is null"); + this.queryPreparer = requireNonNull(queryPreparer, "queryPreparer is null"); + } + @Override public Statement rewrite( + AnalyzerFactory analyzerFactory, Session session, - Metadata metadata, - SqlParser parser, - Optional queryExplainer, Statement node, List parameter, Map, Expression> parameterLookup, - GroupProvider groupProvider, - AccessControl accessControl, - WarningCollector warningCollector, - StatsCalculator statsCalculator) + WarningCollector warningCollector) { - return (Statement) new Visitor(session, parser, queryExplainer, warningCollector).process(node, null); + return (Statement) new Visitor(session, queryPreparer, queryExplainerFactory.createQueryExplainer(analyzerFactory), warningCollector).process(node, null); } private static final class Visitor @@ -72,17 +75,17 @@ private static final class Visitor { private final Session session; private final QueryPreparer queryPreparer; - private final Optional queryExplainer; + private final QueryExplainer queryExplainer; private final WarningCollector warningCollector; public Visitor( Session session, - SqlParser parser, - Optional queryExplainer, + QueryPreparer queryPreparer, + QueryExplainer queryExplainer, WarningCollector warningCollector) { this.session = requireNonNull(session, "session is null"); - this.queryPreparer = new QueryPreparer(requireNonNull(parser, "parser is null")); + this.queryPreparer = requireNonNull(queryPreparer, "queryPreparer is null"); this.queryExplainer = requireNonNull(queryExplainer, "queryExplainer is null"); this.warningCollector = requireNonNull(warningCollector, "warningCollector is null"); } @@ -128,23 +131,23 @@ private Node getQueryPlan(Explain node, ExplainType.Type planType, ExplainFormat PreparedQuery preparedQuery = queryPreparer.prepareQuery(session, node.getStatement()); if (planType == VALIDATE) { - queryExplainer.get().analyze(session, preparedQuery.getStatement(), preparedQuery.getParameters(), warningCollector); + queryExplainer.validate(session, preparedQuery.getStatement(), preparedQuery.getParameters(), warningCollector); return singleValueQuery("Valid", true); } String plan; switch (planFormat) { case GRAPHVIZ: - plan = queryExplainer.get().getGraphvizPlan(session, preparedQuery.getStatement(), planType, preparedQuery.getParameters(), warningCollector); + plan = queryExplainer.getGraphvizPlan(session, preparedQuery.getStatement(), planType, preparedQuery.getParameters(), warningCollector); break; case JSON: - plan = queryExplainer.get().getJsonPlan(session, preparedQuery.getStatement(), planType, preparedQuery.getParameters(), warningCollector); + plan = queryExplainer.getJsonPlan(session, preparedQuery.getStatement(), planType, preparedQuery.getParameters(), warningCollector); break; case TEXT: - plan = queryExplainer.get().getPlan(session, preparedQuery.getStatement(), planType, preparedQuery.getParameters(), warningCollector); + plan = queryExplainer.getPlan(session, preparedQuery.getStatement(), planType, preparedQuery.getParameters(), warningCollector); break; default: - throw new IllegalArgumentException("Invalid Explain Format: " + planFormat.toString()); + throw new IllegalArgumentException("Invalid Explain Format: " + planFormat); } return singleValueQuery("Query Plan", plan); } diff --git a/core/trino-main/src/main/java/io/trino/sql/rewrite/ShowQueriesRewrite.java b/core/trino-main/src/main/java/io/trino/sql/rewrite/ShowQueriesRewrite.java index db6a07fbea5f..1a1f9a09d39b 100644 --- a/core/trino-main/src/main/java/io/trino/sql/rewrite/ShowQueriesRewrite.java +++ b/core/trino-main/src/main/java/io/trino/sql/rewrite/ShowQueriesRewrite.java @@ -21,7 +21,6 @@ import com.google.common.primitives.Primitives; import io.trino.Session; import io.trino.connector.CatalogName; -import io.trino.cost.StatsCalculator; import io.trino.execution.warnings.WarningCollector; import io.trino.metadata.FunctionKind; import io.trino.metadata.FunctionMetadata; @@ -39,11 +38,10 @@ import io.trino.spi.connector.CatalogSchemaName; import io.trino.spi.connector.ConnectorTableMetadata; import io.trino.spi.connector.SchemaTableName; -import io.trino.spi.security.GroupProvider; import io.trino.spi.security.PrincipalType; import io.trino.spi.security.TrinoPrincipal; import io.trino.spi.session.PropertyMetadata; -import io.trino.sql.analyzer.QueryExplainer; +import io.trino.sql.analyzer.AnalyzerFactory; import io.trino.sql.parser.ParsingException; import io.trino.sql.parser.SqlParser; import io.trino.sql.tree.AllColumns; @@ -86,6 +84,8 @@ import io.trino.sql.tree.TableElement; import io.trino.sql.tree.Values; +import javax.inject.Inject; + import java.util.Collections; import java.util.List; import java.util.Map; @@ -150,22 +150,29 @@ import static java.util.Objects.requireNonNull; import static java.util.stream.Collectors.toList; -final class ShowQueriesRewrite +public final class ShowQueriesRewrite implements StatementRewrite.Rewrite { + private final Metadata metadata; + private final SqlParser parser; + private final AccessControl accessControl; + + @Inject + public ShowQueriesRewrite(Metadata metadata, SqlParser parser, AccessControl accessControl) + { + this.metadata = requireNonNull(metadata, "metadata is null"); + this.parser = requireNonNull(parser, "parser is null"); + this.accessControl = requireNonNull(accessControl, "accessControl is null"); + } + @Override public Statement rewrite( + AnalyzerFactory analyzerFactory, Session session, - Metadata metadata, - SqlParser parser, - Optional queryExplainer, Statement node, List parameters, Map, Expression> parameterLookup, - GroupProvider groupProvider, - AccessControl accessControl, - WarningCollector warningCollector, - StatsCalculator statsCalculator) + WarningCollector warningCollector) { return (Statement) new Visitor(metadata, parser, session, accessControl).process(node, null); } diff --git a/core/trino-main/src/main/java/io/trino/sql/rewrite/ShowStatsRewrite.java b/core/trino-main/src/main/java/io/trino/sql/rewrite/ShowStatsRewrite.java index 8bcf572b6750..2d0b1525abca 100644 --- a/core/trino-main/src/main/java/io/trino/sql/rewrite/ShowStatsRewrite.java +++ b/core/trino-main/src/main/java/io/trino/sql/rewrite/ShowStatsRewrite.java @@ -20,11 +20,8 @@ import io.trino.cost.StatsCalculator; import io.trino.cost.SymbolStatsEstimate; import io.trino.execution.warnings.WarningCollector; -import io.trino.metadata.Metadata; import io.trino.operator.scalar.timestamp.TimestampToVarcharCast; import io.trino.operator.scalar.timestamptz.TimestampWithTimeZoneToVarcharCast; -import io.trino.security.AccessControl; -import io.trino.spi.security.GroupProvider; import io.trino.spi.type.BigintType; import io.trino.spi.type.DecimalType; import io.trino.spi.type.IntegerType; @@ -35,8 +32,9 @@ import io.trino.spi.type.TinyintType; import io.trino.spi.type.Type; import io.trino.sql.QueryUtil; +import io.trino.sql.analyzer.AnalyzerFactory; import io.trino.sql.analyzer.QueryExplainer; -import io.trino.sql.parser.SqlParser; +import io.trino.sql.analyzer.QueryExplainerFactory; import io.trino.sql.planner.Plan; import io.trino.sql.planner.Symbol; import io.trino.sql.planner.plan.OutputNode; @@ -59,12 +57,12 @@ import io.trino.sql.tree.TableSubquery; import io.trino.sql.tree.Values; +import javax.inject.Inject; + import java.time.LocalDate; import java.util.List; import java.util.Map; -import java.util.Optional; -import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Verify.verify; import static com.google.common.collect.ImmutableList.toImmutableList; import static io.trino.spi.type.BooleanType.BOOLEAN; @@ -89,21 +87,26 @@ public class ShowStatsRewrite private static final Expression NULL_DOUBLE = new Cast(new NullLiteral(), toSqlType(DOUBLE)); private static final Expression NULL_VARCHAR = new Cast(new NullLiteral(), toSqlType(VARCHAR)); + private final QueryExplainerFactory queryExplainerFactory; + private final StatsCalculator statsCalculator; + + @Inject + public ShowStatsRewrite(QueryExplainerFactory queryExplainerFactory, StatsCalculator statsCalculator) + { + this.queryExplainerFactory = requireNonNull(queryExplainerFactory, "queryExplainerFactory is null"); + this.statsCalculator = requireNonNull(statsCalculator, "statsCalculator is null"); + } + @Override public Statement rewrite( + AnalyzerFactory analyzerFactory, Session session, - Metadata metadata, - SqlParser parser, - Optional queryExplainer, Statement node, List parameters, Map, Expression> parameterLookup, - GroupProvider groupProvider, - AccessControl accessControl, - WarningCollector warningCollector, - StatsCalculator statsCalculator) + WarningCollector warningCollector) { - return (Statement) new Visitor(session, parameters, queryExplainer, warningCollector, statsCalculator).process(node, null); + return (Statement) new Visitor(session, parameters, queryExplainerFactory.createQueryExplainer(analyzerFactory), warningCollector, statsCalculator).process(node, null); } private static class Visitor @@ -111,11 +114,11 @@ private static class Visitor { private final Session session; private final List parameters; - private final Optional queryExplainer; + private final QueryExplainer queryExplainer; private final WarningCollector warningCollector; private final StatsCalculator statsCalculator; - private Visitor(Session session, List parameters, Optional queryExplainer, WarningCollector warningCollector, StatsCalculator statsCalculator) + private Visitor(Session session, List parameters, QueryExplainer queryExplainer, WarningCollector warningCollector, StatsCalculator statsCalculator) { this.session = requireNonNull(session, "session is null"); this.parameters = requireNonNull(parameters, "parameters is null"); @@ -127,10 +130,8 @@ private Visitor(Session session, List parameters, Optional REWRITES = ImmutableList.of( - new DescribeInputRewrite(), - new DescribeOutputRewrite(), - new ShowQueriesRewrite(), - new ShowStatsRewrite(), - new ExplainRewrite()); + private final Set rewrites; - private StatementRewrite() {} + @Inject + public StatementRewrite(Set rewrites) + { + this.rewrites = ImmutableSet.copyOf(requireNonNull(rewrites, "rewrites is null")); + } - public static Statement rewrite( + public Statement rewrite( + AnalyzerFactory analyzerFactory, Session session, - Metadata metadata, - SqlParser parser, - Optional queryExplainer, Statement node, List parameters, Map, Expression> parameterLookup, - GroupProvider groupProvider, - AccessControl accessControl, - WarningCollector warningCollector, - StatsCalculator statsCalculator) + WarningCollector warningCollector) { - for (Rewrite rewrite : REWRITES) { - node = requireNonNull(rewrite.rewrite(session, metadata, parser, queryExplainer, node, parameters, parameterLookup, groupProvider, accessControl, warningCollector, statsCalculator), "Statement rewrite returned null"); + for (Rewrite rewrite : rewrites) { + node = requireNonNull( + rewrite.rewrite( + analyzerFactory, + session, + node, + parameters, + parameterLookup, + warningCollector), + "Statement rewrite returned null"); } return node; } - interface Rewrite + public interface Rewrite { Statement rewrite( + AnalyzerFactory analyzerFactory, Session session, - Metadata metadata, - SqlParser parser, - Optional queryExplainer, Statement node, List parameters, Map, Expression> parameterLookup, - GroupProvider groupProvider, - AccessControl accessControl, - WarningCollector warningCollector, - StatsCalculator statsCalculator); + WarningCollector warningCollector); } } diff --git a/core/trino-main/src/main/java/io/trino/testing/LocalQueryRunner.java b/core/trino-main/src/main/java/io/trino/testing/LocalQueryRunner.java index d0536c30445d..3e2ea977e3a4 100644 --- a/core/trino-main/src/main/java/io/trino/testing/LocalQueryRunner.java +++ b/core/trino-main/src/main/java/io/trino/testing/LocalQueryRunner.java @@ -128,7 +128,8 @@ import io.trino.split.SplitSource; import io.trino.sql.analyzer.Analysis; import io.trino.sql.analyzer.Analyzer; -import io.trino.sql.analyzer.QueryExplainer; +import io.trino.sql.analyzer.AnalyzerFactory; +import io.trino.sql.analyzer.QueryExplainerFactory; import io.trino.sql.gen.ExpressionCompiler; import io.trino.sql.gen.JoinCompiler; import io.trino.sql.gen.JoinFilterFunctionCompiler; @@ -152,6 +153,12 @@ import io.trino.sql.planner.plan.TableScanNode; import io.trino.sql.planner.planprinter.PlanPrinter; import io.trino.sql.planner.sanity.PlanSanityChecker; +import io.trino.sql.rewrite.DescribeInputRewrite; +import io.trino.sql.rewrite.DescribeOutputRewrite; +import io.trino.sql.rewrite.ExplainRewrite; +import io.trino.sql.rewrite.ShowQueriesRewrite; +import io.trino.sql.rewrite.ShowStatsRewrite; +import io.trino.sql.rewrite.StatementRewrite; import io.trino.testing.PageConsumerOperator.PageConsumerOutputFactory; import io.trino.transaction.InMemoryTransactionManager; import io.trino.transaction.TransactionId; @@ -244,7 +251,6 @@ public class LocalQueryRunner private final boolean alwaysRevokeMemory; private final NodeSpillConfig nodeSpillConfig; private final FeaturesConfig featuresConfig; - private final PlanOptimizersProvider planOptimizersProvider; private final OperatorFactories operatorFactories; private boolean printPlan; @@ -269,7 +275,6 @@ private LocalQueryRunner( boolean alwaysRevokeMemory, int nodeCountForStats, Map>> defaultSessionProperties, - PlanOptimizersProvider planOptimizersProvider, OperatorFactories operatorFactories, Set extraSessionProperties) { @@ -279,7 +284,6 @@ private LocalQueryRunner( this.taskManagerConfig = new TaskManagerConfig().setTaskConcurrency(4); this.nodeSpillConfig = requireNonNull(nodeSpillConfig, "nodeSpillConfig is null"); - this.planOptimizersProvider = requireNonNull(planOptimizersProvider, "planOptimizersProvider is null"); this.operatorFactories = requireNonNull(operatorFactories, "operatorFactories is null"); this.alwaysRevokeMemory = alwaysRevokeMemory; this.notificationExecutor = newCachedThreadPool(daemonThreadsNamed("local-query-runner-executor-%s")); @@ -492,6 +496,12 @@ public Metadata getMetadata() return metadata; } + @Override + public AnalyzerFactory getAnalyzerFactory() + { + return createAnalyzerFactory(getPlanOptimizers(false)); + } + public TypeOperators getTypeOperators() { return typeOperators; @@ -868,21 +878,22 @@ public Plan createPlan(Session session, @Language("SQL") String sql, LogicalPlan public List getPlanOptimizers(boolean forceSingleNode) { - return planOptimizersProvider.getPlanOptimizers( - forceSingleNode, - sqlParser, + return new PlanOptimizers( metadata, typeOperators, + new TypeAnalyzer(sqlParser, metadata), taskManagerConfig, + forceSingleNode, splitManager, pageSourceManager, statsCalculator, scalarStatsCalculator, costCalculator, estimatedExchangesCostCalculator, - featuresConfig, + new CostComparator(featuresConfig), taskCountEstimator, - nodePartitioningManager); + nodePartitioningManager, + new RuleStatsRecorder()).get(); } public Plan createPlan(Session session, @Language("SQL") String sql, List optimizers, WarningCollector warningCollector) @@ -898,17 +909,12 @@ public Plan createPlan(Session session, @Language("SQL") String sql, List optimizers) + { + QueryExplainerFactory queryExplainerFactory = new QueryExplainerFactory( + () -> optimizers, + planFragmenter, + metadata, + typeOperators, + sqlParser, + statsCalculator, + costCalculator); + + return new AnalyzerFactory( + metadata, + sqlParser, + accessControl, + groupProvider, + new StatementRewrite(ImmutableSet.of( + new DescribeInputRewrite(sqlParser), + new DescribeOutputRewrite(sqlParser), + new ShowQueriesRewrite(metadata, sqlParser, accessControl), + new ShowStatsRewrite(queryExplainerFactory, statsCalculator), + new ExplainRewrite(queryExplainerFactory, new QueryPreparer(sqlParser))))); + } + private static List getNextBatch(SplitSource splitSource) { return getFutureValue(splitSource.getNextBatch(NOT_PARTITIONED, Lifespan.taskWide(), 1000)).getSplits(); @@ -939,25 +969,6 @@ private static List findTableScanNodes(PlanNode node) .findAll(); } - public interface PlanOptimizersProvider - { - List getPlanOptimizers( - boolean forceSingleNode, - SqlParser sqlParser, - MetadataManager metadata, - TypeOperators typeOperators, - TaskManagerConfig taskManagerConfig, - SplitManager splitManager, - PageSourceManager pageSourceManager, - StatsCalculator statsCalculator, - ScalarStatsCalculator scalarStatsCalculator, - CostCalculator costCalculator, - CostCalculator estimatedExchangesCostCalculator, - FeaturesConfig featuresConfig, - TaskCountEstimator taskCountEstimator, - NodePartitioningManager nodePartitioningManager); - } - public static class Builder { private final Session defaultSession; @@ -968,37 +979,6 @@ public static class Builder private Map>> defaultSessionProperties = ImmutableMap.of(); private Set extraSessionProperties = ImmutableSet.of(); private int nodeCountForStats; - private PlanOptimizersProvider planOptimizersProvider = ( - forceSingleNode, - sqlParser, - metadata, - typeOperators, - taskManagerConfig, - splitManager, - pageSourceManager, - statsCalculator, - scalarStatsCalculator, - costCalculator, - estimatedExchangesCostCalculator, - featuresConfig, - taskCountEstimator, - nodePartitioningManager) -> - new PlanOptimizers( - metadata, - typeOperators, - new TypeAnalyzer(sqlParser, metadata), - taskManagerConfig, - forceSingleNode, - splitManager, - pageSourceManager, - statsCalculator, - scalarStatsCalculator, - costCalculator, - estimatedExchangesCostCalculator, - new CostComparator(featuresConfig), - taskCountEstimator, - nodePartitioningManager, - new RuleStatsRecorder()).get(); private OperatorFactories operatorFactories = new TrinoOperatorFactories(); private Builder(Session defaultSession) @@ -1042,12 +1022,6 @@ public Builder withNodeCountForStats(int nodeCountForStats) return this; } - public Builder withPlanOptimizersProvider(PlanOptimizersProvider planOptimizersProvider) - { - this.planOptimizersProvider = requireNonNull(planOptimizersProvider, "planOptimizersProvider is null"); - return this; - } - public Builder withOperatorFactories(OperatorFactories operatorFactories) { this.operatorFactories = requireNonNull(operatorFactories, "operatorFactories is null"); @@ -1075,7 +1049,6 @@ public LocalQueryRunner build() alwaysRevokeMemory, nodeCountForStats, defaultSessionProperties, - planOptimizersProvider, operatorFactories, extraSessionProperties); } diff --git a/core/trino-main/src/main/java/io/trino/testing/QueryRunner.java b/core/trino-main/src/main/java/io/trino/testing/QueryRunner.java index 8bf1e86adae3..1a04088e729d 100644 --- a/core/trino-main/src/main/java/io/trino/testing/QueryRunner.java +++ b/core/trino-main/src/main/java/io/trino/testing/QueryRunner.java @@ -22,6 +22,7 @@ import io.trino.spi.Plugin; import io.trino.split.PageSourceManager; import io.trino.split.SplitManager; +import io.trino.sql.analyzer.AnalyzerFactory; import io.trino.sql.planner.NodePartitioningManager; import io.trino.sql.planner.Plan; import io.trino.transaction.TransactionManager; @@ -46,6 +47,8 @@ public interface QueryRunner Metadata getMetadata(); + AnalyzerFactory getAnalyzerFactory(); + SplitManager getSplitManager(); PageSourceManager getPageSourceManager(); diff --git a/core/trino-main/src/test/java/io/trino/execution/TestCreateMaterializedViewTask.java b/core/trino-main/src/test/java/io/trino/execution/TestCreateMaterializedViewTask.java index 6809c253d72e..1f3bd497bae8 100644 --- a/core/trino-main/src/test/java/io/trino/execution/TestCreateMaterializedViewTask.java +++ b/core/trino-main/src/test/java/io/trino/execution/TestCreateMaterializedViewTask.java @@ -16,9 +16,9 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; import io.trino.Session; import io.trino.connector.CatalogName; -import io.trino.cost.StatsCalculator; import io.trino.execution.warnings.WarningCollector; import io.trino.metadata.AbstractMockMetadata; import io.trino.metadata.Catalog; @@ -43,8 +43,10 @@ import io.trino.spi.connector.TestingColumnHandle; import io.trino.spi.resourcegroups.ResourceGroupId; import io.trino.spi.security.AccessDeniedException; +import io.trino.sql.analyzer.AnalyzerFactory; import io.trino.sql.parser.SqlParser; import io.trino.sql.planner.TestingConnectorTransactionHandle; +import io.trino.sql.rewrite.StatementRewrite; import io.trino.sql.tree.AllColumns; import io.trino.sql.tree.CreateMaterializedView; import io.trino.sql.tree.Identifier; @@ -67,7 +69,6 @@ import static com.google.common.collect.ImmutableMap.toImmutableMap; import static com.google.common.util.concurrent.MoreExecutors.directExecutor; import static io.airlift.concurrent.MoreFutures.getFutureValue; -import static io.trino.cost.StatsCalculator.noopStatsCalculator; import static io.trino.metadata.MetadataManager.createTestMetadataManager; import static io.trino.spi.StandardErrorCode.ALREADY_EXISTS; import static io.trino.spi.StandardErrorCode.INVALID_MATERIALIZED_VIEW_PROPERTY; @@ -101,8 +102,8 @@ public class TestCreateMaterializedViewTask private MockMetadata metadata; private TransactionManager transactionManager; private SqlParser parser; - private StatsCalculator statsCalculator; private QueryStateMachine queryStateMachine; + private AnalyzerFactory analyzerFactory; @BeforeMethod public void setUp() @@ -127,7 +128,7 @@ public void setUp() materializedViewPropertyManager, testCatalog.getConnectorCatalogName()); parser = new SqlParser(); - statsCalculator = noopStatsCalculator(); + analyzerFactory = new AnalyzerFactory(metadata, parser, new AllowAllAccessControl(), new TestingGroupProvider(), new StatementRewrite(ImmutableSet.of())); queryStateMachine = stateMachine(transactionManager, createTestMetadataManager(), new AllowAllAccessControl()); } @@ -143,7 +144,7 @@ public void testCreateMaterializedViewIfNotExists() ImmutableList.of(), Optional.empty()); - getFutureValue(new CreateMaterializedViewTask(metadata, new AllowAllAccessControl(), parser, new TestingGroupProvider(), statsCalculator) + getFutureValue(new CreateMaterializedViewTask(metadata, new AllowAllAccessControl(), parser, analyzerFactory) .execute(statement, queryStateMachine, ImmutableList.of(), WarningCollector.NOOP)); assertEquals(metadata.getCreateMaterializedViewCallCount(), 1); } @@ -160,7 +161,7 @@ public void testCreateMaterializedViewWithExistingView() ImmutableList.of(), Optional.empty()); - assertTrinoExceptionThrownBy(() -> getFutureValue(new CreateMaterializedViewTask(metadata, new AllowAllAccessControl(), parser, new TestingGroupProvider(), statsCalculator) + assertTrinoExceptionThrownBy(() -> getFutureValue(new CreateMaterializedViewTask(metadata, new AllowAllAccessControl(), parser, analyzerFactory) .execute(statement, queryStateMachine, ImmutableList.of(), WarningCollector.NOOP))) .hasErrorCode(ALREADY_EXISTS) .hasMessage("Materialized view already exists"); @@ -180,7 +181,7 @@ public void testCreateMaterializedViewWithInvalidProperty() ImmutableList.of(new Property(new Identifier("baz"), new StringLiteral("abc"))), Optional.empty()); - assertTrinoExceptionThrownBy(() -> getFutureValue(new CreateMaterializedViewTask(metadata, new AllowAllAccessControl(), parser, new TestingGroupProvider(), statsCalculator) + assertTrinoExceptionThrownBy(() -> getFutureValue(new CreateMaterializedViewTask(metadata, new AllowAllAccessControl(), parser, analyzerFactory) .execute(statement, queryStateMachine, ImmutableList.of(), WarningCollector.NOOP))) .hasErrorCode(INVALID_MATERIALIZED_VIEW_PROPERTY) .hasMessage("Catalog 'catalog' does not support materialized view property 'baz'"); @@ -203,7 +204,8 @@ public void testCreateDenyPermission() accessControl.loadSystemAccessControl(AllowAllSystemAccessControl.NAME, ImmutableMap.of()); accessControl.deny(privilege("test_mv", CREATE_MATERIALIZED_VIEW)); - assertThatThrownBy(() -> getFutureValue(new CreateMaterializedViewTask(metadata, accessControl, parser, new TestingGroupProvider(), statsCalculator) + AnalyzerFactory analyzerFactory = new AnalyzerFactory(metadata, parser, accessControl, new TestingGroupProvider(), new StatementRewrite(ImmutableSet.of())); + assertThatThrownBy(() -> getFutureValue(new CreateMaterializedViewTask(metadata, accessControl, parser, analyzerFactory) .execute(statement, queryStateMachine, ImmutableList.of(), WarningCollector.NOOP))) .isInstanceOf(AccessDeniedException.class) .hasMessageContaining("Cannot create materialized view catalog.schema.test_mv"); diff --git a/core/trino-main/src/test/java/io/trino/execution/TestSetTimeZoneTask.java b/core/trino-main/src/test/java/io/trino/execution/TestSetTimeZoneTask.java index 24557507f4b5..5b762230e06f 100644 --- a/core/trino-main/src/test/java/io/trino/execution/TestSetTimeZoneTask.java +++ b/core/trino-main/src/test/java/io/trino/execution/TestSetTimeZoneTask.java @@ -259,8 +259,8 @@ private void executeSetTimeZone(SetTimeZone setTimeZone, QueryStateMachine state localQueryRunner.getMetadata(), localQueryRunner.getAccessControl(), localQueryRunner.getSqlParser(), - localQueryRunner.getGroupProvider(), - localQueryRunner.getStatsCalculator()); + localQueryRunner.getAnalyzerFactory(), + localQueryRunner.getGroupProvider()); getFutureValue(task.execute(setTimeZone, stateMachine, emptyList(), WarningCollector.NOOP)); } } diff --git a/core/trino-main/src/test/java/io/trino/sql/analyzer/TestAnalyzer.java b/core/trino-main/src/test/java/io/trino/sql/analyzer/TestAnalyzer.java index 5a8dd3cf59e3..31722baa650c 100644 --- a/core/trino-main/src/test/java/io/trino/sql/analyzer/TestAnalyzer.java +++ b/core/trino-main/src/test/java/io/trino/sql/analyzer/TestAnalyzer.java @@ -63,6 +63,8 @@ import io.trino.spi.type.Type; import io.trino.sql.parser.ParsingOptions; import io.trino.sql.parser.SqlParser; +import io.trino.sql.rewrite.ShowQueriesRewrite; +import io.trino.sql.rewrite.StatementRewrite; import io.trino.sql.tree.Statement; import io.trino.testing.TestingAccessControlManager; import io.trino.testing.TestingMetadata; @@ -80,7 +82,6 @@ import static com.google.common.collect.Iterables.getOnlyElement; import static io.trino.connector.CatalogName.createInformationSchemaCatalogName; import static io.trino.connector.CatalogName.createSystemTablesCatalogName; -import static io.trino.cost.StatsCalculator.noopStatsCalculator; import static io.trino.metadata.MetadataManager.createTestMetadataManager; import static io.trino.operator.scalar.ApplyFunction.APPLY_FUNCTION; import static io.trino.spi.StandardErrorCode.AMBIGUOUS_NAME; @@ -5251,17 +5252,13 @@ private void inSetupTransaction(Consumer consumer) private static Analyzer createAnalyzer(Session session, Metadata metadata, AccessControl accessControl) { - return new Analyzer( + StatementRewrite statementRewrite = new StatementRewrite(ImmutableSet.of(new ShowQueriesRewrite(metadata, SQL_PARSER, accessControl))); + AnalyzerFactory analyzerFactory = new AnalyzerFactory(metadata, SQL_PARSER, accessControl, user -> ImmutableSet.of(), statementRewrite); + return analyzerFactory.createAnalyzer( session, - metadata, - SQL_PARSER, - user -> ImmutableSet.of(), - accessControl, - Optional.empty(), emptyList(), emptyMap(), - WarningCollector.NOOP, - noopStatsCalculator()); + WarningCollector.NOOP); } private Analysis analyze(@Language("SQL") String query) diff --git a/plugin/trino-thrift/src/test/java/io/trino/plugin/thrift/integration/ThriftQueryRunner.java b/plugin/trino-thrift/src/test/java/io/trino/plugin/thrift/integration/ThriftQueryRunner.java index ef864527caad..87165830347b 100644 --- a/plugin/trino-thrift/src/test/java/io/trino/plugin/thrift/integration/ThriftQueryRunner.java +++ b/plugin/trino-thrift/src/test/java/io/trino/plugin/thrift/integration/ThriftQueryRunner.java @@ -38,6 +38,7 @@ import io.trino.spi.Plugin; import io.trino.split.PageSourceManager; import io.trino.split.SplitManager; +import io.trino.sql.analyzer.AnalyzerFactory; import io.trino.sql.planner.NodePartitioningManager; import io.trino.testing.DistributedQueryRunner; import io.trino.testing.MaterializedResult; @@ -210,6 +211,12 @@ public Metadata getMetadata() return source.getMetadata(); } + @Override + public AnalyzerFactory getAnalyzerFactory() + { + return source.getAnalyzerFactory(); + } + @Override public SplitManager getSplitManager() { diff --git a/testing/trino-testing/src/main/java/io/trino/testing/AbstractTestQueryFramework.java b/testing/trino-testing/src/main/java/io/trino/testing/AbstractTestQueryFramework.java index 2ef94f2a76e1..435ad9d43134 100644 --- a/testing/trino-testing/src/main/java/io/trino/testing/AbstractTestQueryFramework.java +++ b/testing/trino-testing/src/main/java/io/trino/testing/AbstractTestQueryFramework.java @@ -14,6 +14,7 @@ package io.trino.testing; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; import com.google.common.collect.MoreCollectors; import com.google.errorprone.annotations.CanIgnoreReturnValue; import io.airlift.units.Duration; @@ -27,6 +28,7 @@ import io.trino.cost.ScalarStatsCalculator; import io.trino.cost.TaskCountEstimator; import io.trino.execution.QueryManagerConfig; +import io.trino.execution.QueryPreparer; import io.trino.execution.QueryStats; import io.trino.execution.TaskManagerConfig; import io.trino.execution.warnings.WarningCollector; @@ -38,20 +40,28 @@ import io.trino.spi.QueryId; import io.trino.spi.type.Type; import io.trino.spi.type.TypeOperators; +import io.trino.sql.analyzer.AnalyzerFactory; import io.trino.sql.analyzer.QueryExplainer; +import io.trino.sql.analyzer.QueryExplainerFactory; import io.trino.sql.parser.SqlParser; import io.trino.sql.planner.Plan; import io.trino.sql.planner.PlanFragmenter; import io.trino.sql.planner.PlanOptimizers; +import io.trino.sql.planner.PlanOptimizersFactory; import io.trino.sql.planner.RuleStatsRecorder; import io.trino.sql.planner.TypeAnalyzer; import io.trino.sql.planner.optimizations.PlanNodeSearcher; -import io.trino.sql.planner.optimizations.PlanOptimizer; import io.trino.sql.planner.plan.FilterNode; import io.trino.sql.planner.plan.PlanNodeId; import io.trino.sql.planner.plan.ProjectNode; import io.trino.sql.planner.plan.TableScanNode; import io.trino.sql.query.QueryAssertions.QueryAssert; +import io.trino.sql.rewrite.DescribeInputRewrite; +import io.trino.sql.rewrite.DescribeOutputRewrite; +import io.trino.sql.rewrite.ExplainRewrite; +import io.trino.sql.rewrite.ShowQueriesRewrite; +import io.trino.sql.rewrite.ShowStatsRewrite; +import io.trino.sql.rewrite.StatementRewrite; import io.trino.sql.tree.ExplainType; import io.trino.testing.TestingAccessControlManager.TestingPrivilege; import io.trino.transaction.TransactionBuilder; @@ -461,7 +471,7 @@ private QueryExplainer getQueryExplainer() CostCalculator costCalculator = new CostCalculatorUsingExchanges(taskCountEstimator); TypeOperators typeOperators = new TypeOperators(); TypeAnalyzer typeAnalyzer = new TypeAnalyzer(sqlParser, metadata); - List optimizers = new PlanOptimizers( + PlanOptimizersFactory planOptimizersFactory = new PlanOptimizers( metadata, typeOperators, typeAnalyzer, @@ -476,17 +486,27 @@ private QueryExplainer getQueryExplainer() new CostComparator(featuresConfig), taskCountEstimator, queryRunner.getNodePartitioningManager(), - new RuleStatsRecorder()).get(); - return new QueryExplainer( - optimizers, + new RuleStatsRecorder()); + QueryExplainerFactory queryExplainerFactory = new QueryExplainerFactory( + planOptimizersFactory, new PlanFragmenter(metadata, queryRunner.getNodePartitioningManager(), new QueryManagerConfig()), metadata, typeOperators, - queryRunner.getGroupProvider(), - queryRunner.getAccessControl(), sqlParser, queryRunner.getStatsCalculator(), costCalculator); + AnalyzerFactory analyzerFactory = new AnalyzerFactory( + metadata, + sqlParser, + queryRunner.getAccessControl(), + queryRunner.getGroupProvider(), + new StatementRewrite(ImmutableSet.of( + new DescribeInputRewrite(sqlParser), + new DescribeOutputRewrite(sqlParser), + new ShowQueriesRewrite(metadata, sqlParser, queryRunner.getAccessControl()), + new ShowStatsRewrite(queryExplainerFactory, queryRunner.getStatsCalculator()), + new ExplainRewrite(queryExplainerFactory, new QueryPreparer(sqlParser))))); + return queryExplainerFactory.createQueryExplainer(analyzerFactory); } protected static void skipTestUnless(boolean requirement) diff --git a/testing/trino-testing/src/main/java/io/trino/testing/DistributedQueryRunner.java b/testing/trino-testing/src/main/java/io/trino/testing/DistributedQueryRunner.java index f0cb3888c2b9..86b9508ead4a 100644 --- a/testing/trino-testing/src/main/java/io/trino/testing/DistributedQueryRunner.java +++ b/testing/trino-testing/src/main/java/io/trino/testing/DistributedQueryRunner.java @@ -41,6 +41,7 @@ import io.trino.spi.security.SystemAccessControl; import io.trino.split.PageSourceManager; import io.trino.split.SplitManager; +import io.trino.sql.analyzer.AnalyzerFactory; import io.trino.sql.planner.NodePartitioningManager; import io.trino.sql.planner.Plan; import io.trino.transaction.TransactionManager; @@ -323,6 +324,12 @@ public Metadata getMetadata() return coordinator.getMetadata(); } + @Override + public AnalyzerFactory getAnalyzerFactory() + { + return coordinator.getAnalyzerFactory(); + } + @Override public SplitManager getSplitManager() { diff --git a/testing/trino-testing/src/main/java/io/trino/testing/StandaloneQueryRunner.java b/testing/trino-testing/src/main/java/io/trino/testing/StandaloneQueryRunner.java index 40d801e51e84..ee2016f03f23 100644 --- a/testing/trino-testing/src/main/java/io/trino/testing/StandaloneQueryRunner.java +++ b/testing/trino-testing/src/main/java/io/trino/testing/StandaloneQueryRunner.java @@ -26,6 +26,7 @@ import io.trino.spi.Plugin; import io.trino.split.PageSourceManager; import io.trino.split.SplitManager; +import io.trino.sql.analyzer.AnalyzerFactory; import io.trino.sql.planner.NodePartitioningManager; import io.trino.transaction.TransactionManager; import org.intellij.lang.annotations.Language; @@ -122,6 +123,12 @@ public Metadata getMetadata() return server.getMetadata(); } + @Override + public AnalyzerFactory getAnalyzerFactory() + { + return server.getAnalyzerFactory(); + } + @Override public SplitManager getSplitManager() {