This is an automated email from the ASF dual-hosted git repository. jackietien pushed a commit to branch ty/TableModelGrammar in repository https://gitbox.apache.org/repos/asf/iotdb.git
commit 4676d100dbf054d7ad65e459e9521703c0fa21ab Author: JackieTien97 <[email protected]> AuthorDate: Thu Feb 29 10:25:32 2024 +0800 finish analyze --- .../iotdb/db/queryengine/common/SessionInfo.java | 7 +- .../plan/relational/analyzer/Analyzer.java | 59 +++++++++++++++- .../relational/analyzer/ExpressionAnalyzer.java | 24 +++++-- .../relational/analyzer/StatementAnalyzer.java | 16 +++-- .../analyzer/StatementAnalyzerFactory.java | 60 ++++++++++++++++ .../plan/relational/analyzer/AnalyzerTest.java | 79 ++++++++++++++++++++++ 6 files changed, 227 insertions(+), 18 deletions(-) diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/SessionInfo.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/SessionInfo.java index a4a28dd2f38..4ec877d1886 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/SessionInfo.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/SessionInfo.java @@ -55,16 +55,11 @@ public class SessionInfo { } public SessionInfo( - long sessionId, - String userName, - String zoneId, - @Nullable String databaseName, - ClientVersion version) { + long sessionId, String userName, String zoneId, @Nullable String databaseName) { this.sessionId = sessionId; this.userName = userName; this.zoneId = zoneId; this.databaseName = databaseName; - this.version = version; } public long getSessionId() { diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/Analyzer.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/Analyzer.java index 909b5b7b1d4..741f49017d4 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/Analyzer.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/Analyzer.java @@ -19,4 +19,61 @@ package org.apache.iotdb.db.queryengine.plan.relational.analyzer; -public class Analyzer {} +import org.apache.iotdb.db.queryengine.common.SessionInfo; +import org.apache.iotdb.db.queryengine.execution.warnings.WarningCollector; +import org.apache.iotdb.db.relational.sql.tree.Expression; +import org.apache.iotdb.db.relational.sql.tree.Parameter; +import org.apache.iotdb.db.relational.sql.tree.Statement; + +import java.util.List; +import java.util.Map; + +import static java.util.Objects.requireNonNull; + +public class Analyzer { + + private final StatementAnalyzerFactory statementAnalyzerFactory; + + private final SessionInfo session; + private final List<Expression> parameters; + + private final Map<NodeRef<Parameter>, Expression> parameterLookup; + + private final WarningCollector warningCollector; + + Analyzer( + SessionInfo session, + StatementAnalyzerFactory statementAnalyzerFactory, + List<Expression> parameters, + Map<NodeRef<Parameter>, Expression> parameterLookup, + WarningCollector warningCollector) { + this.session = requireNonNull(session, "session is null"); + this.statementAnalyzerFactory = + requireNonNull(statementAnalyzerFactory, "statementAnalyzerFactory is null"); + this.parameters = parameters; + this.parameterLookup = parameterLookup; + this.warningCollector = requireNonNull(warningCollector, "warningCollector is null"); + } + + public Analysis analyze(Statement statement) { + Analysis analysis = new Analysis(statement, parameterLookup); + StatementAnalyzer analyzer = + statementAnalyzerFactory.createStatementAnalyzer( + analysis, session, warningCollector, CorrelationSupport.ALLOWED); + + analyzer.analyze(statement); + + // TODO access control + // check column access permissions for each table + // analysis.getTableColumnReferences().forEach((accessControlInfo, tableColumnReferences) -> + // tableColumnReferences.forEach((tableName, columns) -> + // accessControlInfo.getAccessControl().checkCanSelectFromColumns( + // accessControlInfo.getSecurityContext(session.getRequiredTransactionId(), + // session.getQueryId(), + // session.getStart()), + // tableName, + // columns))); + + return analysis; + } +} diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/ExpressionAnalyzer.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/ExpressionAnalyzer.java index 9454fa1d1ed..64bd4a98952 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/ExpressionAnalyzer.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/ExpressionAnalyzer.java @@ -148,6 +148,7 @@ public class ExpressionAnalyzer { private ExpressionAnalyzer( Metadata metadata, AccessControl accessControl, + StatementAnalyzerFactory statementAnalyzerFactory, Analysis analysis, SessionInfo session, TypeProvider types, @@ -156,8 +157,8 @@ public class ExpressionAnalyzer { metadata, accessControl, (node, correlationSupport) -> - new StatementAnalyzer( - analysis, accessControl, warningCollector, session, metadata, correlationSupport), + statementAnalyzerFactory.createStatementAnalyzer( + analysis, session, warningCollector, correlationSupport), session, types, analysis.getParameters(), @@ -1394,6 +1395,7 @@ public class ExpressionAnalyzer { public static ExpressionAnalysis analyzeExpressions( Metadata metadata, SessionInfo session, + StatementAnalyzerFactory statementAnalyzerFactory, AccessControl accessControl, TypeProvider types, Iterable<Expression> expressions, @@ -1401,7 +1403,14 @@ public class ExpressionAnalyzer { WarningCollector warningCollector) { Analysis analysis = new Analysis(null, parameters); ExpressionAnalyzer analyzer = - new ExpressionAnalyzer(metadata, accessControl, analysis, session, types, warningCollector); + new ExpressionAnalyzer( + metadata, + accessControl, + statementAnalyzerFactory, + analysis, + session, + types, + warningCollector); for (Expression expression : expressions) { analyzer.analyze( expression, @@ -1420,6 +1429,7 @@ public class ExpressionAnalyzer { public static ExpressionAnalysis analyzeExpression( Metadata metadata, SessionInfo session, + StatementAnalyzerFactory statementAnalyzerFactory, AccessControl accessControl, Scope scope, Analysis analysis, @@ -1428,7 +1438,13 @@ public class ExpressionAnalyzer { CorrelationSupport correlationSupport) { ExpressionAnalyzer analyzer = new ExpressionAnalyzer( - metadata, accessControl, analysis, session, TypeProvider.empty(), warningCollector); + metadata, + accessControl, + statementAnalyzerFactory, + analysis, + session, + TypeProvider.empty(), + warningCollector); analyzer.analyze(expression, scope, correlationSupport); updateAnalysis(analysis, analyzer, session, accessControl); diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java index 5b465e02be7..2f98a73d3f2 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java @@ -153,6 +153,8 @@ import static org.apache.iotdb.tsfile.read.common.type.BooleanType.BOOLEAN; public class StatementAnalyzer { + private final StatementAnalyzerFactory statementAnalyzerFactory; + private final Analysis analysis; private final AccessControl accessControl; @@ -166,12 +168,14 @@ public class StatementAnalyzer { private final CorrelationSupport correlationSupport; public StatementAnalyzer( + StatementAnalyzerFactory statementAnalyzerFactory, Analysis analysis, AccessControl accessControl, WarningCollector warningCollector, SessionInfo sessionContext, Metadata metadata, CorrelationSupport correlationSupport) { + this.statementAnalyzerFactory = statementAnalyzerFactory; this.analysis = analysis; this.accessControl = accessControl; this.warningCollector = warningCollector; @@ -633,13 +637,8 @@ public class StatementAnalyzer { @Override protected Scope visitTableSubquery(TableSubquery node, Optional<Scope> scope) { StatementAnalyzer analyzer = - new StatementAnalyzer( - analysis, - accessControl, - warningCollector, - sessionContext, - metadata, - CorrelationSupport.ALLOWED); + statementAnalyzerFactory.createStatementAnalyzer( + analysis, sessionContext, warningCollector, CorrelationSupport.ALLOWED); Scope queryScope = analyzer.analyze( node.getQuery(), @@ -1913,6 +1912,7 @@ public class StatementAnalyzer { ExpressionAnalyzer.analyzeExpression( metadata, sessionContext, + statementAnalyzerFactory, accessControl, orderByScope, analysis, @@ -2099,6 +2099,7 @@ public class StatementAnalyzer { return ExpressionAnalyzer.analyzeExpression( metadata, sessionContext, + statementAnalyzerFactory, accessControl, scope, analysis, @@ -2112,6 +2113,7 @@ public class StatementAnalyzer { return ExpressionAnalyzer.analyzeExpression( metadata, sessionContext, + statementAnalyzerFactory, accessControl, scope, analysis, diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzerFactory.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzerFactory.java new file mode 100644 index 00000000000..4179e19cf33 --- /dev/null +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzerFactory.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.iotdb.db.queryengine.plan.relational.analyzer; + +import org.apache.iotdb.db.queryengine.common.SessionInfo; +import org.apache.iotdb.db.queryengine.execution.warnings.WarningCollector; +import org.apache.iotdb.db.queryengine.plan.relational.metadata.Metadata; +import org.apache.iotdb.db.queryengine.plan.relational.security.AccessControl; +import org.apache.iotdb.db.relational.sql.parser.SqlParser; + +import static java.util.Objects.requireNonNull; + +public class StatementAnalyzerFactory { + + private final Metadata metadata; + private final SqlParser sqlParser; + private final AccessControl accessControl; + + public StatementAnalyzerFactory( + Metadata metadata, SqlParser sqlParser, AccessControl accessControl) { + this.metadata = requireNonNull(metadata, "plannerContext is null"); + this.sqlParser = requireNonNull(sqlParser, "sqlParser is null"); + this.accessControl = requireNonNull(accessControl, "accessControl is null"); + } + + public StatementAnalyzerFactory withSpecializedAccessControl(AccessControl accessControl) { + return new StatementAnalyzerFactory(metadata, sqlParser, accessControl); + } + + public StatementAnalyzer createStatementAnalyzer( + Analysis analysis, + SessionInfo session, + WarningCollector warningCollector, + CorrelationSupport correlationSupport) { + return new StatementAnalyzer( + this, analysis, accessControl, warningCollector, session, metadata, correlationSupport); + } + + public static StatementAnalyzerFactory createTestingStatementAnalyzerFactory( + Metadata metadata, AccessControl accessControl) { + return new StatementAnalyzerFactory(metadata, new SqlParser(), accessControl); + } +} diff --git a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/AnalyzerTest.java b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/AnalyzerTest.java new file mode 100644 index 00000000000..3feb40ada8d --- /dev/null +++ b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/AnalyzerTest.java @@ -0,0 +1,79 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.iotdb.db.queryengine.plan.relational.analyzer; + +import org.apache.iotdb.db.queryengine.common.SessionInfo; +import org.apache.iotdb.db.queryengine.plan.relational.metadata.Metadata; +import org.apache.iotdb.db.queryengine.plan.relational.security.AccessControl; +import org.apache.iotdb.db.relational.sql.parser.SqlParser; +import org.apache.iotdb.db.relational.sql.tree.Statement; + +import org.junit.Test; +import org.mockito.Mockito; + +import java.time.ZoneId; +import java.util.Collections; + +import static org.apache.iotdb.db.queryengine.execution.warnings.WarningCollector.NOOP; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + +public class AnalyzerTest { + + private final SqlParser sqlParser = new SqlParser(); + + private final NopAccessControl nopAccessControl = new NopAccessControl(); + + @Test + public void testRawDataQuery() { + String sql = "select s1, status, s1 + 1 as t from table1 where time > 100 and s2 > 10;"; + Metadata metadata = Mockito.mock(Metadata.class); + Mockito.when(metadata.tableExists(Mockito.any())).thenReturn(true); + + Analysis actualAnalysis = analyzeSQL(sql, metadata); + assertNotNull(actualAnalysis); + System.out.println(actualAnalysis.getTypes()); + } + + private Analysis analyzeSQL(String sql, Metadata metadata) { + try { + Statement statement = sqlParser.createStatement(sql); + SessionInfo session = new SessionInfo(0, "test", ZoneId.systemDefault().getId(), "testdb"); + StatementAnalyzerFactory statementAnalyzerFactory = + new StatementAnalyzerFactory(metadata, sqlParser, nopAccessControl); + + Analyzer analyzer = + new Analyzer( + session, + statementAnalyzerFactory, + Collections.emptyList(), + Collections.emptyMap(), + NOOP); + return analyzer.analyze(statement); + } catch (Exception e) { + e.printStackTrace(); + fail(sql + ", " + e.getMessage()); + } + fail(); + return null; + } + + private static class NopAccessControl implements AccessControl {} +}
