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 77f43c39d64 support oracle page with parameter cal expression (#30299)
77f43c39d64 is described below

commit 77f43c39d64bd341d75f92f04f2514cc5486a9e6
Author: Chuxin Chen <[email protected]>
AuthorDate: Tue Feb 27 09:09:39 2024 +0800

    support oracle page with parameter cal expression (#30299)
    
    * support oracle page with parameter cal expression
    
    * support oracle page with parameter cal expression
---
 .../select/pagination/PaginationContext.java       |  6 ++
 .../engine/RowNumberPaginationContextEngine.java   | 11 ++-
 .../rownum/ExpressionRowNumberValueSegment.java    | 78 ++++++++++++++++++++++
 .../ExpressionRowNumberValueSegmentTest.java       | 53 +++++++++++++++
 4 files changed, 145 insertions(+), 3 deletions(-)

diff --git 
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/pagination/PaginationContext.java
 
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/pagination/PaginationContext.java
index 8fb79ddb64b..d6530bcc86f 100644
--- 
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/pagination/PaginationContext.java
+++ 
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/pagination/PaginationContext.java
@@ -23,6 +23,7 @@ import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.Nu
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.PaginationValueSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.ParameterMarkerPaginationValueSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.limit.LimitValueSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.rownum.ExpressionRowNumberValueSegment;
 
 import java.util.List;
 import java.util.Optional;
@@ -56,6 +57,9 @@ public final class PaginationContext {
             Object obj = null == params || params.isEmpty() ? 0L : 
params.get(((ParameterMarkerPaginationValueSegment) 
paginationValueSegment).getParameterIndex());
             return obj instanceof Long ? (long) obj : (int) obj;
         }
+        if (paginationValueSegment instanceof ExpressionRowNumberValueSegment) 
{
+            return ((ExpressionRowNumberValueSegment) 
paginationValueSegment).getValue(params);
+        }
         return ((NumberLiteralPaginationValueSegment) 
paginationValueSegment).getValue();
     }
     
@@ -107,6 +111,7 @@ public final class PaginationContext {
      * @return offset parameter index
      */
     public Optional<Integer> getOffsetParameterIndex() {
+        // TODO handle offsetSegment instance of 
ExpressionRowNumberValueSegment
         return offsetSegment instanceof ParameterMarkerPaginationValueSegment 
? Optional.of(((ParameterMarkerPaginationValueSegment) 
offsetSegment).getParameterIndex()) : Optional.empty();
     }
     
@@ -116,6 +121,7 @@ public final class PaginationContext {
      * @return row count parameter index
      */
     public Optional<Integer> getRowCountParameterIndex() {
+        // TODO handle offsetSegment instance of 
ExpressionRowNumberValueSegment
         return rowCountSegment instanceof ParameterMarkerPaginationValueSegment
                 ? Optional.of(((ParameterMarkerPaginationValueSegment) 
rowCountSegment).getParameterIndex())
                 : Optional.empty();
diff --git 
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/pagination/engine/RowNumberPaginationContextEngine.java
 
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/pagination/engine/RowNumberPaginationContextEngine.java
index 72d266e396a..2cc26aaa460 100644
--- 
a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/pagination/engine/RowNumberPaginationContextEngine.java
+++ 
b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/pagination/engine/RowNumberPaginationContextEngine.java
@@ -24,6 +24,7 @@ import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BinaryOp
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
 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.pagination.rownum.ExpressionRowNumberValueSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.rownum.NumberLiteralRowNumberValueSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.rownum.ParameterMarkerRowNumberValueSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.rownum.RowNumberValueSegment;
@@ -137,8 +138,12 @@ public final class RowNumberPaginationContextEngine {
     private RowNumberValueSegment createRowNumberValueSegment(final 
ExpressionSegment expression, final boolean boundOpened) {
         int startIndex = expression.getStartIndex();
         int stopIndex = expression.getStopIndex();
-        return expression instanceof LiteralExpressionSegment
-                ? new NumberLiteralRowNumberValueSegment(startIndex, 
stopIndex, (int) ((LiteralExpressionSegment) expression).getLiterals(), 
boundOpened)
-                : new ParameterMarkerRowNumberValueSegment(startIndex, 
stopIndex, ((ParameterMarkerExpressionSegment) 
expression).getParameterMarkerIndex(), boundOpened);
+        if (expression instanceof LiteralExpressionSegment) {
+            return new NumberLiteralRowNumberValueSegment(startIndex, 
stopIndex, (int) ((LiteralExpressionSegment) expression).getLiterals(), 
boundOpened);
+        }
+        if (expression instanceof ParameterMarkerExpressionSegment) {
+            return new ParameterMarkerRowNumberValueSegment(startIndex, 
stopIndex, ((ParameterMarkerExpressionSegment) 
expression).getParameterMarkerIndex(), boundOpened);
+        }
+        return new ExpressionRowNumberValueSegment(startIndex, stopIndex, 
expression, boundOpened);
     }
 }
diff --git 
a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/pagination/rownum/ExpressionRowNumberValueSegment.java
 
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/pagination/rownum/ExpressionRowNumberValueSegment.java
new file mode 100644
index 00000000000..c077ec46a06
--- /dev/null
+++ 
b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/pagination/rownum/ExpressionRowNumberValueSegment.java
@@ -0,0 +1,78 @@
+/*
+ * 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.shardingsphere.sql.parser.sql.common.segment.dml.pagination.rownum;
+
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BinaryOperationExpression;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
+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 java.util.List;
+
+/**
+ * Row number value segment for expression.
+ */
+public final class ExpressionRowNumberValueSegment extends 
RowNumberValueSegment {
+    
+    private final ExpressionSegment expressionSegment;
+    
+    public ExpressionRowNumberValueSegment(final int startIndex, final int 
stopIndex, final ExpressionSegment expressionSegment, final boolean 
boundOpened) {
+        super(startIndex, stopIndex, boundOpened);
+        this.expressionSegment = expressionSegment;
+    }
+    
+    /**
+     * Get value.
+     *
+     * @param params parameters
+     * @return value
+     */
+    public Long getValue(final List<Object> params) {
+        return getValueFromExpression(expressionSegment, params);
+    }
+    
+    private Long getValueFromExpression(final ExpressionSegment 
expressionSegment, final List<Object> params) {
+        if (expressionSegment instanceof ParameterMarkerExpressionSegment) {
+            return null == params || params.isEmpty() ? 0L : 
Long.parseLong(params.get(((ParameterMarkerExpressionSegment) 
expressionSegment).getParameterMarkerIndex()).toString());
+        }
+        if (expressionSegment instanceof BinaryOperationExpression) {
+            return 
getValueFromBinaryOperationExpression((BinaryOperationExpression) 
expressionSegment, params);
+        }
+        if (expressionSegment instanceof LiteralExpressionSegment) {
+            return Long.parseLong(expressionSegment.getText());
+        }
+        throw new UnsupportedOperationException(String.format("Unsupported 
expression: %s in page expression", expressionSegment.getClass().getName()));
+    }
+    
+    private Long getValueFromBinaryOperationExpression(final 
BinaryOperationExpression binaryOperationExpression, final List<Object> params) 
{
+        String operator = binaryOperationExpression.getOperator();
+        Long leftValue = 
getValueFromExpression(binaryOperationExpression.getLeft(), params);
+        Long rightValue = 
getValueFromExpression(binaryOperationExpression.getRight(), params);
+        switch (operator) {
+            case "+":
+                return leftValue + rightValue;
+            case "-":
+                return leftValue - rightValue;
+            case "*":
+                return leftValue * rightValue;
+            case "/":
+                return leftValue / rightValue;
+            default:
+                throw new 
UnsupportedOperationException(String.format("Unsupported operator: %s in page 
expression", operator));
+        }
+    }
+}
diff --git 
a/parser/sql/statement/src/test/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/pagination/rownum/ExpressionRowNumberValueSegmentTest.java
 
b/parser/sql/statement/src/test/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/pagination/rownum/ExpressionRowNumberValueSegmentTest.java
new file mode 100644
index 00000000000..0bb916e20f2
--- /dev/null
+++ 
b/parser/sql/statement/src/test/java/org/apache/shardingsphere/sql/parser/sql/common/segment/dml/pagination/rownum/ExpressionRowNumberValueSegmentTest.java
@@ -0,0 +1,53 @@
+/*
+ * 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.shardingsphere.sql.parser.sql.common.segment.dml.pagination.rownum;
+
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BinaryOperationExpression;
+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.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+class ExpressionRowNumberValueSegmentTest {
+    
+    @Test
+    void assertGetValueWithLiteralExpression() {
+        ExpressionRowNumberValueSegment actual = new 
ExpressionRowNumberValueSegment(0, 0, new BinaryOperationExpression(0, 0, new 
LiteralExpressionSegment(0, 0, 1),
+                new LiteralExpressionSegment(0, 0, 1), "+", "1 + 1"), false);
+        assertThat(actual.getValue(Collections.emptyList()), is(2L));
+    }
+    
+    @Test
+    void assertGetValueWithParameterMarker() {
+        ExpressionRowNumberValueSegment actual = new 
ExpressionRowNumberValueSegment(0, 0, new BinaryOperationExpression(0, 0, new 
ParameterMarkerExpressionSegment(0, 0, 0),
+                new ParameterMarkerExpressionSegment(0, 0, 1), "+", "? + ?"), 
false);
+        assertThat(actual.getValue(Arrays.asList(1, 1)), is(2L));
+    }
+    
+    @Test
+    void assertGetValueWithMixed() {
+        ExpressionRowNumberValueSegment actual = new 
ExpressionRowNumberValueSegment(0, 0, new BinaryOperationExpression(0, 0, new 
LiteralExpressionSegment(0, 0, 1),
+                new BinaryOperationExpression(0, 0, new 
ParameterMarkerExpressionSegment(0, 0, 0), new LiteralExpressionSegment(0, 0, 
2), "+", "? + 2"), "+", "1 + ? + 2"), false);
+        assertThat(actual.getValue(Collections.singletonList(1)), is(4L));
+    }
+}

Reply via email to