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

terrymanu 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 a4022e9466d Fix Firebird OFFSET/FETCH rewrite by visiting limitClause 
(#39955)
a4022e9466d is described below

commit a4022e9466d7966094e53bd1985f88e4fcefdb98
Author: Zhicheng Lin <[email protected]>
AuthorDate: Sun Oct 18 23:02:08 2026 +0800

    Fix Firebird OFFSET/FETCH rewrite by visiting limitClause (#39955)
    
    * Fix Firebird OFFSET/FETCH rewrite by visiting limitClause
    
    Firebird select statements that use OFFSET ... ROWS FETCH FIRST ... ROWS 
ONLY
    were never rewritten, because the pagination information never reached a
    LimitSegment:
    
    - FirebirdDMLStatementVisitor.visitSelectClause handled only firstSkipClause
      (FIRST n / SKIP n, the Firebird-specific syntax) and ignored the 
limitClause
      that selectClause declares in DMLStatement.g4.
    - orderByClause also carried a trailing limitClause?. ANTLR's greedy 
prediction
      consumed the clause inside orderByClause, so for a statement with ORDER 
BY the
      outer ctx.limitClause() was null. orderByClause is reused by window
      specifications (OVER (...)) and GROUP_CONCAT(...), where accepting a 
LIMIT is
      wrong regardless, and every statement that wants one already declares its 
own
      limitClause? (DML / DAL / DDL), so the nested one is removed.
    
    With both changes, SELECT * FROM t_order ORDER BY order_id OFFSET 100000 
ROWS
    FETCH FIRST 10 ROWS ONLY parses to a LimitSegment with offset=100000 and
    rowCount=10, and the sharding pagination rewrite can apply.
    
    Anchors in visitLimitClause are taken from the matched context, and the
    rowsClause branch guards the optional TO so ROWS n cannot run past the end 
of
    the expression list.
    
    Tests: the existing select_pagination_with_offset_fetch case is limited to
    SQLServer, PostgreSQL and openGauss and never covered Firebird, which is why
    this went unnoticed. Added two Firebird cases to sql/supported/dml and the
    matching expectations to case/dml, one without ORDER BY and the one from the
    report with ORDER BY.
    
    Verified locally: InternalFirebirdParserIT passes 238/238 with both changes.
    With only the visitor change (grammar untouched) the ORDER BY case still 
fails
    with "Offset should not exist"; with only the grammar change both cases fail
    with "Actual limit segment should exist", so both halves are required.
    
    Closes #39926
    
    * Fix Firebird pagination parameter marker indexes per review
    
    * Format Firebird visitor per Spotless
    
    * Complete Firebird pagination after merging shard results
    
    * Polish Firebird pagination builder formatting
    
    * Fix registerBlob call missing boolean argument in Firebird blob test
    
    * Visit WITH clause in SQL order and exercise Firebird SPI in pagination 
tests
    
    - Visit withClause before combineClause so parameter markers are numbered
      in SQL order when a CTE precedes OFFSET/FETCH, and attach parameter
      markers after the with-segment rebuild so they are not dropped
    - Add Firebird parser IT with a preceding parameterized CTE
    - Add shardingsphere-database-connector-firebird test dependency so the
      pagination builder test resolves the actual Firebird database type
    - Load the builder via DatabaseTypedSPILoader and assert the registration
      path instead of direct construction
    - Move the cross-shard merge decoration assertion into
      ShardingDQLResultMergerTest and drop the handwritten MergedResult stub
    
    * Polish Firebird pagination tests per review standards
    
    - Merge the short SelectStatementContext declaration into one line in
      ShardingDQLResultMergerTest
    - Rename the sole builder test to assertBuild per CODE_OF_CONDUCT.md
    
    ---------
    
    Co-authored-by: lzcGeek <[email protected]>
---
 features/sharding/core/pom.xml                     |   6 +
 ...birdPaginationDecoratorMergedResultBuilder.java |  42 +++++++
 ....builder.PaginationDecoratorMergedResultBuilder |   1 +
 .../merge/dql/ShardingDQLResultMergerTest.java     |  26 +++++
 ...PaginationDecoratorMergedResultBuilderTest.java |  48 ++++++++
 .../src/main/antlr4/imports/firebird/BaseRule.g4   |   2 +-
 .../type/FirebirdDMLStatementVisitor.java          |  53 ++++++++-
 .../main/resources/case/dml/select-pagination.xml  | 126 +++++++++++++++++++++
 .../sql/supported/dml/select-pagination.xml        |   5 +
 9 files changed, 303 insertions(+), 6 deletions(-)

diff --git a/features/sharding/core/pom.xml b/features/sharding/core/pom.xml
index 4245824fd64..6bd37aef29e 100644
--- a/features/sharding/core/pom.xml
+++ b/features/sharding/core/pom.xml
@@ -139,6 +139,12 @@
             <version>${project.version}</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.shardingsphere</groupId>
+            <artifactId>shardingsphere-database-connector-firebird</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>org.apache.shardingsphere</groupId>
             <artifactId>shardingsphere-test-it-yaml</artifactId>
diff --git 
a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/merge/dql/pagination/builder/dialect/FirebirdPaginationDecoratorMergedResultBuilder.java
 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/merge/dql/pagination/builder/dialect/FirebirdPaginationDecoratorMergedResultBuilder.java
new file mode 100644
index 00000000000..15649fcb727
--- /dev/null
+++ 
b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/merge/dql/pagination/builder/dialect/FirebirdPaginationDecoratorMergedResultBuilder.java
@@ -0,0 +1,42 @@
+/*
+ * 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.sharding.merge.dql.pagination.builder.dialect;
+
+import 
org.apache.shardingsphere.infra.binder.context.segment.select.pagination.PaginationContext;
+import org.apache.shardingsphere.infra.merge.result.MergedResult;
+import 
org.apache.shardingsphere.infra.merge.result.impl.decorator.DecoratorMergedResult;
+import 
org.apache.shardingsphere.sharding.merge.dql.pagination.LimitDecoratorMergedResult;
+import 
org.apache.shardingsphere.sharding.merge.dql.pagination.builder.PaginationDecoratorMergedResultBuilder;
+
+import java.sql.SQLException;
+
+/**
+ * Pagination decorator merged result builder for Firebird.
+ */
+public final class FirebirdPaginationDecoratorMergedResultBuilder implements 
PaginationDecoratorMergedResultBuilder {
+    
+    @Override
+    public DecoratorMergedResult build(final MergedResult mergedResult, final 
PaginationContext paginationContext) throws SQLException {
+        return new LimitDecoratorMergedResult(mergedResult, paginationContext);
+    }
+    
+    @Override
+    public String getDatabaseType() {
+        return "Firebird";
+    }
+}
diff --git 
a/features/sharding/core/src/main/resources/META-INF/services/org.apache.shardingsphere.sharding.merge.dql.pagination.builder.PaginationDecoratorMergedResultBuilder
 
b/features/sharding/core/src/main/resources/META-INF/services/org.apache.shardingsphere.sharding.merge.dql.pagination.builder.PaginationDecoratorMergedResultBuilder
index 4ddcd32bdec..8db9c30581e 100644
--- 
a/features/sharding/core/src/main/resources/META-INF/services/org.apache.shardingsphere.sharding.merge.dql.pagination.builder.PaginationDecoratorMergedResultBuilder
+++ 
b/features/sharding/core/src/main/resources/META-INF/services/org.apache.shardingsphere.sharding.merge.dql.pagination.builder.PaginationDecoratorMergedResultBuilder
@@ -20,3 +20,4 @@ 
org.apache.shardingsphere.sharding.merge.dql.pagination.builder.dialect.PostgreS
 
org.apache.shardingsphere.sharding.merge.dql.pagination.builder.dialect.OpenGaussPaginationDecoratorMergedResultBuilder
 
org.apache.shardingsphere.sharding.merge.dql.pagination.builder.dialect.OraclePaginationDecoratorMergedResultBuilder
 
org.apache.shardingsphere.sharding.merge.dql.pagination.builder.dialect.SQLServerPaginationDecoratorMergedResultBuilder
+org.apache.shardingsphere.sharding.merge.dql.pagination.builder.dialect.FirebirdPaginationDecoratorMergedResultBuilder
diff --git 
a/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/merge/dql/ShardingDQLResultMergerTest.java
 
b/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/merge/dql/ShardingDQLResultMergerTest.java
index bcd547a2d8e..877373a8a98 100644
--- 
a/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/merge/dql/ShardingDQLResultMergerTest.java
+++ 
b/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/merge/dql/ShardingDQLResultMergerTest.java
@@ -100,6 +100,8 @@ class ShardingDQLResultMergerTest {
     
     private final DatabaseType sqlserverDatabaseType = 
TypedSPILoader.getService(DatabaseType.class, "SQLServer");
     
+    private final DatabaseType firebirdDatabaseType = 
TypedSPILoader.getService(DatabaseType.class, "Firebird");
+    
     @Test
     void assertBuildIteratorStreamMergedResult() throws SQLException {
         ShardingDQLResultMerger resultMerger = new 
ShardingDQLResultMerger(mysqlDatabaseType);
@@ -197,6 +199,30 @@ class ShardingDQLResultMergerTest {
         assertFalse(actual.next());
     }
     
+    @Test
+    void assertBuildIteratorStreamMergedResultWithFirebirdOffsetFetch() throws 
SQLException {
+        ShardingDQLResultMerger resultMerger = new 
ShardingDQLResultMerger(firebirdDatabaseType);
+        ShardingSphereDatabase database = mock(ShardingSphereDatabase.class, 
RETURNS_DEEP_STUBS);
+        SelectStatement selectStatement = 
buildSelectStatement(firebirdDatabaseType);
+        selectStatement = withProjections(selectStatement, new 
ProjectionsSegment(0, 0));
+        selectStatement = withLimit(selectStatement, new LimitSegment(0, 0, 
new NumberLiteralLimitValueSegment(0, 0, 2L), new 
NumberLiteralLimitValueSegment(0, 0, 2L)));
+        SelectStatementContext selectStatementContext = new 
SelectStatementContext(selectStatement, createShardingSphereMetaData(database), 
"foo_db", Collections.emptyList());
+        MergedResult actual = resultMerger.merge(createFourQueryResults(), 
selectStatementContext, createDialectDatabase(firebirdDatabaseType), 
mock(ConnectionContext.class));
+        assertTrue(actual.next());
+        assertTrue(actual.next());
+        assertFalse(actual.next());
+    }
+    
+    private List<QueryResult> createFourQueryResults() throws SQLException {
+        List<QueryResult> result = new LinkedList<>();
+        for (int i = 0; i < 4; i++) {
+            QueryResult queryResult = createQueryResult();
+            when(queryResult.next()).thenReturn(true, true, false);
+            result.add(queryResult);
+        }
+        return result;
+    }
+    
     @Test
     void assertBuildOrderByStreamMergedResult() throws SQLException {
         ShardingDQLResultMerger resultMerger = new 
ShardingDQLResultMerger(mysqlDatabaseType);
diff --git 
a/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/merge/dql/pagination/builder/dialect/FirebirdPaginationDecoratorMergedResultBuilderTest.java
 
b/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/merge/dql/pagination/builder/dialect/FirebirdPaginationDecoratorMergedResultBuilderTest.java
new file mode 100644
index 00000000000..0802e622d37
--- /dev/null
+++ 
b/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/merge/dql/pagination/builder/dialect/FirebirdPaginationDecoratorMergedResultBuilderTest.java
@@ -0,0 +1,48 @@
+/*
+ * 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.sharding.merge.dql.pagination.builder.dialect;
+
+import 
org.apache.shardingsphere.database.connector.core.spi.DatabaseTypedSPILoader;
+import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
+import 
org.apache.shardingsphere.infra.binder.context.segment.select.pagination.PaginationContext;
+import org.apache.shardingsphere.infra.merge.result.MergedResult;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
+import 
org.apache.shardingsphere.sharding.merge.dql.pagination.LimitDecoratorMergedResult;
+import 
org.apache.shardingsphere.sharding.merge.dql.pagination.builder.PaginationDecoratorMergedResultBuilder;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.limit.NumberLiteralLimitValueSegment;
+import org.junit.jupiter.api.Test;
+
+import java.sql.SQLException;
+import java.util.Collections;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.isA;
+import static org.mockito.Mockito.mock;
+
+class FirebirdPaginationDecoratorMergedResultBuilderTest {
+    
+    private final DatabaseType databaseType = 
TypedSPILoader.getService(DatabaseType.class, "Firebird");
+    
+    @Test
+    void assertBuild() throws SQLException {
+        PaginationContext paginationContext = new PaginationContext(new 
NumberLiteralLimitValueSegment(0, 0, 10L), new 
NumberLiteralLimitValueSegment(0, 0, 10L), Collections.emptyList());
+        PaginationDecoratorMergedResultBuilder builder = 
DatabaseTypedSPILoader.getService(PaginationDecoratorMergedResultBuilder.class, 
databaseType);
+        assertThat(builder, 
isA(FirebirdPaginationDecoratorMergedResultBuilder.class));
+        assertThat(builder.build(mock(MergedResult.class), paginationContext), 
isA(LimitDecoratorMergedResult.class));
+    }
+}
diff --git 
a/parser/sql/engine/dialect/firebird/src/main/antlr4/imports/firebird/BaseRule.g4
 
b/parser/sql/engine/dialect/firebird/src/main/antlr4/imports/firebird/BaseRule.g4
index ae1d3b57f45..5871ae36469 100644
--- 
a/parser/sql/engine/dialect/firebird/src/main/antlr4/imports/firebird/BaseRule.g4
+++ 
b/parser/sql/engine/dialect/firebird/src/main/antlr4/imports/firebird/BaseRule.g4
@@ -389,7 +389,7 @@ subquery
     ;
 
 orderByClause
-    : ORDER BY orderByItem (COMMA_ orderByItem)* limitClause?
+    : ORDER BY orderByItem (COMMA_ orderByItem)*
     ;
 
 orderByItem
diff --git 
a/parser/sql/engine/dialect/firebird/src/main/java/org/apache/shardingsphere/sql/parser/engine/firebird/visitor/statement/type/FirebirdDMLStatementVisitor.java
 
b/parser/sql/engine/dialect/firebird/src/main/java/org/apache/shardingsphere/sql/parser/engine/firebird/visitor/statement/type/FirebirdDMLStatementVisitor.java
index 7c66c049d50..affb013abed 100644
--- 
a/parser/sql/engine/dialect/firebird/src/main/java/org/apache/shardingsphere/sql/parser/engine/firebird/visitor/statement/type/FirebirdDMLStatementVisitor.java
+++ 
b/parser/sql/engine/dialect/firebird/src/main/java/org/apache/shardingsphere/sql/parser/engine/firebird/visitor/statement/type/FirebirdDMLStatementVisitor.java
@@ -44,8 +44,12 @@ import 
org.apache.shardingsphere.sql.parser.autogen.FirebirdStatementParser.Inse
 import 
org.apache.shardingsphere.sql.parser.autogen.FirebirdStatementParser.InsertValuesClauseContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.FirebirdStatementParser.JoinSpecificationContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.FirebirdStatementParser.JoinedTableContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.FirebirdStatementParser.LimitClauseContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.FirebirdStatementParser.MergeContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.FirebirdStatementParser.NumberLiteralsContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.FirebirdStatementParser.OffsetDefinitionContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.FirebirdStatementParser.OrderByItemContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.FirebirdStatementParser.ParameterMarkerContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.FirebirdStatementParser.ProjectionContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.FirebirdStatementParser.ProjectionsContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.FirebirdStatementParser.QualifiedShorthandContext;
@@ -257,11 +261,12 @@ public final class FirebirdDMLStatementVisitor extends 
FirebirdStatementVisitor
     
     @Override
     public ASTNode visitSelect(final SelectContext ctx) {
+        WithSegment withSegment = null == ctx.withClause() ? null : 
(WithSegment) visit(ctx.withClause());
         SelectStatement result = (SelectStatement) visit(ctx.combineClause());
-        result.addParameterMarkers(getParameterMarkerSegments());
-        if (null != ctx.withClause()) {
-            result = createSelectStatementBuilder(result).with((WithSegment) 
visit(ctx.withClause())).build();
+        if (null != withSegment) {
+            result = 
createSelectStatementBuilder(result).with(withSegment).build();
         }
+        result.addParameterMarkers(getParameterMarkerSegments());
         return result;
     }
     
@@ -334,6 +339,9 @@ public final class FirebirdDMLStatementVisitor extends 
FirebirdStatementVisitor
         if (null != ctx.havingClause()) {
             selectStatementBuilder.having((HavingSegment) 
visit(ctx.havingClause()));
         }
+        if (null != ctx.limitClause()) {
+            selectStatementBuilder.limit((LimitSegment) 
visit(ctx.limitClause()));
+        }
         return selectStatementBuilder.build();
     }
     
@@ -352,6 +360,40 @@ public final class FirebirdDMLStatementVisitor extends 
FirebirdStatementVisitor
         return new LimitSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), offset, rowCount);
     }
     
+    @Override
+    public ASTNode visitLimitClause(final LimitClauseContext ctx) {
+        PaginationValueSegment rowCount = null;
+        PaginationValueSegment offset = null;
+        if (null != ctx.rowsClause()) {
+            offset = (PaginationValueSegment) 
visitLimitValue(ctx.rowsClause().expr(0));
+            if (ctx.rowsClause().expr().size() > 1) {
+                rowCount = (PaginationValueSegment) 
visitLimitValue(ctx.rowsClause().expr(1));
+            }
+        } else {
+            OffsetDefinitionContext offsetDefinition = ctx.offsetDefinition();
+            if (null != offsetDefinition.offsetClause()) {
+                offset = (PaginationValueSegment) 
visitLimitValue(offsetDefinition.offsetClause().limitOffset());
+            }
+            if (null != offsetDefinition.fetchClause()) {
+                rowCount = (PaginationValueSegment) 
visitLimitValue(offsetDefinition.fetchClause().limitRowCount());
+            }
+        }
+        return new LimitSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), offset, rowCount);
+    }
+    
+    private ASTNode visitLimitValue(final ParserRuleContext ctx) {
+        if (ctx.getChild(0) instanceof NumberLiteralsContext) {
+            return new 
NumberLiteralLimitValueSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), ((NumberLiteralValue) 
visit(ctx.getChild(0))).getValue().longValue());
+        }
+        if (ctx.getChild(0) instanceof ParameterMarkerContext) {
+            ParameterMarkerSegment result =
+                    new 
ParameterMarkerLimitValueSegment(ctx.getStart().getStartIndex(), 
ctx.getStop().getStopIndex(), ((ParameterMarkerValue) 
visit(ctx.getChild(0))).getValue());
+            getParameterMarkerSegments().add(result);
+            return result;
+        }
+        return null;
+    }
+    
     @Override
     public ASTNode visitFirstValue(final FirstValueContext ctx) {
         // TODO Add expression support for firstSkipClause
@@ -615,9 +657,10 @@ public final class FirebirdDMLStatementVisitor extends 
FirebirdStatementVisitor
     
     @Override
     public ASTNode visitSubquery(final SubqueryContext ctx) {
+        WithSegment withSegment = null == ctx.withClause() ? null : 
(WithSegment) visit(ctx.withClause());
         SelectStatement result = (SelectStatement) visit(ctx.combineClause());
-        if (null != ctx.withClause()) {
-            result = createSelectStatementBuilder(result).with((WithSegment) 
visit(ctx.withClause())).build();
+        if (null != withSegment) {
+            result = 
createSelectStatementBuilder(result).with(withSegment).build();
         }
         return result;
     }
diff --git a/test/it/parser/src/main/resources/case/dml/select-pagination.xml 
b/test/it/parser/src/main/resources/case/dml/select-pagination.xml
index e13f58797ea..6a7151f244c 100644
--- a/test/it/parser/src/main/resources/case/dml/select-pagination.xml
+++ b/test/it/parser/src/main/resources/case/dml/select-pagination.xml
@@ -2084,6 +2084,35 @@
         </from>
     </select>
 
+    <select sql-case-id="select_pagination_with_offset_and_fetch_firebird">
+        <limit start-index="22" stop-index="64">
+            <offset value="100000" start-index="29" stop-index="34" />
+            <row-count value="10" start-index="53" stop-index="54" />
+        </limit>
+        <projections start-index="7" stop-index="7">
+            <shorthand-projection start-index="7" stop-index="7" />
+        </projections>
+        <from start-index="14" stop-index="20">
+            <simple-table name="t_order" start-index="14" stop-index="20" />
+        </from>
+    </select>
+
+    <select 
sql-case-id="select_pagination_with_order_by_offset_and_fetch_firebird">
+        <limit start-index="40" stop-index="82">
+            <offset value="100000" start-index="47" stop-index="52" />
+            <row-count value="10" start-index="71" stop-index="72" />
+        </limit>
+        <projections start-index="7" stop-index="7">
+            <shorthand-projection start-index="7" stop-index="7" />
+        </projections>
+        <from start-index="14" stop-index="20">
+            <simple-table name="t_order" start-index="14" stop-index="20" />
+        </from>
+        <order-by>
+            <column-item name="order_id" start-index="31" stop-index="38" />
+        </order-by>
+    </select>
+
     <select 
sql-case-id="select_pagination_with_first_skip_parameters_firebird" 
parameters="1, 2">
         <limit start-index="7" stop-index="20">
             <row-count value="1" parameter-index="0" start-index="13" 
stop-index="13" />
@@ -2097,6 +2126,103 @@
         </from>
     </select>
 
+    <select 
sql-case-id="select_pagination_with_where_parameter_offset_and_fetch_firebird" 
parameters="1, 2, 3">
+        <projections start-index="7" stop-index="7">
+            <shorthand-projection start-index="7" stop-index="7" />
+        </projections>
+        <from start-index="14" stop-index="20">
+            <simple-table name="t_order" start-index="14" stop-index="20" />
+        </from>
+        <where start-index="22" stop-index="38">
+            <expr>
+                <binary-operation-expression start-index="28" stop-index="38">
+                    <left>
+                        <column name="user_id" start-index="28" 
stop-index="34" />
+                    </left>
+                    <operator>=</operator>
+                    <right>
+                        <literal-expression value="1" start-index="38" 
stop-index="38" />
+                        <parameter-marker-expression parameter-index="0" 
start-index="38" stop-index="38" />
+                    </right>
+                </binary-operation-expression>
+            </expr>
+        </where>
+        <order-by>
+            <column-item name="order_id" start-index="49" stop-index="56" />
+        </order-by>
+        <limit start-index="58" stop-index="94" literal-start-index="58" 
literal-stop-index="94">
+            <offset value="2" parameter-index="1" start-index="65" 
stop-index="65" literal-start-index="65" literal-stop-index="65" />
+            <row-count value="3" parameter-index="2" start-index="84" 
stop-index="84" literal-start-index="84" literal-stop-index="84" />
+        </limit>
+    </select>
+
+    <select 
sql-case-id="select_pagination_with_where_parameter_fetch_firebird" 
parameters="1, 2">
+        <projections start-index="7" stop-index="7">
+            <shorthand-projection start-index="7" stop-index="7" />
+        </projections>
+        <from start-index="14" stop-index="20">
+            <simple-table name="t_order" start-index="14" stop-index="20" />
+        </from>
+        <where start-index="22" stop-index="38">
+            <expr>
+                <binary-operation-expression start-index="28" stop-index="38">
+                    <left>
+                        <column name="user_id" start-index="28" 
stop-index="34" />
+                    </left>
+                    <operator>=</operator>
+                    <right>
+                        <literal-expression value="1" start-index="38" 
stop-index="38" />
+                        <parameter-marker-expression parameter-index="0" 
start-index="38" stop-index="38" />
+                    </right>
+                </binary-operation-expression>
+            </expr>
+        </where>
+        <limit start-index="40" stop-index="62" literal-start-index="40" 
literal-stop-index="62">
+            <row-count value="2" parameter-index="1" start-index="52" 
stop-index="52" literal-start-index="52" literal-stop-index="52" />
+        </limit>
+    </select>
+
+    <select 
sql-case-id="select_pagination_with_cte_where_parameter_offset_and_fetch_firebird"
 parameters="7, 8, 9">
+        <with start-index="0" stop-index="56">
+            <common-table-expression name="c" start-index="5" stop-index="56">
+                <subquery-expression start-index="5" stop-index="56">
+                    <select>
+                        <projections start-index="18" stop-index="24">
+                            <column-projection name="user_id" start-index="18" 
stop-index="24" />
+                        </projections>
+                        <from start-index="31" stop-index="37">
+                            <simple-table name="t_order" start-index="31" 
stop-index="37" />
+                        </from>
+                        <where start-index="39" stop-index="55">
+                            <expr>
+                                <binary-operation-expression start-index="45" 
stop-index="55">
+                                    <left>
+                                        <column name="user_id" 
start-index="45" stop-index="51" />
+                                    </left>
+                                    <operator>=</operator>
+                                    <right>
+                                        <literal-expression value="7" 
start-index="55" stop-index="55" />
+                                        <parameter-marker-expression 
parameter-index="0" start-index="55" stop-index="55" />
+                                    </right>
+                                </binary-operation-expression>
+                            </expr>
+                        </where>
+                    </select>
+                </subquery-expression>
+            </common-table-expression>
+        </with>
+        <projections start-index="65" stop-index="65">
+            <shorthand-projection start-index="65" stop-index="65" />
+        </projections>
+        <from start-index="72" stop-index="72">
+            <simple-table name="c" start-index="72" stop-index="72" />
+        </from>
+        <limit start-index="74" stop-index="109" literal-start-index="74" 
literal-stop-index="109">
+            <offset value="8" parameter-index="1" start-index="81" 
stop-index="81" literal-start-index="81" literal-stop-index="81" />
+            <row-count value="9" parameter-index="2" start-index="99" 
stop-index="99" literal-start-index="99" literal-stop-index="99" />
+        </limit>
+    </select>
+
     <select sql-case-id="select_limit_offset_doris">
         <from>
             <simple-table name="t_order" start-index="14" stop-index="20" />
diff --git 
a/test/it/parser/src/main/resources/sql/supported/dml/select-pagination.xml 
b/test/it/parser/src/main/resources/sql/supported/dml/select-pagination.xml
index 757dffda74e..feb156ea114 100644
--- a/test/it/parser/src/main/resources/sql/supported/dml/select-pagination.xml
+++ b/test/it/parser/src/main/resources/sql/supported/dml/select-pagination.xml
@@ -42,6 +42,11 @@
     <sql-case id="select_pagination_with_first_skip" value="SELECT FIRST 1 
SKIP 1 1 a FROM t_order" db-types="Firebird" />
     <sql-case id="select_pagination_with_skip" value="SELECT SKIP 1 1 a FROM 
t_order" db-types="Firebird" />
     <sql-case id="select_pagination_with_first_skip_parameters_firebird" 
value="SELECT FIRST ? SKIP ? user_id FROM t_order" db-types="Firebird" />
+    <sql-case id="select_pagination_with_offset_and_fetch_firebird" 
value="SELECT * FROM t_order OFFSET 100000 ROWS FETCH FIRST 10 ROWS ONLY" 
db-types="Firebird" />
+    <sql-case id="select_pagination_with_order_by_offset_and_fetch_firebird" 
value="SELECT * FROM t_order ORDER BY order_id OFFSET 100000 ROWS FETCH FIRST 
10 ROWS ONLY" db-types="Firebird" />
+    <sql-case 
id="select_pagination_with_where_parameter_offset_and_fetch_firebird" 
value="SELECT * FROM t_order WHERE user_id = ? ORDER BY order_id OFFSET ? ROWS 
FETCH FIRST ? ROWS ONLY" db-types="Firebird" />
+    <sql-case id="select_pagination_with_where_parameter_fetch_firebird" 
value="SELECT * FROM t_order WHERE user_id = ? FETCH FIRST ? ROWS ONLY" 
db-types="Firebird" />
+    <sql-case 
id="select_pagination_with_cte_where_parameter_offset_and_fetch_firebird" 
value="WITH c AS (SELECT user_id FROM t_order WHERE user_id = ?) SELECT * FROM 
c OFFSET ? ROWS FETCH NEXT ? ROWS ONLY" db-types="Firebird" />
     <sql-case id="select_limit_offset_doris" value="SELECT * FROM t_order 
LIMIT 5 OFFSET 2" db-types="Doris" />
     <sql-case id="select_limit_only_doris" value="SELECT * FROM t_order LIMIT 
5" db-types="Doris" />
     <sql-case id="select_limit_with_params_doris" value="SELECT * FROM t_order 
LIMIT ?, ?" db-types="Doris,Hive,openGauss" />

Reply via email to