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 2022/01/04 02:17:57 UTC

[shardingsphere] branch master updated: support concat method, improve in expression convert (#14492)

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 d2b2eac  support concat method, improve in expression convert (#14492)
d2b2eac is described below

commit d2b2eacfc5d6a7724e7344cc94475a251a3b0bfc
Author: liguoping <xd...@163.com>
AuthorDate: Tue Jan 4 10:17:08 2022 +0800

    support concat method, improve in expression convert (#14492)
    
    * commit
    
    * concat 暂存
    
    * subquery specially
    
    * code style
---
 .../segment/expression/ExpressionConverter.java      | 11 ++++++++---
 .../segment/expression/impl/FunctionConverter.java   | 20 +++++++++++++++++++-
 .../expression/impl/InExpressionConverter.java       | 15 +++++++++++++--
 .../expression/impl/ListExpressionConverter.java     | 11 +++++++++++
 .../impl/AggregationProjectionConverter.java         | 19 +++++++++++++++----
 .../SQLNodeConvertEngineParameterizedTest.java       |  1 +
 6 files changed, 67 insertions(+), 10 deletions(-)

diff --git a/shardingsphere-infra/shardingsphere-infra-federation/shardingsphere-infra-federation-optimizer/src/main/java/org/apache/shardingsphere/infra/federation/optimizer/converter/segment/expression/ExpressionConverter.java b/shardingsphere-infra/shardingsphere-infra-federation/shardingsphere-infra-federation-optimizer/src/main/java/org/apache/shardingsphere/infra/federation/optimizer/converter/segment/expression/ExpressionConverter.java
index ee594af..395c7c1 100644
--- a/shardingsphere-infra/shardingsphere-infra-federation/shardingsphere-infra-federation-optimizer/src/main/java/org/apache/shardingsphere/infra/federation/optimizer/converter/segment/expression/ExpressionConverter.java
+++ b/shardingsphere-infra/shardingsphere-infra-federation/shardingsphere-infra-federation-optimizer/src/main/java/org/apache/shardingsphere/infra/federation/optimizer/converter/segment/expression/ExpressionConverter.java
@@ -23,8 +23,10 @@ import org.apache.calcite.sql.SqlDynamicParam;
 import org.apache.calcite.sql.SqlIdentifier;
 import org.apache.calcite.sql.SqlLiteral;
 import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.SqlNodeList;
 import org.apache.calcite.sql.SqlOperator;
 import org.apache.calcite.sql.SqlSelect;
+import org.apache.calcite.sql.SqlUnresolvedFunction;
 import org.apache.calcite.sql.fun.SqlBetweenOperator;
 import org.apache.calcite.sql.fun.SqlCastFunction;
 import org.apache.calcite.sql.fun.SqlInOperator;
@@ -73,7 +75,7 @@ public final class ExpressionConverter implements SQLSegmentConverter<Expression
             // TODO 
             throw new UnsupportedOperationException("unsupported CommonExpressionSegment");
         } else if (segment instanceof ListExpression) {
-            return new ListExpressionConverter().convertToSQLNode((ListExpression) segment);
+            return new ListExpressionConverter().convertToSQLNode((ListExpression) segment).map(optional -> optional);
         } else if (segment instanceof BinaryOperationExpression) {
             return new BinaryOperationExpressionConverter().convertToSQLNode((BinaryOperationExpression) segment).map(optional -> optional);
         } else if (segment instanceof ColumnSegment) {
@@ -97,7 +99,7 @@ public final class ExpressionConverter implements SQLSegmentConverter<Expression
     @Override
     public Optional<ExpressionSegment> convertToSQLSegment(final SqlNode sqlNode) {
         if (null == sqlNode) {
-            return Optional.empty(); 
+            return Optional.empty();
         }
         if (sqlNode instanceof SqlIdentifier) {
             return new ColumnConverter().convertToSQLSegment((SqlIdentifier) sqlNode).map(optional -> optional);
@@ -114,6 +116,9 @@ public final class ExpressionConverter implements SQLSegmentConverter<Expression
         if (sqlNode instanceof SqlDynamicParam) {
             return new ParameterMarkerExpressionConverter().convertToSQLSegment(sqlNode).map(optional -> optional);
         }
+        if (sqlNode instanceof SqlNodeList) {
+            return new ListExpressionConverter().convertToSQLSegment(sqlNode).map(optional -> optional);
+        }
         return Optional.empty();
     }
     
@@ -137,7 +142,7 @@ public final class ExpressionConverter implements SQLSegmentConverter<Expression
         if (operator instanceof SqlBinaryOperator || operator instanceof SqlLikeOperator) {
             return new BinaryOperationExpressionConverter().convertToSQLSegment(sqlBasicCall).map(optional -> optional);
         }
-        if (operator instanceof SqlPositionFunction || operator instanceof SqlCastFunction) {
+        if (operator instanceof SqlPositionFunction || operator instanceof SqlCastFunction || operator instanceof SqlUnresolvedFunction) {
             return new FunctionConverter().convertToSQLSegment(sqlBasicCall).map(optional -> optional);
         }
         return Optional.empty();
diff --git a/shardingsphere-infra/shardingsphere-infra-federation/shardingsphere-infra-federation-optimizer/src/main/java/org/apache/shardingsphere/infra/federation/optimizer/converter/segment/expression/impl/FunctionConverter.java b/shardingsphere-infra/shardingsphere-infra-federation/shardingsphere-infra-federation-optimizer/src/main/java/org/apache/shardingsphere/infra/federation/optimizer/converter/segment/expression/impl/FunctionConverter.java
index f1c79bf..abbda47 100644
--- a/shardingsphere-infra/shardingsphere-infra-federation/shardingsphere-infra-federation-optimizer/src/main/java/org/apache/shardingsphere/infra/federation/optimizer/converter/segment/expression/impl/FunctionConverter.java
+++ b/shardingsphere-infra/shardingsphere-infra-federation/shardingsphere-infra-federation-optimizer/src/main/java/org/apache/shardingsphere/infra/federation/optimizer/converter/segment/expression/impl/FunctionConverter.java
@@ -20,16 +20,23 @@ package org.apache.shardingsphere.infra.federation.optimizer.converter.segment.e
 import org.apache.calcite.sql.SqlBasicCall;
 import org.apache.calcite.sql.SqlCharStringLiteral;
 import org.apache.calcite.sql.SqlDataTypeSpec;
+import org.apache.calcite.sql.SqlDynamicParam;
+import org.apache.calcite.sql.SqlFunctionCategory;
+import org.apache.calcite.sql.SqlIdentifier;
 import org.apache.calcite.sql.SqlLiteral;
 import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.SqlOperator;
+import org.apache.calcite.sql.SqlUnresolvedFunction;
 import org.apache.calcite.sql.SqlUserDefinedTypeNameSpec;
 import org.apache.calcite.sql.fun.SqlCastFunction;
 import org.apache.calcite.sql.fun.SqlPositionFunction;
 import org.apache.calcite.sql.parser.SqlParserPos;
+import org.apache.shardingsphere.infra.federation.optimizer.converter.context.ConverterContextHolder;
 import org.apache.shardingsphere.infra.federation.optimizer.converter.segment.SQLSegmentConverter;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.FunctionSegment;
 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.generic.DataTypeSegment;
 
 import java.util.ArrayList;
@@ -50,6 +57,10 @@ public final class FunctionConverter implements SQLSegmentConverter<FunctionSegm
         if ("CAST".equalsIgnoreCase(segment.getFunctionName())) {
             return Optional.of(new SqlBasicCall(new SqlCastFunction(), getSqlNodes(segment.getParameters()), SqlParserPos.ZERO));
         }
+        if ("CONCAT".equalsIgnoreCase(segment.getFunctionName())) {
+            return Optional.of(new SqlBasicCall(new SqlUnresolvedFunction(new SqlIdentifier("CONCAT", SqlParserPos.ZERO), 
+                    null, null, null, null, SqlFunctionCategory.USER_DEFINED_FUNCTION), getSqlNodes(segment.getParameters()), SqlParserPos.ZERO));
+        }
         return Optional.empty();
     }
     
@@ -64,7 +75,8 @@ public final class FunctionConverter implements SQLSegmentConverter<FunctionSegm
     }
     
     private String getFunctionText(final SqlBasicCall sqlBasicCall) {
-        if (null != sqlBasicCall.getOperator() && sqlBasicCall.getOperator() instanceof SqlCastFunction) {
+        SqlOperator operator;
+        if (null != (operator = sqlBasicCall.getOperator()) && (operator instanceof SqlCastFunction || operator instanceof SqlUnresolvedFunction)) {
             return sqlBasicCall.toString().replace("`", "");
         }
         return sqlBasicCall.toString();
@@ -81,6 +93,9 @@ public final class FunctionConverter implements SQLSegmentConverter<FunctionSegm
                 result.add(dataTypeSegment);
             } else if (operand instanceof SqlCharStringLiteral) {
                 result.add(new LiteralExpressionSegment(getStartIndex(operand), getStopIndex(operand), operand.toString().replace("'", "")));
+            } else if (operand instanceof SqlDynamicParam) {
+                ConverterContextHolder.get().getParameterCount().getAndIncrement();
+                result.add(new ParameterMarkerExpressionSegment(getStartIndex(operand), getStopIndex(operand), ((SqlDynamicParam) operand).getIndex()));
             }
         });
         return result;
@@ -95,6 +110,9 @@ public final class FunctionConverter implements SQLSegmentConverter<FunctionSegm
             if (sqlSegment instanceof DataTypeSegment) {
                 sqlNodes.add(new SqlDataTypeSpec(new SqlUserDefinedTypeNameSpec(((DataTypeSegment) sqlSegment).getDataTypeName(), SqlParserPos.ZERO), SqlParserPos.ZERO));
             }
+            if (sqlSegment instanceof ParameterMarkerExpressionSegment) {
+                sqlNodes.add(new SqlDynamicParam(((ParameterMarkerExpressionSegment) sqlSegment).getParameterMarkerIndex(), SqlParserPos.ZERO));
+            }
         });
         return sqlNodes.toArray(new SqlNode[0]);
     }
diff --git a/shardingsphere-infra/shardingsphere-infra-federation/shardingsphere-infra-federation-optimizer/src/main/java/org/apache/shardingsphere/infra/federation/optimizer/converter/segment/expression/impl/InExpressionConverter.java b/shardingsphere-infra/shardingsphere-infra-federation/shardingsphere-infra-federation-optimizer/src/main/java/org/apache/shardingsphere/infra/federation/optimizer/converter/segment/expression/impl/InExpressionConverter.java
index 04d7a7c..7b57ef0 100644
--- a/shardingsphere-infra/shardingsphere-infra-federation/shardingsphere-infra-federation-optimizer/src/main/java/org/apache/shardingsphere/infra/federation/optimizer/converter/segment/expression/impl/InExpressionConverter.java
+++ b/shardingsphere-infra/shardingsphere-infra-federation/shardingsphere-infra-federation-optimizer/src/main/java/org/apache/shardingsphere/infra/federation/optimizer/converter/segment/expression/impl/InExpressionConverter.java
@@ -20,6 +20,8 @@ package org.apache.shardingsphere.infra.federation.optimizer.converter.segment.e
 import lombok.RequiredArgsConstructor;
 import org.apache.calcite.sql.SqlBasicCall;
 import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.SqlNodeList;
+import org.apache.calcite.sql.SqlSelect;
 import org.apache.calcite.sql.fun.SqlStdOperatorTable;
 import org.apache.calcite.sql.parser.SqlParserPos;
 import org.apache.shardingsphere.infra.federation.optimizer.converter.segment.SQLSegmentConverter;
@@ -27,6 +29,7 @@ import org.apache.shardingsphere.infra.federation.optimizer.converter.segment.ex
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.InExpression;
 
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.LinkedList;
 import java.util.Optional;
@@ -51,7 +54,14 @@ public final class InExpressionConverter implements SQLSegmentConverter<InExpres
         Collection<SqlNode> sqlNodes = new LinkedList<>();
         ExpressionConverter expressionConverter = new ExpressionConverter();
         expressionConverter.convertToSQLNode(expression.getLeft()).ifPresent(sqlNodes::add);
-        expressionConverter.convertToSQLNode(expression.getRight()).ifPresent(sqlNodes::add);
+        expressionConverter.convertToSQLNode(expression.getRight()).ifPresent(sqlNode -> {
+            if (sqlNode instanceof SqlBasicCall) {
+                SqlNodeList sqlNodeList = new SqlNodeList(Arrays.asList(((SqlBasicCall) sqlNode).getOperands().clone()), SqlParserPos.ZERO);
+                sqlNodes.add(sqlNodeList);
+            } else {
+                sqlNodes.add(sqlNode);
+            }
+        });
         SqlBasicCall sqlNode = new SqlBasicCall(SqlStdOperatorTable.IN, sqlNodes.toArray(new SqlNode[]{}), SqlParserPos.ZERO);
         return expression.isNot() ? Optional.of(new SqlBasicCall(SqlStdOperatorTable.NOT, new SqlNode[]{sqlNode}, SqlParserPos.ZERO)) : Optional.of(sqlNode);
     }
@@ -64,6 +74,7 @@ public final class InExpressionConverter implements SQLSegmentConverter<InExpres
         ExpressionConverter expressionConverter = new ExpressionConverter();
         ExpressionSegment left = expressionConverter.convertToSQLSegment(sqlBasicCall.getOperandList().get(0)).orElseThrow(IllegalStateException::new);
         ExpressionSegment right = expressionConverter.convertToSQLSegment(sqlBasicCall.getOperandList().get(1)).orElseThrow(IllegalStateException::new);
-        return Optional.of(new InExpression(getStartIndex(sqlBasicCall), getStopIndex(sqlBasicCall) + 1, left, right, not));
+        return Optional.of(new InExpression(getStartIndex(sqlBasicCall), 
+                sqlBasicCall.getOperandList().get(1) instanceof SqlSelect ? getStopIndex(sqlBasicCall) + 1 : getStopIndex(sqlBasicCall), left, right, not));
     }
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-federation/shardingsphere-infra-federation-optimizer/src/main/java/org/apache/shardingsphere/infra/federation/optimizer/converter/segment/expression/impl/ListExpressionConverter.java b/shardingsphere-infra/shardingsphere-infra-federation/shardingsphere-infra-federation-optimizer/src/main/java/org/apache/shardingsphere/infra/federation/optimizer/converter/segment/expression/impl/ListExpressionConverter.java
index cd28447..ab9968c 100644
--- a/shardingsphere-infra/shardingsphere-infra-federation/shardingsphere-infra-federation-optimizer/src/main/java/org/apache/shardingsphere/infra/federation/optimizer/converter/segment/expression/impl/ListExpressionConverter.java
+++ b/shardingsphere-infra/shardingsphere-infra-federation/shardingsphere-infra-federation-optimizer/src/main/java/org/apache/shardingsphere/infra/federation/optimizer/converter/segment/expression/impl/ListExpressionConverter.java
@@ -19,6 +19,7 @@ package org.apache.shardingsphere.infra.federation.optimizer.converter.segment.e
 
 import org.apache.calcite.sql.SqlBasicCall;
 import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.SqlNodeList;
 import org.apache.calcite.sql.fun.SqlStdOperatorTable;
 import org.apache.calcite.sql.parser.SqlParserPos;
 import org.apache.shardingsphere.infra.federation.optimizer.converter.segment.SQLSegmentConverter;
@@ -26,6 +27,7 @@ import org.apache.shardingsphere.infra.federation.optimizer.converter.segment.ex
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ListExpression;
 
+import java.util.List;
 import java.util.Optional;
 
 /**
@@ -52,6 +54,15 @@ public final class ListExpressionConverter implements SQLSegmentConverter<ListEx
     
     @Override
     public Optional<ListExpression> convertToSQLSegment(final SqlNode sqlNode) {
+        if (null == sqlNode) {
+            return Optional.empty();
+        }
+        if (sqlNode instanceof SqlNodeList) {
+            List<SqlNode> items = ((SqlNodeList) sqlNode).getList();
+            ListExpression result = new ListExpression(getStartIndex(sqlNode), getStopIndex(sqlNode));
+            items.forEach(item -> new ExpressionConverter().convertToSQLSegment(item).ifPresent(result.getItems()::add));
+            return Optional.of(result);
+        }
         return Optional.empty();
     }
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-federation/shardingsphere-infra-federation-optimizer/src/main/java/org/apache/shardingsphere/infra/federation/optimizer/converter/segment/projection/impl/AggregationProjectionConverter.java b/shardingsphere-infra/shardingsphere-infra-federation/shardingsphere-infra-federation-optimizer/src/main/java/org/apache/shardingsphere/infra/federation/optimizer/converter/segment/projection/impl/AggregationProjectionConverter.java
index 8fadfc2..e9a0bf8 100644
--- a/shardingsphere-infra/shardingsphere-infra-federation/shardingsphere-infra-federation-optimizer/src/main/java/org/apache/shardingsphere/infra/federation/optimizer/converter/segment/projection/impl/AggregationProjectionConverter.java
+++ b/shardingsphere-infra/shardingsphere-infra-federation/shardingsphere-infra-federation-optimizer/src/main/java/org/apache/shardingsphere/infra/federation/optimizer/converter/segment/projection/impl/AggregationProjectionConverter.java
@@ -77,11 +77,11 @@ public final class AggregationProjectionConverter implements SQLSegmentConverter
         }
         if (segment.getAlias().isPresent()) {
             return Optional.of(new SqlBasicCall(SqlStdOperatorTable.AS, new SqlNode[]{new SqlBasicCall(convertOperator(segment.getType().name()), 
-                    new SqlNode[]{SqlIdentifier.star(parameters, SqlParserPos.ZERO, Collections.singletonList(SqlParserPos.ZERO))}, SqlParserPos.ZERO, false, functionQuantifier),
+                    new SqlNode[]{createParametersSqlNode(parameters)}, SqlParserPos.ZERO, false, functionQuantifier),
                     SqlIdentifier.star(Collections.singletonList(segment.getAlias().get()), SqlParserPos.ZERO, Collections.singletonList(SqlParserPos.ZERO))}, SqlParserPos.ZERO));
         }
-        return Optional.of(new SqlBasicCall(convertOperator(segment.getType().name()), 
-                new SqlNode[]{SqlIdentifier.star(parameters, SqlParserPos.ZERO, Collections.singletonList(SqlParserPos.ZERO))}, SqlParserPos.ZERO, false, functionQuantifier));
+        return Optional.of(new SqlBasicCall(convertOperator(segment.getType().name()),
+                new SqlNode[]{createParametersSqlNode(parameters)}, SqlParserPos.ZERO, false, functionQuantifier));
     }
     
     @Override
@@ -91,7 +91,7 @@ public final class AggregationProjectionConverter implements SQLSegmentConverter
         }
         if (isAsOperatorAggregationType(sqlBasicCall)) {
             SqlBasicCall subSqlBasicCall = (SqlBasicCall) sqlBasicCall.getOperandList().get(0);
-            AggregationType aggregationType = AggregationType.valueOf(subSqlBasicCall.getOperator().getName());
+            AggregationType aggregationType = AggregationType.valueOf(subSqlBasicCall.getOperator().getName().toUpperCase());
             String innerExpression = getInnerExpression(subSqlBasicCall);
             AliasSegment aliasSegment = new AliasSegment(getStartIndex(sqlBasicCall.getOperandList().get(1)), getStopIndex(sqlBasicCall.getOperandList().get(1)), 
                     new IdentifierValue(((SqlIdentifier) sqlBasicCall.getOperandList().get(1)).names.get(0)));
@@ -148,4 +148,15 @@ public final class AggregationProjectionConverter implements SQLSegmentConverter
                 && sqlBasicCall.getOperandList().get(0) instanceof SqlBasicCall
                 && AggregationType.isAggregationType(((SqlBasicCall) sqlBasicCall.getOperandList().get(0)).getOperator().getName());
     }
+    
+    private SqlNode createParametersSqlNode(final List<String> parameters) {
+        if (1 == parameters.size()) {
+            try {
+                Long.parseLong(parameters.get(0));
+                return SqlLiteral.createExactNumeric(parameters.get(0), SqlParserPos.ZERO);
+            } catch (NumberFormatException ignored) {
+            }
+        }
+        return SqlIdentifier.star(parameters, SqlParserPos.ZERO, Collections.singletonList(SqlParserPos.ZERO));
+    }
 }
diff --git a/shardingsphere-test/shardingsphere-optimize-test/src/test/java/org/apache/shardingsphere/infra/federation/converter/parameterized/engine/SQLNodeConvertEngineParameterizedTest.java b/shardingsphere-test/shardingsphere-optimize-test/src/test/java/org/apache/shardingsphere/infra/federation/converter/parameterized/engine/SQLNodeConvertEngineParameterizedTest.java
index 8a03dcf..98e77ef 100644
--- a/shardingsphere-test/shardingsphere-optimize-test/src/test/java/org/apache/shardingsphere/infra/federation/converter/parameterized/engine/SQLNodeConvertEngineParameterizedTest.java
+++ b/shardingsphere-test/shardingsphere-optimize-test/src/test/java/org/apache/shardingsphere/infra/federation/converter/parameterized/engine/SQLNodeConvertEngineParameterizedTest.java
@@ -95,6 +95,7 @@ public final class SQLNodeConvertEngineParameterizedTest {
         SUPPORTED_SQL_CASE_IDS.add("select_with_union");
         SUPPORTED_SQL_CASE_IDS.add("select_cast_function");
         SUPPORTED_SQL_CASE_IDS.add("select_with_same_table_name_and_alias");
+        SUPPORTED_SQL_CASE_IDS.add("select_count_like_concat");
     }
     
     private final String sqlCaseId;