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 4ce37f5a1cd Support '2'::int statement in PostgreSQL and openGauss 
(#37962)
4ce37f5a1cd is described below

commit 4ce37f5a1cd4efba9154da946794fd11a9e5b0f1
Author: Claire <[email protected]>
AuthorDate: Sun Feb 8 10:34:05 2026 +0800

    Support '2'::int statement in PostgreSQL and openGauss (#37962)
    
    * support new function
    
    * realese-notes
    
    * npe
    
    * npe
    
    * support Expression
    
    * support new function
    
    * update code
    
    * update code
---
 RELEASE-NOTES.md                                   |   1 +
 .../select/pagination/PaginationContext.java       |  71 +++++++
 .../segment/limit/PaginationValueSQLConverter.java |  12 +-
 .../main/antlr4/imports/opengauss/DMLStatement.g4  |   6 +-
 .../statement/OpenGaussStatementVisitor.java       |  39 ++--
 .../main/antlr4/imports/postgresql/DMLStatement.g4 |   6 +-
 .../statement/PostgreSQLStatementVisitor.java      |  39 ++--
 .../ExpressionPaginationValueSegment.java          |  28 +--
 .../limit/ExpressionLimitValueSegment.java         |  25 +--
 .../asserts/segment/limit/LimitClauseAssert.java   |   5 +
 .../impl/limit/ExpectedPaginationValue.java        |   3 +
 .../parser/src/main/resources/case/dml/select.xml  | 225 +++++++++++++++++++++
 .../main/resources/sql/supported/dml/select.xml    |  16 ++
 13 files changed, 401 insertions(+), 75 deletions(-)

diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md
index 57ebd82d78b..7d1c30cdca7 100644
--- a/RELEASE-NOTES.md
+++ b/RELEASE-NOTES.md
@@ -10,6 +10,7 @@
 2. SQL Parser: Fix escape '\' in SQL causing DialectSQLParsingException - 
[#37943](https://github.com/apache/shardingsphere/pull/37943)
 3. SQL Parser: Fix error parsing \l command SQL statement when front-end 
protocol is og - [#37953](https://github.com/apache/shardingsphere/pull/37953)
 4. SQL Parser:Fix SQLParsingException when using reserved word `order` in 
ORDER BY clause - [#37958](https://github.com/apache/shardingsphere/pull/37958)
+5. SQL Parser:Support '2'::int statement in PostgreSQL and openGauss - 
[#37962](https://github.com/apache/shardingsphere/pull/37962)
 
 ## Release 5.5.3
 
diff --git 
a/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/pagination/PaginationContext.java
 
b/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/pagination/PaginationContext.java
index a468039d49a..d269e8a849a 100644
--- 
a/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/pagination/PaginationContext.java
+++ 
b/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/pagination/PaginationContext.java
@@ -19,9 +19,15 @@ package 
org.apache.shardingsphere.infra.binder.context.segment.select.pagination
 
 import lombok.Getter;
 import 
org.apache.shardingsphere.infra.binder.context.statement.type.dml.SelectStatementContext;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.BinaryOperationExpression;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.CaseWhenExpression;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.ExpressionSegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.simple.LiteralExpressionSegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.simple.ParameterMarkerExpressionSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.NumberLiteralPaginationValueSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.PaginationValueSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.ParameterMarkerPaginationValueSegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.ExpressionPaginationValueSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.limit.LimitValueSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.rownum.ExpressionRowNumberValueSegment;
 
@@ -63,9 +69,74 @@ public final class PaginationContext {
         if (paginationValueSegment instanceof ExpressionRowNumberValueSegment) 
{
             return ((ExpressionRowNumberValueSegment) 
paginationValueSegment).getValue(params);
         }
+        if (paginationValueSegment instanceof 
ExpressionPaginationValueSegment) {
+            Long result = 
getValueFromExpression(((ExpressionPaginationValueSegment) 
paginationValueSegment).getExpression(), params);
+            return result;
+        }
         return ((NumberLiteralPaginationValueSegment) 
paginationValueSegment).getValue();
     }
     
+    private Long getValueFromExpression(final ExpressionSegment 
expressionSegment, final List<Object> params) {
+        if (expressionSegment instanceof BinaryOperationExpression) {
+            return 
getValueFromBinaryOperationExpression((BinaryOperationExpression) 
expressionSegment, params);
+        }
+        if (expressionSegment instanceof CaseWhenExpression) {
+            return getValueFromCaseWhenExpression((CaseWhenExpression) 
expressionSegment, params);
+        }
+        return null;
+    }
+    
+    private Long getValueFromBinaryOperationExpression(final 
BinaryOperationExpression binaryOperationExpression, final List<Object> params) 
{
+        Long left = 
getValueFromExpression(binaryOperationExpression.getLeft(), params);
+        Long right = 
getValueFromExpression(binaryOperationExpression.getRight(), params);
+        if (null == left || null == right) {
+            return null;
+        }
+        switch (binaryOperationExpression.getOperator()) {
+            case "+":
+                return left + right;
+            case "-":
+                return left - right;
+            case "*":
+                return left * right;
+            case "/":
+                return 0L == right ? null : left / right;
+            default:
+                return null;
+        }
+    }
+    
+    private Long getValueFromCaseWhenExpression(final CaseWhenExpression 
caseWhenExpression, final List<Object> params) {
+        if (null != caseWhenExpression.getCaseExpr()) {
+            return null;
+        }
+        java.util.Iterator<ExpressionSegment> whenIterator = 
caseWhenExpression.getWhenExprs().iterator();
+        java.util.Iterator<ExpressionSegment> thenIterator = 
caseWhenExpression.getThenExprs().iterator();
+        while (whenIterator.hasNext() && thenIterator.hasNext()) {
+            Boolean whenValue = 
getBooleanValueFromExpression(whenIterator.next(), params);
+            if (Boolean.TRUE.equals(whenValue)) {
+                return getValueFromExpression(thenIterator.next(), params);
+            }
+            thenIterator.next();
+        }
+        return null == caseWhenExpression.getElseExpr() ? null : 
getValueFromExpression(caseWhenExpression.getElseExpr(), params);
+    }
+    
+    private Boolean getBooleanValueFromExpression(final ExpressionSegment 
expressionSegment, final List<Object> params) {
+        if (expressionSegment instanceof LiteralExpressionSegment) {
+            Object literals = ((LiteralExpressionSegment) 
expressionSegment).getLiterals();
+            if (literals instanceof Boolean) {
+                return (Boolean) literals;
+            }
+            return null == literals ? null : 
Boolean.parseBoolean(literals.toString());
+        }
+        if (expressionSegment instanceof ParameterMarkerExpressionSegment) {
+            Object obj = null == params || params.isEmpty() ? null : 
params.get(((ParameterMarkerExpressionSegment) 
expressionSegment).getParameterMarkerIndex());
+            return null == obj ? null : Boolean.parseBoolean(obj.toString());
+        }
+        return null;
+    }
+    
     /**
      * Get offset segment.
      *
diff --git 
a/kernel/sql-federation/compiler/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/sql/ast/converter/segment/limit/PaginationValueSQLConverter.java
 
b/kernel/sql-federation/compiler/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/sql/ast/converter/segment/limit/PaginationValueSQLConverter.java
index 5cd3191af9a..14add58f9c4 100644
--- 
a/kernel/sql-federation/compiler/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/sql/ast/converter/segment/limit/PaginationValueSQLConverter.java
+++ 
b/kernel/sql-federation/compiler/src/main/java/org/apache/shardingsphere/sqlfederation/compiler/sql/ast/converter/segment/limit/PaginationValueSQLConverter.java
@@ -23,9 +23,11 @@ import org.apache.calcite.sql.SqlDynamicParam;
 import org.apache.calcite.sql.SqlLiteral;
 import org.apache.calcite.sql.SqlNode;
 import org.apache.calcite.sql.parser.SqlParserPos;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.ExpressionPaginationValueSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.NumberLiteralPaginationValueSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.PaginationValueSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.limit.ParameterMarkerLimitValueSegment;
+import 
org.apache.shardingsphere.sqlfederation.compiler.sql.ast.converter.segment.expression.ExpressionConverter;
 
 import java.util.Optional;
 
@@ -42,9 +44,13 @@ public final class PaginationValueSQLConverter {
      * @return SQL node
      */
     public static Optional<SqlNode> convert(final PaginationValueSegment 
segment) {
-        return Optional.of(segment instanceof 
NumberLiteralPaginationValueSegment
-                ? getLiteralSQLNode((NumberLiteralPaginationValueSegment) 
segment)
-                : getParameterMarkerSQLNode((ParameterMarkerLimitValueSegment) 
segment));
+        if (segment instanceof NumberLiteralPaginationValueSegment) {
+            return 
Optional.of(getLiteralSQLNode((NumberLiteralPaginationValueSegment) segment));
+        }
+        if (segment instanceof ExpressionPaginationValueSegment) {
+            return 
ExpressionConverter.convert(((ExpressionPaginationValueSegment) 
segment).getExpression());
+        }
+        return 
Optional.of(getParameterMarkerSQLNode((ParameterMarkerLimitValueSegment) 
segment));
     }
     
     private static SqlNode getLiteralSQLNode(final 
NumberLiteralPaginationValueSegment segment) {
diff --git 
a/parser/sql/engine/dialect/opengauss/src/main/antlr4/imports/opengauss/DMLStatement.g4
 
b/parser/sql/engine/dialect/opengauss/src/main/antlr4/imports/opengauss/DMLStatement.g4
index 0fdc1759e9a..9d4cf614e17 100644
--- 
a/parser/sql/engine/dialect/opengauss/src/main/antlr4/imports/opengauss/DMLStatement.g4
+++ 
b/parser/sql/engine/dialect/opengauss/src/main/antlr4/imports/opengauss/DMLStatement.g4
@@ -231,15 +231,15 @@ offsetClause
 
 selectLimitValue
     : ALL
-    | cExpr
+    | aExpr
     ;
 
 selectOffsetValue
-    : cExpr
+    : aExpr
     ;
 
 selectFetchValue
-    : cExpr
+    : aExpr
     ;
 
 rowOrRows
diff --git 
a/parser/sql/engine/dialect/opengauss/src/main/java/org/apache/shardingsphere/sql/parser/engine/opengauss/visitor/statement/OpenGaussStatementVisitor.java
 
b/parser/sql/engine/dialect/opengauss/src/main/java/org/apache/shardingsphere/sql/parser/engine/opengauss/visitor/statement/OpenGaussStatementVisitor.java
index 5528c5d7137..ea7b38f7885 100644
--- 
a/parser/sql/engine/dialect/opengauss/src/main/java/org/apache/shardingsphere/sql/parser/engine/opengauss/visitor/statement/OpenGaussStatementVisitor.java
+++ 
b/parser/sql/engine/dialect/opengauss/src/main/java/org/apache/shardingsphere/sql/parser/engine/opengauss/visitor/statement/OpenGaussStatementVisitor.java
@@ -167,6 +167,7 @@ import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.order.ite
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.order.item.OrderByItemSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.limit.LimitSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.limit.LimitValueSegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.limit.ExpressionLimitValueSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.limit.NumberLiteralLimitValueSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.limit.ParameterMarkerLimitValueSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.predicate.HavingSegment;
@@ -444,7 +445,7 @@ public abstract class OpenGaussStatementVisitor extends 
OpenGaussStatementParser
         }
         ExpressionSegment caseExpr = null == ctx.caseArg() ? null : 
(ExpressionSegment) visit(ctx.caseArg().aExpr());
         ExpressionSegment elseExpr = null == ctx.caseDefault() ? null : 
(ExpressionSegment) visit(ctx.caseDefault().aExpr());
-        return new CaseWhenExpression(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), caseExpr, whenExprs, thenExprs, elseExpr);
+        return new CaseWhenExpression(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), caseExpr, whenExprs, thenExprs, elseExpr, 
getOriginalText(ctx));
     }
     
     @Override
@@ -1393,29 +1394,37 @@ public abstract class OpenGaussStatementVisitor extends 
OpenGaussStatementParser
         if (null != ctx.ALL()) {
             return null;
         }
-        ASTNode astNode = visit(ctx.cExpr());
-        if (astNode instanceof ParameterMarkerExpressionSegment) {
-            return new 
ParameterMarkerLimitValueSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), ((ParameterMarkerExpressionSegment) 
astNode).getParameterMarkerIndex());
-        }
-        return new NumberLiteralLimitValueSegment(ctx.start.getStartIndex(), 
ctx.stop.getStopIndex(), Long.parseLong(((ExpressionSegment) 
astNode).getText()));
+        return createLimitValueSegment(ctx, (ExpressionSegment) 
visit(ctx.aExpr()));
     }
     
     @Override
     public ASTNode visitSelectOffsetValue(final SelectOffsetValueContext ctx) {
-        ASTNode astNode = visit(ctx.cExpr());
-        if (astNode instanceof ParameterMarkerExpressionSegment) {
-            return new 
ParameterMarkerLimitValueSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), ((ParameterMarkerExpressionSegment) 
astNode).getParameterMarkerIndex());
-        }
-        return new NumberLiteralLimitValueSegment(ctx.start.getStartIndex(), 
ctx.stop.getStopIndex(), Long.parseLong(((ExpressionSegment) 
astNode).getText()));
+        return createLimitValueSegment(ctx, (ExpressionSegment) 
visit(ctx.aExpr()));
     }
     
     @Override
     public ASTNode visitSelectFetchValue(final SelectFetchValueContext ctx) {
-        ASTNode astNode = visit(ctx.cExpr());
-        if (astNode instanceof ParameterMarkerExpressionSegment) {
-            return new 
ParameterMarkerLimitValueSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), ((ParameterMarkerExpressionSegment) 
astNode).getParameterMarkerIndex());
+        return createLimitValueSegment(ctx, (ExpressionSegment) 
visit(ctx.aExpr()));
+    }
+    
+    private LimitValueSegment createLimitValueSegment(final ParserRuleContext 
ctx, final ExpressionSegment segment) {
+        if (segment instanceof ParameterMarkerExpressionSegment) {
+            return new 
ParameterMarkerLimitValueSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(),
+                    ((ParameterMarkerExpressionSegment) 
segment).getParameterMarkerIndex());
+        }
+        if (segment instanceof TypeCastExpression) {
+            return createLimitValueSegment(ctx, ((TypeCastExpression) 
segment).getExpression());
+        }
+        if (segment instanceof LiteralExpressionSegment) {
+            Object literals = ((LiteralExpressionSegment) 
segment).getLiterals();
+            if (null == literals) {
+                return ctx instanceof SelectOffsetValueContext
+                        ? new 
NumberLiteralLimitValueSegment(ctx.start.getStartIndex(), 
ctx.stop.getStopIndex(), 0L)
+                        : null;
+            }
+            return new 
NumberLiteralLimitValueSegment(ctx.start.getStartIndex(), 
ctx.stop.getStopIndex(), Long.parseLong(literals.toString()));
         }
-        return new NumberLiteralLimitValueSegment(ctx.start.getStartIndex(), 
ctx.stop.getStopIndex(), Long.parseLong(((ExpressionSegment) 
astNode).getText()));
+        return new ExpressionLimitValueSegment(ctx.start.getStartIndex(), 
ctx.stop.getStopIndex(), segment);
     }
     
     private LimitSegment createLimitSegmentWhenLimitAndOffset(final 
SelectLimitContext ctx) {
diff --git 
a/parser/sql/engine/dialect/postgresql/src/main/antlr4/imports/postgresql/DMLStatement.g4
 
b/parser/sql/engine/dialect/postgresql/src/main/antlr4/imports/postgresql/DMLStatement.g4
index 84810a50658..c11974f4465 100644
--- 
a/parser/sql/engine/dialect/postgresql/src/main/antlr4/imports/postgresql/DMLStatement.g4
+++ 
b/parser/sql/engine/dialect/postgresql/src/main/antlr4/imports/postgresql/DMLStatement.g4
@@ -233,16 +233,16 @@ offsetClause
     ;
 
 selectLimitValue
-    : cExpr
+    : aExpr
     | ALL
     ;
 
 selectOffsetValue
-    : cExpr
+    : aExpr
     ;
 
 selectFetchValue
-    : cExpr
+    : aExpr
     ;
 
 rowOrRows
diff --git 
a/parser/sql/engine/dialect/postgresql/src/main/java/org/apache/shardingsphere/sql/parser/engine/postgresql/visitor/statement/PostgreSQLStatementVisitor.java
 
b/parser/sql/engine/dialect/postgresql/src/main/java/org/apache/shardingsphere/sql/parser/engine/postgresql/visitor/statement/PostgreSQLStatementVisitor.java
index baa911fc8a3..2a686e88638 100644
--- 
a/parser/sql/engine/dialect/postgresql/src/main/java/org/apache/shardingsphere/sql/parser/engine/postgresql/visitor/statement/PostgreSQLStatementVisitor.java
+++ 
b/parser/sql/engine/dialect/postgresql/src/main/java/org/apache/shardingsphere/sql/parser/engine/postgresql/visitor/statement/PostgreSQLStatementVisitor.java
@@ -168,6 +168,7 @@ import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.order.ite
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.order.item.OrderByItemSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.limit.LimitSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.limit.LimitValueSegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.limit.ExpressionLimitValueSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.limit.NumberLiteralLimitValueSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.limit.ParameterMarkerLimitValueSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.predicate.HavingSegment;
@@ -445,7 +446,7 @@ public abstract class PostgreSQLStatementVisitor extends 
PostgreSQLStatementPars
         }
         ExpressionSegment caseExpr = null == ctx.caseArg() ? null : 
(ExpressionSegment) visit(ctx.caseArg().aExpr());
         ExpressionSegment elseExpr = null == ctx.caseDefault() ? null : 
(ExpressionSegment) visit(ctx.caseDefault().aExpr());
-        return new CaseWhenExpression(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), caseExpr, whenExprs, thenExprs, elseExpr);
+        return new CaseWhenExpression(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), caseExpr, whenExprs, thenExprs, elseExpr, 
getOriginalText(ctx));
     }
     
     @Override
@@ -1361,32 +1362,34 @@ public abstract class PostgreSQLStatementVisitor 
extends PostgreSQLStatementPars
         if (null != ctx.ALL()) {
             return null;
         }
-        ASTNode astNode = visit(ctx.cExpr());
-        if (astNode instanceof ParameterMarkerExpressionSegment) {
-            return new 
ParameterMarkerLimitValueSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), ((ParameterMarkerExpressionSegment) 
astNode).getParameterMarkerIndex());
-        }
-        return new NumberLiteralLimitValueSegment(ctx.start.getStartIndex(), 
ctx.stop.getStopIndex(),
-                (null == ((ExpressionSegment) astNode).getText()) ? null : 
Long.parseLong(((ExpressionSegment) astNode).getText()));
+        return createLimitValueSegment(ctx, (ExpressionSegment) 
visit(ctx.aExpr()));
     }
     
     @Override
     public ASTNode visitSelectOffsetValue(final SelectOffsetValueContext ctx) {
-        ASTNode astNode = visit(ctx.cExpr());
-        if (astNode instanceof ParameterMarkerExpressionSegment) {
-            return new 
ParameterMarkerLimitValueSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), ((ParameterMarkerExpressionSegment) 
astNode).getParameterMarkerIndex());
-        }
-        return new NumberLiteralLimitValueSegment(ctx.start.getStartIndex(), 
ctx.stop.getStopIndex(),
-                (null == ((ExpressionSegment) astNode).getText()) ? null : 
Long.parseLong(((ExpressionSegment) astNode).getText()));
+        return createLimitValueSegment(ctx, (ExpressionSegment) 
visit(ctx.aExpr()));
     }
     
     @Override
     public ASTNode visitSelectFetchValue(final SelectFetchValueContext ctx) {
-        ASTNode astNode = visit(ctx.cExpr());
-        if (astNode instanceof ParameterMarkerExpressionSegment) {
-            return new 
ParameterMarkerLimitValueSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), ((ParameterMarkerExpressionSegment) 
astNode).getParameterMarkerIndex());
+        return createLimitValueSegment(ctx, (ExpressionSegment) 
visit(ctx.aExpr()));
+    }
+    
+    private LimitValueSegment createLimitValueSegment(final ParserRuleContext 
ctx, final ExpressionSegment segment) {
+        if (segment instanceof ParameterMarkerExpressionSegment) {
+            return new 
ParameterMarkerLimitValueSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), ((ParameterMarkerExpressionSegment) 
segment).getParameterMarkerIndex());
+        }
+        if (segment instanceof TypeCastExpression) {
+            return createLimitValueSegment(ctx, ((TypeCastExpression) 
segment).getExpression());
+        }
+        if (segment instanceof LiteralExpressionSegment) {
+            Object literals = ((LiteralExpressionSegment) 
segment).getLiterals();
+            if (null == literals) {
+                return ctx instanceof SelectOffsetValueContext ? new 
NumberLiteralLimitValueSegment(ctx.start.getStartIndex(), 
ctx.stop.getStopIndex(), 0L) : null;
+            }
+            return new 
NumberLiteralLimitValueSegment(ctx.start.getStartIndex(), 
ctx.stop.getStopIndex(), Long.parseLong(literals.toString()));
         }
-        return new NumberLiteralLimitValueSegment(ctx.start.getStartIndex(), 
ctx.stop.getStopIndex(),
-                (null == ((ExpressionSegment) astNode).getText()) ? null : 
Long.parseLong(((ExpressionSegment) astNode).getText()));
+        return new ExpressionLimitValueSegment(ctx.start.getStartIndex(), 
ctx.stop.getStopIndex(), segment);
     }
     
     private LimitSegment createLimitSegmentWhenLimitAndOffset(final 
SelectLimitContext ctx) {
diff --git 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/limit/ExpectedPaginationValue.java
 
b/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/segment/dml/pagination/ExpressionPaginationValueSegment.java
similarity index 54%
copy from 
test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/limit/ExpectedPaginationValue.java
copy to 
parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/segment/dml/pagination/ExpressionPaginationValueSegment.java
index a29e568fdc0..ac8d791328e 100644
--- 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/limit/ExpectedPaginationValue.java
+++ 
b/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/segment/dml/pagination/ExpressionPaginationValueSegment.java
@@ -15,27 +15,19 @@
  * limitations under the License.
  */
 
-package 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.limit;
+package 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination;
 
-import lombok.Getter;
-import lombok.Setter;
-import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.AbstractExpectedSQLSegment;
-
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlAttribute;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.ExpressionSegment;
 
 /**
- * Expected pagination value.
+ * Pagination value segment for expression.
  */
-@XmlAccessorType(XmlAccessType.FIELD)
-@Getter
-@Setter
-public final class ExpectedPaginationValue extends AbstractExpectedSQLSegment {
-    
-    @XmlAttribute
-    private Long value;
+public interface ExpressionPaginationValueSegment extends 
PaginationValueSegment {
     
-    @XmlAttribute(name = "parameter-index")
-    private Integer parameterIndex;
+    /**
+     * Get expression segment.
+     *
+     * @return expression segment
+     */
+    ExpressionSegment getExpression();
 }
diff --git 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/limit/ExpectedPaginationValue.java
 
b/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/segment/dml/pagination/limit/ExpressionLimitValueSegment.java
similarity index 54%
copy from 
test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/limit/ExpectedPaginationValue.java
copy to 
parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/segment/dml/pagination/limit/ExpressionLimitValueSegment.java
index a29e568fdc0..8da097054ef 100644
--- 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/limit/ExpectedPaginationValue.java
+++ 
b/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/segment/dml/pagination/limit/ExpressionLimitValueSegment.java
@@ -15,27 +15,22 @@
  * limitations under the License.
  */
 
-package 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.limit;
+package 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.limit;
 
 import lombok.Getter;
-import lombok.Setter;
-import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.AbstractExpectedSQLSegment;
-
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlAttribute;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.ExpressionSegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.ExpressionPaginationValueSegment;
 
 /**
- * Expected pagination value.
+ * Limit value segment for expression.
  */
-@XmlAccessorType(XmlAccessType.FIELD)
 @Getter
-@Setter
-public final class ExpectedPaginationValue extends AbstractExpectedSQLSegment {
+public final class ExpressionLimitValueSegment extends LimitValueSegment 
implements ExpressionPaginationValueSegment {
     
-    @XmlAttribute
-    private Long value;
+    private final ExpressionSegment expression;
     
-    @XmlAttribute(name = "parameter-index")
-    private Integer parameterIndex;
+    public ExpressionLimitValueSegment(final int startIndex, final int 
stopIndex, final ExpressionSegment expression) {
+        super(startIndex, stopIndex);
+        this.expression = expression;
+    }
 }
diff --git 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/limit/LimitClauseAssert.java
 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/limit/LimitClauseAssert.java
index 655159d21cd..dafb216f8ac 100644
--- 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/limit/LimitClauseAssert.java
+++ 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/segment/limit/LimitClauseAssert.java
@@ -22,6 +22,7 @@ import lombok.NoArgsConstructor;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.NumberLiteralPaginationValueSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.PaginationValueSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.ParameterMarkerPaginationValueSegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.ExpressionPaginationValueSegment;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.SQLCaseAssertContext;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.segment.SQLSegmentAssert;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.limit.ExpectedPaginationValue;
@@ -52,6 +53,8 @@ public final class LimitClauseAssert {
         if (actual instanceof ParameterMarkerPaginationValueSegment) {
             assertThat(assertContext.getText("Offset index assertion error: "),
                     ((ParameterMarkerPaginationValueSegment) 
actual).getParameterIndex(), is(expected.getParameterIndex()));
+        } else if (actual instanceof ExpressionPaginationValueSegment) {
+            assertThat(assertContext.getText("Offset expression assertion 
error: "), ((ExpressionPaginationValueSegment) 
actual).getExpression().getText(), is(expected.getExpression()));
         } else {
             assertThat(assertContext.getText("Offset value assertion error: 
"), ((NumberLiteralPaginationValueSegment) actual).getValue(), 
is(expected.getValue()));
         }
@@ -73,6 +76,8 @@ public final class LimitClauseAssert {
         if (SQLCaseType.PLACEHOLDER == assertContext.getCaseType()) {
             assertThat(assertContext.getText("Row count index assertion error: 
"),
                     ((ParameterMarkerPaginationValueSegment) 
actual).getParameterIndex(), is(expected.getParameterIndex()));
+        } else if (actual instanceof ExpressionPaginationValueSegment) {
+            assertThat(assertContext.getText("Row count expression assertion 
error: "), ((ExpressionPaginationValueSegment) 
actual).getExpression().getText(), is(expected.getExpression()));
         } else {
             assertThat(assertContext.getText("Row count value assertion error: 
"), ((NumberLiteralPaginationValueSegment) actual).getValue(), 
is(expected.getValue()));
         }
diff --git 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/limit/ExpectedPaginationValue.java
 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/limit/ExpectedPaginationValue.java
index a29e568fdc0..70026686012 100644
--- 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/limit/ExpectedPaginationValue.java
+++ 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/limit/ExpectedPaginationValue.java
@@ -36,6 +36,9 @@ public final class ExpectedPaginationValue extends 
AbstractExpectedSQLSegment {
     @XmlAttribute
     private Long value;
     
+    @XmlAttribute
+    private String expression;
+    
     @XmlAttribute(name = "parameter-index")
     private Integer parameterIndex;
 }
diff --git a/test/it/parser/src/main/resources/case/dml/select.xml 
b/test/it/parser/src/main/resources/case/dml/select.xml
index 43833d5a56d..cb0f0387d4a 100644
--- a/test/it/parser/src/main/resources/case/dml/select.xml
+++ b/test/it/parser/src/main/resources/case/dml/select.xml
@@ -13802,4 +13802,229 @@
             <index-item index="1" start-index="291" stop-index="291"/>
         </order-by>
     </select>
+
+    <select sql-case-id="select_pg_int">
+        <from>
+            <simple-table name="t4" start-index="14" stop-index="15" />
+        </from>
+        <projections start-index="7" stop-index="7">
+            <shorthand-projection start-index="7" stop-index="7" />
+        </projections>
+        <limit start-index="17" stop-index="30">
+            <row-count value="2" start-index="23" stop-index="30">
+                <type-cast-expression>
+                    <expression>
+                        <literal-expression value="2" start-index="23" 
stop-index="25" />
+                    </expression>
+                    <data-type>int</data-type>
+                </type-cast-expression>
+            </row-count>
+        </limit>
+    </select>
+
+    <select sql-case-id="select_pg_offset_int">
+        <from>
+            <simple-table name="t4" start-index="14" stop-index="15" />
+        </from>
+        <projections start-index="7" stop-index="7">
+            <shorthand-projection start-index="7" stop-index="7" />
+        </projections>
+        <limit start-index="17" stop-index="32">
+            <offset value="10" start-index="24" stop-index="32">
+                <type-cast-expression>
+                    <expression>
+                        <literal-expression value="10" start-index="25" 
stop-index="27" />
+                    </expression>
+                    <data-type>int</data-type>
+                </type-cast-expression>
+            </offset>
+        </limit>
+    </select>
+
+    <select sql-case-id="select_pg_fetch_next_int">
+        <from>
+            <simple-table name="t4" start-index="14" stop-index="15" />
+        </from>
+        <projections start-index="7" stop-index="7">
+            <shorthand-projection start-index="7" stop-index="7" />
+        </projections>
+        <order-by start-index="17" stop-index="27">
+            <column-item name="id" order-direction="ASC" start-index="26" 
stop-index="27" />
+        </order-by>
+        <limit start-index="29" stop-index="60">
+            <row-count value="10" start-index="40" stop-index="50">
+                <type-cast-expression>
+                    <expression>
+                        <literal-expression value="10" start-index="41" 
stop-index="43" />
+                    </expression>
+                    <data-type>int</data-type>
+                </type-cast-expression>
+            </row-count>
+        </limit>
+    </select>
+
+    <select sql-case-id="select_limit_constant">
+        <from>
+            <simple-table name="t4" start-index="14" stop-index="15" />
+        </from>
+        <projections start-index="7" stop-index="7">
+            <shorthand-projection start-index="7" stop-index="7" />
+        </projections>
+        <limit start-index="17" stop-index="24">
+            <row-count value="10" start-index="23" stop-index="24" />
+        </limit>
+    </select>
+
+    <select sql-case-id="select_limit_all">
+        <from>
+            <simple-table name="t4" start-index="14" stop-index="15" />
+        </from>
+        <projections start-index="7" stop-index="7">
+            <shorthand-projection start-index="7" stop-index="7" />
+        </projections>
+        <limit start-index="17" stop-index="25" />
+    </select>
+
+    <select sql-case-id="select_limit_null">
+        <from>
+            <simple-table name="t4" start-index="14" stop-index="15" />
+        </from>
+        <projections start-index="7" stop-index="7">
+            <shorthand-projection start-index="7" stop-index="7" />
+        </projections>
+        <limit start-index="17" stop-index="26" />
+    </select>
+
+    <select sql-case-id="select_limit_expression">
+        <from>
+            <simple-table name="t4" start-index="14" stop-index="15" />
+        </from>
+        <projections start-index="7" stop-index="7">
+            <shorthand-projection start-index="7" stop-index="7" />
+        </projections>
+        <limit start-index="17" stop-index="29">
+            <row-count expression="5 + 3" start-index="23" stop-index="29" />
+        </limit>
+    </select>
+
+    <select sql-case-id="select_limit_cast">
+        <from>
+            <simple-table name="t4" start-index="14" stop-index="15" />
+        </from>
+        <projections start-index="7" stop-index="7">
+            <shorthand-projection start-index="7" stop-index="7" />
+        </projections>
+        <limit start-index="17" stop-index="36">
+            <row-count value="8" start-index="23" stop-index="36" />
+        </limit>
+    </select>
+
+    <select sql-case-id="select_limit_subquery">
+        <from>
+            <simple-table name="t4" start-index="14" stop-index="15" />
+        </from>
+        <projections start-index="7" stop-index="7">
+            <shorthand-projection start-index="7" stop-index="7" />
+        </projections>
+        <limit start-index="17" stop-index="48">
+            <row-count expression="(SELECT 6 FROM t4 LIMIT 1)" 
start-index="23" stop-index="48" />
+        </limit>
+    </select>
+
+    <select sql-case-id="select_offset_constant">
+        <from>
+            <simple-table name="t4" start-index="14" stop-index="15" />
+        </from>
+        <projections start-index="7" stop-index="7">
+            <shorthand-projection start-index="7" stop-index="7" />
+        </projections>
+        <limit start-index="17" stop-index="34">
+            <offset value="5" start-index="34" stop-index="34" />
+        </limit>
+    </select>
+
+    <select sql-case-id="select_offset_null">
+        <from>
+            <simple-table name="t4" start-index="14" stop-index="15" />
+        </from>
+        <projections start-index="7" stop-index="7">
+            <shorthand-projection start-index="7" stop-index="7" />
+        </projections>
+        <limit start-index="17" stop-index="36">
+            <row-count value="10" start-index="23" stop-index="24" />
+            <offset value="0" start-index="33" stop-index="36">
+                <literal-expression value="NULL" start-index="33" 
stop-index="36" />
+            </offset>
+        </limit>
+    </select>
+
+    <select sql-case-id="select_offset_expression">
+        <from>
+            <simple-table name="t4" start-index="14" stop-index="15" />
+        </from>
+        <projections start-index="7" stop-index="7">
+            <shorthand-projection start-index="7" stop-index="7" />
+        </projections>
+        <limit start-index="17" stop-index="40">
+            <row-count value="10" start-index="23" stop-index="24" />
+            <offset expression="10 - 2" start-index="33" stop-index="40" />
+        </limit>
+    </select>
+
+    <select sql-case-id="select_offset_cast_string">
+        <from>
+            <simple-table name="t4" start-index="14" stop-index="15" />
+        </from>
+        <projections start-index="7" stop-index="7">
+            <shorthand-projection start-index="7" stop-index="7" />
+        </projections>
+        <limit start-index="17" stop-index="40">
+            <row-count value="10" start-index="23" stop-index="24" />
+            <offset value="8" start-index="33" stop-index="40">
+                <type-cast-expression>
+                    <expression>
+                        <literal-expression value="8" start-index="33" 
stop-index="35" />
+                    </expression>
+                    <data-type>int</data-type>
+                </type-cast-expression>
+            </offset>
+        </limit>
+    </select>
+
+    <select sql-case-id="select_limit_offset_combined">
+        <from>
+            <simple-table name="t4" start-index="14" stop-index="15" />
+        </from>
+        <projections start-index="7" stop-index="7">
+            <shorthand-projection start-index="7" stop-index="7" />
+        </projections>
+        <limit start-index="17" stop-index="33">
+            <row-count value="5" start-index="23" stop-index="23" />
+            <offset value="10" start-index="32" stop-index="33" />
+        </limit>
+    </select>
+    
+    <select sql-case-id="select_limit_parameter" parameters="1">
+        <from>
+            <simple-table name="t4" start-index="14" stop-index="15" />
+        </from>
+        <projections start-index="7" stop-index="7">
+            <shorthand-projection start-index="7" stop-index="7" />
+        </projections>
+        <limit start-index="17" stop-index="23">
+            <row-count value="1" parameter-index="0" start-index="23" 
stop-index="23" />
+        </limit>
+    </select>
+
+    <select sql-case-id="select_limit_complex_expr">
+        <from>
+            <simple-table name="t4" start-index="14" stop-index="15" />
+        </from>
+        <projections start-index="7" stop-index="7">
+            <shorthand-projection start-index="7" stop-index="7" />
+        </projections>
+        <limit start-index="17" stop-index="58">
+            <row-count expression="CASE WHEN true THEN 10 ELSE 20 END" 
start-index="23" stop-index="58" />
+        </limit>
+    </select>
 </sql-parser-test-cases>
diff --git a/test/it/parser/src/main/resources/sql/supported/dml/select.xml 
b/test/it/parser/src/main/resources/sql/supported/dml/select.xml
index 4a7d30cdd3e..e4d0deff06c 100644
--- a/test/it/parser/src/main/resources/sql/supported/dml/select.xml
+++ b/test/it/parser/src/main/resources/sql/supported/dml/select.xml
@@ -498,4 +498,20 @@
     <sql-case id="select_order_by_order" value="SELECT id FROM test ORDER BY 
`order` " db-types="MySQL,Hive,Doris,Presto" />
     <sql-case id="select_order_by_order_two" value="SELECT id FROM t_test 
ORDER BY t_test.order" 
db-types="MySQL,Hive,Doris,SQLServer,Firebird,SQL92,Presto" />
     <sql-case id="select_pg_database_info" value="SELECT d.datname as 
&quot;Name&quot;, pg_catalog.pg_get_userbyid(d.datdba) as &quot;Owner&quot;, 
pg_catalog.pg_encoding_to_char(d.encoding) as &quot;Encoding&quot;, 
d.datcollate as &quot;Collate&quot;, d.datctype as &quot;Ctype&quot;, 
pg_catalog.array_to_string(d.datacl, E'\n') AS &quot;Access privileges&quot; 
FROM pg_catalog.pg_database d ORDER BY 1;" db-types="openGauss" />
+    <sql-case id="select_pg_int" value="SELECT * FROM t4 LIMIT '2'::int;" 
db-types="PostgreSQL,openGauss" />
+    <sql-case id="select_pg_offset_int" value="SELECT * FROM t4 OFFSET 
'10'::int;" db-types="PostgreSQL,openGauss" />
+    <sql-case id="select_pg_fetch_next_int" value="SELECT * FROM t4 ORDER BY 
id FETCH NEXT ('10'::int) ROWS ONLY;" db-types="PostgreSQL,openGauss" />
+    <sql-case id="select_limit_constant" value="SELECT * FROM t4 LIMIT 10;" 
db-types="PostgreSQL,openGauss" />
+    <sql-case id="select_limit_all" value="SELECT * FROM t4 LIMIT ALL;" 
db-types="PostgreSQL,openGauss" />
+    <sql-case id="select_limit_null" value="SELECT * FROM t4 LIMIT NULL;" 
db-types="PostgreSQL,openGauss" />
+    <sql-case id="select_limit_cast" value="SELECT * FROM t4 LIMIT CAST(8 AS 
int);" db-types="PostgreSQL,openGauss" />
+    <sql-case id="select_limit_expression" value="SELECT * FROM t4 LIMIT (5 + 
3);" db-types="PostgreSQL,openGauss" />
+    <sql-case id="select_limit_subquery" value="SELECT * FROM t4 LIMIT (SELECT 
6 FROM t4 LIMIT 1);" db-types="PostgreSQL,openGauss" />
+    <sql-case id="select_offset_constant" value="SELECT * FROM t4 LIMIT ALL 
OFFSET 5;" db-types="PostgreSQL,openGauss" />
+    <sql-case id="select_offset_null" value="SELECT * FROM t4 LIMIT 10 OFFSET 
NULL;" db-types="PostgreSQL,openGauss" />
+    <sql-case id="select_offset_expression" value="SELECT * FROM t4 LIMIT 10 
OFFSET (10 - 2);" db-types="PostgreSQL,openGauss" />
+    <sql-case id="select_offset_cast_string" value="SELECT * FROM t4 LIMIT 10 
OFFSET '8'::int;" db-types="PostgreSQL,openGauss" />
+    <sql-case id="select_limit_offset_combined" value="SELECT * FROM t4 LIMIT 
5 OFFSET 10;" db-types="PostgreSQL,openGauss" />
+    <sql-case id="select_limit_parameter" value="SELECT * FROM t4 LIMIT ?;" 
db-types="PostgreSQL,openGauss" />
+    <sql-case id="select_limit_complex_expr" value="SELECT * FROM t4 LIMIT 
(CASE WHEN true THEN 10 ELSE 20 END);" db-types="PostgreSQL,openGauss" />
 </sql-cases>


Reply via email to