You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by du...@apache.org on 2021/11/19 11:26:32 UTC

[shardingsphere] branch master updated: Support more query statements to convert between SQLStatement and SqlNode (#13661)

This is an automated email from the ASF dual-hosted git repository.

duanzhengqiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git


The following commit(s) were added to refs/heads/master by this push:
     new f314a9d  Support more query statements to convert between SQLStatement and SqlNode (#13661)
f314a9d is described below

commit f314a9d53b7c4b4ae369952c99523a40cdb1c27b
Author: liguoping <xd...@163.com>
AuthorDate: Fri Nov 19 19:25:46 2021 +0800

    Support more query statements to convert between SQLStatement and SqlNode (#13661)
    
    * has privileges or not
    
    * select_alias_as_keyword support
    
    * checkstyle
    
    * [select_alias_as_keyword] move 2 to the left condition.
    
    * [select_alias_as_keyword] add javadoc for ParameterMarkerExpressionConverter.
    
    * [select_alias_as_keyword] rollback columnConverter
    
    * 有 as 的情况下,重新获取projectionsSegmentStopIndex
    
    * getProjectionsSegmentStopIndex final param
---
 .../segment/expression/ExpressionConverter.java    |  8 +++++
 .../segment/expression/impl/ColumnConverter.java   |  2 +-
 .../impl/ParameterMarkerExpressionConverter.java}  | 21 ++++++------
 .../segment/projection/ProjectionsConverter.java   | 16 +++++++--
 .../projection/impl/ColumnProjectionConverter.java | 39 +++++++++++++++++++---
 .../statement/SelectStatementConverter.java        | 22 ++++++++++++
 .../SQLNodeConvertEngineParameterizedTest.java     |  1 +
 7 files changed, 91 insertions(+), 18 deletions(-)

diff --git a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/expression/ExpressionConverter.java b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/expression/ExpressionConverter.java
index 92b6fb0..51e0ea6 100644
--- a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/expression/ExpressionConverter.java
+++ b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/expression/ExpressionConverter.java
@@ -19,6 +19,7 @@ package org.apache.shardingsphere.infra.optimize.converter.segment.expression;
 
 import org.apache.calcite.sql.SqlBasicCall;
 import org.apache.calcite.sql.SqlBinaryOperator;
+import org.apache.calcite.sql.SqlDynamicParam;
 import org.apache.calcite.sql.SqlIdentifier;
 import org.apache.calcite.sql.SqlLiteral;
 import org.apache.calcite.sql.SqlNode;
@@ -35,6 +36,7 @@ import org.apache.shardingsphere.infra.optimize.converter.segment.expression.imp
 import org.apache.shardingsphere.infra.optimize.converter.segment.expression.impl.InExpressionConverter;
 import org.apache.shardingsphere.infra.optimize.converter.segment.expression.impl.ListExpressionConverter;
 import org.apache.shardingsphere.infra.optimize.converter.segment.expression.impl.LiteralExpressionConverter;
+import org.apache.shardingsphere.infra.optimize.converter.segment.expression.impl.ParameterMarkerExpressionConverter;
 import org.apache.shardingsphere.infra.optimize.converter.segment.expression.impl.SubqueryExpressionConverter;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BetweenExpression;
@@ -45,6 +47,7 @@ import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.InExpres
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ListExpression;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.complex.CommonExpressionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.LiteralExpressionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.ParameterMarkerExpressionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.subquery.SubqueryExpressionSegment;
 
 import java.util.Optional;
@@ -78,6 +81,8 @@ public final class ExpressionConverter implements SQLSegmentConverter<Expression
             return new InExpressionConverter().convertToSQLNode((InExpression) segment).map(optional -> optional);
         } else if (segment instanceof BetweenExpression) {
             return new BetweenExpressionConverter().convertToSQLNode((BetweenExpression) segment).map(optional -> optional);
+        } else if (segment instanceof ParameterMarkerExpressionSegment) {
+            return new ParameterMarkerExpressionConverter().convertToSQLNode((ParameterMarkerExpressionSegment) segment).map(optional -> optional);
         }
         throw new UnsupportedOperationException("unsupported TableSegment type: " + segment.getClass());
     }
@@ -99,6 +104,9 @@ public final class ExpressionConverter implements SQLSegmentConverter<Expression
         if (sqlNode instanceof SqlLiteral) {
             return new LiteralExpressionConverter().convertToSQLSegment(sqlNode).map(optional -> optional);
         }
+        if (sqlNode instanceof SqlDynamicParam) {
+            return new ParameterMarkerExpressionConverter().convertToSQLSegment(sqlNode).map(optional -> optional);
+        }
         return Optional.empty();
     }
     
diff --git a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/expression/impl/ColumnConverter.java b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/expression/impl/ColumnConverter.java
index 14e8934..f113666 100644
--- a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/expression/impl/ColumnConverter.java
+++ b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/expression/impl/ColumnConverter.java
@@ -49,7 +49,7 @@ public final class ColumnConverter implements SQLSegmentConverter<ColumnSegment,
         }
         ImmutableList<String> names = sqlIdentifier.names;
         if (1 == names.size()) {
-            return Optional.of(new ColumnSegment(getStartIndex(sqlIdentifier), getStopIndex(sqlIdentifier), new IdentifierValue(names.get(0))));    
+            return Optional.of(new ColumnSegment(getStartIndex(sqlIdentifier), getStopIndex(sqlIdentifier), new IdentifierValue(names.get(0))));
         }
         ColumnSegment result = new ColumnSegment(getStartIndex(sqlIdentifier), getStopIndex(sqlIdentifier), new IdentifierValue(names.get(1)));
         SqlIdentifier owner = sqlIdentifier.getComponent(0);
diff --git a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/projection/impl/ColumnProjectionConverter.java b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/expression/impl/ParameterMarkerExpressionConverter.java
similarity index 57%
copy from shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/projection/impl/ColumnProjectionConverter.java
copy to shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/expression/impl/ParameterMarkerExpressionConverter.java
index 9f48990..33ba472 100644
--- a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/projection/impl/ColumnProjectionConverter.java
+++ b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/expression/impl/ParameterMarkerExpressionConverter.java
@@ -15,27 +15,28 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.infra.optimize.converter.segment.projection.impl;
+package org.apache.shardingsphere.infra.optimize.converter.segment.expression.impl;
 
-import org.apache.calcite.sql.SqlIdentifier;
+import org.apache.calcite.sql.SqlDynamicParam;
+import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.parser.SqlParserPos;
 import org.apache.shardingsphere.infra.optimize.converter.segment.SQLSegmentConverter;
-import org.apache.shardingsphere.infra.optimize.converter.segment.expression.impl.ColumnConverter;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ColumnProjectionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.ParameterMarkerExpressionSegment;
 
 import java.util.Optional;
 
 /**
- * Column projection converter. 
+ * Parameter marker expression converter.
  */
-public final class ColumnProjectionConverter implements SQLSegmentConverter<ColumnProjectionSegment, SqlIdentifier> {
+public final class ParameterMarkerExpressionConverter implements SQLSegmentConverter<ParameterMarkerExpressionSegment, SqlNode> {
     
     @Override
-    public Optional<SqlIdentifier> convertToSQLNode(final ColumnProjectionSegment segment) {
-        return new ColumnConverter().convertToSQLNode(segment.getColumn());
+    public Optional<SqlNode> convertToSQLNode(final ParameterMarkerExpressionSegment segment) {
+        return Optional.of(new SqlDynamicParam(segment.getParameterMarkerIndex(), SqlParserPos.ZERO));
     }
     
     @Override
-    public Optional<ColumnProjectionSegment> convertToSQLSegment(final SqlIdentifier sqlNode) {
-        return new ColumnConverter().convertToSQLSegment(sqlNode).map(ColumnProjectionSegment::new);
+    public Optional<ParameterMarkerExpressionSegment> convertToSQLSegment(final SqlNode sqlNode) {
+        return Optional.of(new ParameterMarkerExpressionSegment(getStartIndex(sqlNode), getStopIndex(sqlNode), ((SqlDynamicParam) sqlNode).getIndex()));
     }
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/projection/ProjectionsConverter.java b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/projection/ProjectionsConverter.java
index c35f705..dbf0afd 100644
--- a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/projection/ProjectionsConverter.java
+++ b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/projection/ProjectionsConverter.java
@@ -19,6 +19,7 @@ package org.apache.shardingsphere.infra.optimize.converter.segment.projection;
 
 import org.apache.calcite.sql.SqlBasicCall;
 import org.apache.calcite.sql.SqlIdentifier;
+import org.apache.calcite.sql.SqlKind;
 import org.apache.calcite.sql.SqlNode;
 import org.apache.calcite.sql.SqlNodeList;
 import org.apache.calcite.sql.SqlOrderBy;
@@ -60,7 +61,7 @@ public final class ProjectionsConverter implements SQLSegmentConverter<Projectio
     
     private Optional<SqlNode> getProjectionSQLNode(final ProjectionSegment segment) {
         if (segment instanceof ColumnProjectionSegment) {
-            return new ColumnProjectionConverter().convertToSQLNode((ColumnProjectionSegment) segment).map(optional -> optional);
+            return new ColumnProjectionConverter().convertToSQLNode((ColumnProjectionSegment) segment);
         } else if (segment instanceof ExpressionProjectionSegment) {
             return new ExpressionProjectionConverter().convertToSQLNode((ExpressionProjectionSegment) segment);
         } else if (segment instanceof ShorthandProjectionSegment) {
@@ -81,12 +82,20 @@ public final class ProjectionsConverter implements SQLSegmentConverter<Projectio
             getProjectionSegment(each).ifPresent(projections::add);
         }
         int startIndex = projections.get(0).getStartIndex();
-        int stopIndex = projections.get(projections.size() - 1).getStopIndex();
+        int stopIndex = getProjectionsSegmentStopIndex(sqlNodeList.get(sqlNodeList.size() - 1), projections.get(projections.size() - 1));
         ProjectionsSegment result = new ProjectionsSegment(startIndex, stopIndex);
         result.getProjections().addAll(projections);
         return Optional.of(result);
     }
     
+    private int getProjectionsSegmentStopIndex(final SqlNode lastSqlNode, final ProjectionSegment projectionSegment) {
+        int stopIndex = projectionSegment.getStopIndex();
+        if (lastSqlNode instanceof SqlBasicCall && SqlKind.AS == ((SqlBasicCall) lastSqlNode).getOperator().getKind()) {
+            stopIndex = getStopIndex(((SqlBasicCall) lastSqlNode).getOperandList().get(1));
+        }
+        return stopIndex;
+    }
+    
     private Optional<ProjectionSegment> getProjectionSegment(final SqlNode sqlNode) {
         if (sqlNode instanceof SqlIdentifier) {
             SqlIdentifier sqlIdentifier = (SqlIdentifier) sqlNode;
@@ -99,6 +108,9 @@ public final class ProjectionsConverter implements SQLSegmentConverter<Projectio
             if (AggregationType.isAggregationType(sqlBasicCall.getOperator().getName())) {
                 return new AggregationProjectionConverter().convertToSQLSegment(sqlBasicCall).map(optional -> optional);
             }
+            if (null != sqlBasicCall.getOperator() && SqlKind.AS == sqlBasicCall.getOperator().getKind()) {
+                return new ColumnProjectionConverter().convertToSQLSegment(sqlNode).map(optional -> optional);
+            }
             return new ExpressionProjectionConverter().convertToSQLSegment(sqlNode).map(optional -> optional);
         } else if (sqlNode instanceof SqlSelect || sqlNode instanceof SqlOrderBy) {
             return new SubqueryProjectionConverter().convertToSQLSegment(sqlNode).map(optional -> optional);
diff --git a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/projection/impl/ColumnProjectionConverter.java b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/projection/impl/ColumnProjectionConverter.java
index 9f48990..e65cf6d 100644
--- a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/projection/impl/ColumnProjectionConverter.java
+++ b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/segment/projection/impl/ColumnProjectionConverter.java
@@ -17,25 +17,54 @@
 
 package org.apache.shardingsphere.infra.optimize.converter.segment.projection.impl;
 
+import org.apache.calcite.sql.SqlAsOperator;
+import org.apache.calcite.sql.SqlBasicCall;
 import org.apache.calcite.sql.SqlIdentifier;
+import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.parser.SqlParserPos;
 import org.apache.shardingsphere.infra.optimize.converter.segment.SQLSegmentConverter;
 import org.apache.shardingsphere.infra.optimize.converter.segment.expression.impl.ColumnConverter;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ColumnProjectionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
 
+import java.util.List;
 import java.util.Optional;
 
 /**
  * Column projection converter. 
  */
-public final class ColumnProjectionConverter implements SQLSegmentConverter<ColumnProjectionSegment, SqlIdentifier> {
+public final class ColumnProjectionConverter implements SQLSegmentConverter<ColumnProjectionSegment, SqlNode> {
     
     @Override
-    public Optional<SqlIdentifier> convertToSQLNode(final ColumnProjectionSegment segment) {
-        return new ColumnConverter().convertToSQLNode(segment.getColumn());
+    public Optional<SqlNode> convertToSQLNode(final ColumnProjectionSegment segment) {
+        if (segment.getAlias().isPresent()) {
+            Optional<SqlIdentifier> columnSqlIdentifier = new ColumnConverter().convertToSQLNode(segment.getColumn());
+            SqlIdentifier aliasSqlIdentifier = new SqlIdentifier(segment.getAlias().get(), SqlParserPos.ZERO);
+            return Optional.of(new SqlBasicCall(new SqlAsOperator(), new SqlNode[]{columnSqlIdentifier.get(), aliasSqlIdentifier}, SqlParserPos.ZERO));
+        }
+        return new ColumnConverter().convertToSQLNode(segment.getColumn()).map(optional -> optional);
     }
     
     @Override
-    public Optional<ColumnProjectionSegment> convertToSQLSegment(final SqlIdentifier sqlNode) {
-        return new ColumnConverter().convertToSQLSegment(sqlNode).map(ColumnProjectionSegment::new);
+    public Optional<ColumnProjectionSegment> convertToSQLSegment(final SqlNode sqlNode) {
+        if (sqlNode instanceof SqlBasicCall) {
+            List<SqlNode> operands = ((SqlBasicCall) sqlNode).getOperandList();
+            Optional<ColumnSegment> columnSegment = new ColumnConverter().convertToSQLSegment((SqlIdentifier) operands.get(0));
+            if (!columnSegment.isPresent()) {
+                return Optional.empty();
+            }
+            ColumnProjectionSegment columnProjectionSegment = new ColumnProjectionSegment(columnSegment.get());
+            if (2 == operands.size()) {
+                SqlIdentifier aliasSqlNode = (SqlIdentifier) operands.get(1);
+                columnProjectionSegment.setAlias(new AliasSegment(getStartIndex(aliasSqlNode), getStopIndex(aliasSqlNode), new IdentifierValue(aliasSqlNode.names.get(0))));
+            }
+            return Optional.of(columnProjectionSegment);
+        }
+        if (sqlNode instanceof SqlIdentifier) {
+            return new ColumnConverter().convertToSQLSegment((SqlIdentifier) sqlNode).map(ColumnProjectionSegment::new);
+        }
+        return Optional.empty();
     }
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/statement/SelectStatementConverter.java b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/statement/SelectStatementConverter.java
index 968e494..e3e2498 100644
--- a/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/statement/SelectStatementConverter.java
+++ b/shardingsphere-infra/shardingsphere-infra-optimize/src/main/java/org/apache/shardingsphere/infra/optimize/converter/statement/SelectStatementConverter.java
@@ -32,6 +32,8 @@ import org.apache.shardingsphere.infra.optimize.converter.segment.projection.Dis
 import org.apache.shardingsphere.infra.optimize.converter.segment.projection.ProjectionsConverter;
 import org.apache.shardingsphere.infra.optimize.converter.segment.where.WhereConverter;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.SQLSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BinaryOperationExpression;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.ParameterMarkerExpressionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionsSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.PaginationValueSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.limit.LimitSegment;
@@ -90,10 +92,30 @@ public final class SelectStatementConverter implements SQLStatementConverter<Sel
             new OrderByConverter().convertToSQLSegment(sqlOrderBy.orderList).ifPresent(result::setOrderBy);
             createLimitSegment(sqlOrderBy, context).ifPresent(result::setLimit);
         }
+        calculateParamCount(result, context);
         result.setParameterCount(context.getParameterCount().get());
         return result;
     }
     
+    private void calculateParamCount(final MySQLSelectStatement result, final ConverterContext context) {
+        result.getWhere().ifPresent(whereSegment -> {
+            if (whereSegment.getExpr() instanceof BinaryOperationExpression) {
+                if (((BinaryOperationExpression) whereSegment.getExpr()).getLeft() instanceof ParameterMarkerExpressionSegment 
+                        || ((BinaryOperationExpression) whereSegment.getExpr()).getRight() instanceof ParameterMarkerExpressionSegment) {
+                    context.getParameterCount().incrementAndGet();
+                }
+            }
+        });
+        result.getHaving().ifPresent(havingSegment -> {
+            if (havingSegment.getExpr() instanceof BinaryOperationExpression) {
+                if (((BinaryOperationExpression) havingSegment.getExpr()).getLeft() instanceof ParameterMarkerExpressionSegment
+                        || ((BinaryOperationExpression) havingSegment.getExpr()).getRight() instanceof ParameterMarkerExpressionSegment) {
+                    context.getParameterCount().incrementAndGet();
+                }
+            }
+        });
+    }
+    
     private Optional<LimitSegment> createLimitSegment(final SqlOrderBy sqlOrderBy, final ConverterContext context) {
         if (null == sqlOrderBy.offset && null == sqlOrderBy.fetch) {
             return Optional.empty();
diff --git a/shardingsphere-test/shardingsphere-optimize-test/src/test/java/org/apache/shardingsphere/infra/optimize/converter/parameterized/engine/SQLNodeConvertEngineParameterizedTest.java b/shardingsphere-test/shardingsphere-optimize-test/src/test/java/org/apache/shardingsphere/infra/optimize/converter/parameterized/engine/SQLNodeConvertEngineParameterizedTest.java
index 024042d..c46407b 100644
--- a/shardingsphere-test/shardingsphere-optimize-test/src/test/java/org/apache/shardingsphere/infra/optimize/converter/parameterized/engine/SQLNodeConvertEngineParameterizedTest.java
+++ b/shardingsphere-test/shardingsphere-optimize-test/src/test/java/org/apache/shardingsphere/infra/optimize/converter/parameterized/engine/SQLNodeConvertEngineParameterizedTest.java
@@ -83,6 +83,7 @@ public final class SQLNodeConvertEngineParameterizedTest {
         SUPPORTED_SQL_CASE_IDS.add("select_group_by_with_limit");
         SUPPORTED_SQL_CASE_IDS.add("select_left_outer_join_related_with_alias");
         SUPPORTED_SQL_CASE_IDS.add("select_right_outer_join_related_with_alias");
+        SUPPORTED_SQL_CASE_IDS.add("select_alias_as_keyword");
     }
     
     private final String sqlCaseId;