You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by zh...@apache.org on 2025/07/02 08:50:08 UTC

(shardingsphere) branch master updated: Add DialectPaginationOption.containsTop (#35855)

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

zhangliang 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 0feddb5c76d Add DialectPaginationOption.containsTop (#35855)
0feddb5c76d is described below

commit 0feddb5c76d9ce35e8fb61edbecb9eae68f008e5
Author: Liang Zhang <zh...@apache.org>
AuthorDate: Wed Jul 2 16:49:57 2025 +0800

    Add DialectPaginationOption.containsTop (#35855)
    
    * Refactor PaginationContextEngine
    
    * Refactor PaginationContextEngine
    
    * Add DialectPaginationOption.containsTop
    
    * Add DialectPaginationOption.containsTop
    
    * Add DialectPaginationOption.containsTop
    
    * Add DialectPaginationOption.containsTop
    
    * Add DialectPaginationOption.containsTop
    
    * Add DialectPaginationOption.containsTop
---
 .../protocol/MySQLDateBinaryProtocolValue.java     |  1 +
 .../merge/dql/ShardingDQLResultMergerTest.java     | 32 +++----------
 .../RowNumberDecoratorMergedResultTest.java        | 31 +++++--------
 .../pagination/engine/PaginationContextEngine.java | 46 ++++---------------
 .../engine/RowNumberPaginationContextEngine.java   |  6 +--
 ...textEngine.java => TopProjectionExtractor.java} | 52 +++++-----------------
 .../engine/PaginationContextEngineTest.java        | 25 ++++++++---
 .../RowNumberPaginationContextEngineTest.java      |  2 +-
 .../database/metadata/DialectDatabaseMetaData.java |  2 +-
 .../option/pagination/DialectPaginationOption.java |  2 +
 .../metadata/database/OracleDatabaseMetaData.java  |  2 +-
 .../database/SQLServerDatabaseMetaData.java        |  2 +-
 .../sql/execute/result/query/QueryResult.java      |  2 +-
 13 files changed, 64 insertions(+), 141 deletions(-)

diff --git a/db-protocol/mysql/src/main/java/org/apache/shardingsphere/db/protocol/mysql/packet/command/query/binary/execute/protocol/MySQLDateBinaryProtocolValue.java b/db-protocol/mysql/src/main/java/org/apache/shardingsphere/db/protocol/mysql/packet/command/query/binary/execute/protocol/MySQLDateBinaryProtocolValue.java
index 5ba7133c384..5f6454720ff 100644
--- a/db-protocol/mysql/src/main/java/org/apache/shardingsphere/db/protocol/mysql/packet/command/query/binary/execute/protocol/MySQLDateBinaryProtocolValue.java
+++ b/db-protocol/mysql/src/main/java/org/apache/shardingsphere/db/protocol/mysql/packet/command/query/binary/execute/protocol/MySQLDateBinaryProtocolValue.java
@@ -87,6 +87,7 @@ public final class MySQLDateBinaryProtocolValue implements MySQLBinaryProtocolVa
         writeNanos(payload, nanos);
     }
     
+    @SuppressWarnings("UseOfObsoleteDateTimeApi")
     private LocalDateTime getLocalDateTime(final Object value) {
         if (value instanceof LocalDate) {
             return ((LocalDate) value).atStartOfDay();
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 3a473adbd9b..94d4f5f6875 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
@@ -36,7 +36,6 @@ import org.apache.shardingsphere.sharding.merge.dql.groupby.GroupByMemoryMergedR
 import org.apache.shardingsphere.sharding.merge.dql.groupby.GroupByStreamMergedResult;
 import org.apache.shardingsphere.sharding.merge.dql.orderby.OrderByStreamMergedResult;
 import org.apache.shardingsphere.sharding.merge.dql.pagination.LimitDecoratorMergedResult;
-import org.apache.shardingsphere.sharding.merge.dql.pagination.RowNumberDecoratorMergedResult;
 import org.apache.shardingsphere.sharding.merge.dql.pagination.TopAndRowNumberDecoratorMergedResult;
 import org.apache.shardingsphere.sql.parser.statement.core.enums.AggregationType;
 import org.apache.shardingsphere.sql.parser.statement.core.enums.OrderDirection;
@@ -52,7 +51,6 @@ import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.order.ite
 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.NumberLiteralLimitValueSegment;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.rownum.NumberLiteralRowNumberValueSegment;
-import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.top.TopProjectionSegment;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.predicate.WhereSegment;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.SimpleTableSegment;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.SubqueryTableSegment;
@@ -136,9 +134,6 @@ class ShardingDQLResultMergerTest {
         SubquerySegment subquerySegment = mock(SubquerySegment.class);
         SelectStatement subSelectStatement = mock(SelectStatement.class);
         ProjectionsSegment subProjectionsSegment = mock(ProjectionsSegment.class);
-        TopProjectionSegment topProjectionSegment = mock(TopProjectionSegment.class);
-        when(topProjectionSegment.getAlias()).thenReturn("row_id");
-        when(subProjectionsSegment.getProjections()).thenReturn(Collections.singletonList(topProjectionSegment));
         when(subSelectStatement.getProjections()).thenReturn(subProjectionsSegment);
         when(subquerySegment.getSelect()).thenReturn(subSelectStatement);
         when(subqueryTableSegment.getSubquery()).thenReturn(subquerySegment);
@@ -147,8 +142,7 @@ class ShardingDQLResultMergerTest {
         SelectStatementContext selectStatementContext = new SelectStatementContext(
                 oracleDatabaseType, selectStatement, null, createShardingSphereMetaData(database), "foo_db", Collections.emptyList());
         MergedResult actual = resultMerger.merge(createQueryResults(), selectStatementContext, createDatabase(), mock(ConnectionContext.class));
-        assertThat(actual, instanceOf(RowNumberDecoratorMergedResult.class));
-        assertThat(((RowNumberDecoratorMergedResult) actual).getMergedResult(), instanceOf(IteratorStreamMergedResult.class));
+        assertThat(actual, instanceOf(IteratorStreamMergedResult.class));
     }
     
     @Test
@@ -207,9 +201,6 @@ class ShardingDQLResultMergerTest {
         SubquerySegment subquerySegment = mock(SubquerySegment.class);
         SelectStatement subSelectStatement = mock(SelectStatement.class);
         ProjectionsSegment subProjectionsSegment = mock(ProjectionsSegment.class);
-        TopProjectionSegment topProjectionSegment = mock(TopProjectionSegment.class);
-        when(topProjectionSegment.getAlias()).thenReturn("row_id");
-        when(subProjectionsSegment.getProjections()).thenReturn(Collections.singletonList(topProjectionSegment));
         when(subSelectStatement.getProjections()).thenReturn(subProjectionsSegment);
         when(subquerySegment.getSelect()).thenReturn(subSelectStatement);
         when(subqueryTableSegment.getSubquery()).thenReturn(subquerySegment);
@@ -221,8 +212,7 @@ class ShardingDQLResultMergerTest {
         SelectStatementContext selectStatementContext = new SelectStatementContext(oracleDatabaseType,
                 selectStatement, null, createShardingSphereMetaData(database), "foo_db", Collections.emptyList());
         MergedResult actual = resultMerger.merge(createQueryResults(), selectStatementContext, createDatabase(), mock(ConnectionContext.class));
-        assertThat(actual, instanceOf(RowNumberDecoratorMergedResult.class));
-        assertThat(((RowNumberDecoratorMergedResult) actual).getMergedResult(), instanceOf(OrderByStreamMergedResult.class));
+        assertThat(actual, instanceOf(OrderByStreamMergedResult.class));
     }
     
     @Test
@@ -284,9 +274,6 @@ class ShardingDQLResultMergerTest {
         SubquerySegment subquerySegment = mock(SubquerySegment.class);
         SelectStatement subSelectStatement = mock(SelectStatement.class);
         ProjectionsSegment subProjectionsSegment = mock(ProjectionsSegment.class);
-        TopProjectionSegment topProjectionSegment = mock(TopProjectionSegment.class);
-        when(topProjectionSegment.getAlias()).thenReturn("row_id");
-        when(subProjectionsSegment.getProjections()).thenReturn(Collections.singletonList(topProjectionSegment));
         when(subSelectStatement.getProjections()).thenReturn(subProjectionsSegment);
         when(subquerySegment.getSelect()).thenReturn(subSelectStatement);
         when(subqueryTableSegment.getSubquery()).thenReturn(subquerySegment);
@@ -299,8 +286,7 @@ class ShardingDQLResultMergerTest {
         SelectStatementContext selectStatementContext = new SelectStatementContext(
                 oracleDatabaseType, selectStatement, null, createShardingSphereMetaData(database), "foo_db", Collections.emptyList());
         MergedResult actual = resultMerger.merge(createQueryResults(), selectStatementContext, createDatabase(), mock(ConnectionContext.class));
-        assertThat(actual, instanceOf(RowNumberDecoratorMergedResult.class));
-        assertThat(((RowNumberDecoratorMergedResult) actual).getMergedResult(), instanceOf(GroupByStreamMergedResult.class));
+        assertThat(actual, instanceOf(GroupByStreamMergedResult.class));
     }
     
     @Test
@@ -361,9 +347,6 @@ class ShardingDQLResultMergerTest {
         SubquerySegment subquerySegment = mock(SubquerySegment.class);
         SelectStatement subSelectStatement = mock(SelectStatement.class);
         ProjectionsSegment subProjectionsSegment = mock(ProjectionsSegment.class);
-        TopProjectionSegment topProjectionSegment = mock(TopProjectionSegment.class);
-        when(topProjectionSegment.getAlias()).thenReturn("row_id");
-        when(subProjectionsSegment.getProjections()).thenReturn(Collections.singletonList(topProjectionSegment));
         when(subSelectStatement.getProjections()).thenReturn(subProjectionsSegment);
         when(subquerySegment.getSelect()).thenReturn(subSelectStatement);
         when(subqueryTableSegment.getSubquery()).thenReturn(subquerySegment);
@@ -376,8 +359,7 @@ class ShardingDQLResultMergerTest {
         SelectStatementContext selectStatementContext = new SelectStatementContext(
                 oracleDatabaseType, selectStatement, null, createShardingSphereMetaData(database), "foo_db", Collections.emptyList());
         MergedResult actual = resultMerger.merge(createQueryResults(), selectStatementContext, createDatabase(), mock(ConnectionContext.class));
-        assertThat(actual, instanceOf(RowNumberDecoratorMergedResult.class));
-        assertThat(((RowNumberDecoratorMergedResult) actual).getMergedResult(), instanceOf(GroupByStreamMergedResult.class));
+        assertThat(actual, instanceOf(GroupByStreamMergedResult.class));
     }
     
     @Test
@@ -439,9 +421,6 @@ class ShardingDQLResultMergerTest {
         SubquerySegment subquerySegment = mock(SubquerySegment.class);
         SelectStatement subSelectStatement = mock(SelectStatement.class);
         ProjectionsSegment subProjectionsSegment = mock(ProjectionsSegment.class);
-        TopProjectionSegment topProjectionSegment = mock(TopProjectionSegment.class);
-        when(topProjectionSegment.getAlias()).thenReturn("row_id");
-        when(subProjectionsSegment.getProjections()).thenReturn(Collections.singletonList(topProjectionSegment));
         when(subSelectStatement.getProjections()).thenReturn(subProjectionsSegment);
         when(subquerySegment.getSelect()).thenReturn(subSelectStatement);
         when(subqueryTableSegment.getSubquery()).thenReturn(subquerySegment);
@@ -454,8 +433,7 @@ class ShardingDQLResultMergerTest {
         SelectStatementContext selectStatementContext = new SelectStatementContext(
                 oracleDatabaseType, selectStatement, null, createShardingSphereMetaData(database), "foo_db", Collections.emptyList());
         MergedResult actual = resultMerger.merge(createQueryResults(), selectStatementContext, createDatabase(), mock(ConnectionContext.class));
-        assertThat(actual, instanceOf(RowNumberDecoratorMergedResult.class));
-        assertThat(((RowNumberDecoratorMergedResult) actual).getMergedResult(), instanceOf(GroupByMemoryMergedResult.class));
+        assertThat(actual, instanceOf(GroupByMemoryMergedResult.class));
     }
     
     @Test
diff --git a/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/merge/dql/pagination/RowNumberDecoratorMergedResultTest.java b/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/merge/dql/pagination/RowNumberDecoratorMergedResultTest.java
index df7ea5ed781..2dee91490e5 100644
--- a/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/merge/dql/pagination/RowNumberDecoratorMergedResultTest.java
+++ b/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/merge/dql/pagination/RowNumberDecoratorMergedResultTest.java
@@ -34,8 +34,6 @@ import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.Bina
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.simple.LiteralExpressionSegment;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.subquery.SubquerySegment;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.ProjectionsSegment;
-import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.rownum.NumberLiteralRowNumberValueSegment;
-import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.top.TopProjectionSegment;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.predicate.WhereSegment;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.SubqueryTableSegment;
 import org.apache.shardingsphere.sql.parser.statement.core.statement.type.dml.SelectStatement;
@@ -71,9 +69,6 @@ class RowNumberDecoratorMergedResultTest {
         SubquerySegment subquerySegment = mock(SubquerySegment.class);
         SelectStatement subSelectStatement = mock(SelectStatement.class);
         ProjectionsSegment subProjectionsSegment = mock(ProjectionsSegment.class);
-        TopProjectionSegment topProjectionSegment = mock(TopProjectionSegment.class);
-        when(topProjectionSegment.getAlias()).thenReturn("row_id");
-        when(subProjectionsSegment.getProjections()).thenReturn(Collections.singletonList(topProjectionSegment));
         when(subSelectStatement.getProjections()).thenReturn(subProjectionsSegment);
         when(subquerySegment.getSelect()).thenReturn(subSelectStatement);
         when(subqueryTableSegment.getSubquery()).thenReturn(subquerySegment);
@@ -83,8 +78,11 @@ class RowNumberDecoratorMergedResultTest {
         ShardingSphereDatabase database = mock(ShardingSphereDatabase.class, RETURNS_DEEP_STUBS);
         when(database.getName()).thenReturn("foo_db");
         SelectStatementContext selectStatementContext = new SelectStatementContext(databaseType, selectStatement, null, createShardingSphereMetaData(database), "foo_db", Collections.emptyList());
-        MergedResult actual = resultMerger.merge(Arrays.asList(mockQueryResult(), mockQueryResult(), mockQueryResult(), mockQueryResult()), selectStatementContext, database,
-                mock(ConnectionContext.class));
+        MergedResult actual = resultMerger.merge(
+                Arrays.asList(mockQueryResult(), mockQueryResult(), mockQueryResult(), mockQueryResult()), selectStatementContext, database, mock(ConnectionContext.class));
+        for (int i = 0; i < 8; i++) {
+            assertTrue(actual.next());
+        }
         assertFalse(actual.next());
     }
     
@@ -119,10 +117,6 @@ class RowNumberDecoratorMergedResultTest {
         SubquerySegment subquerySegment = mock(SubquerySegment.class);
         SelectStatement subSelectStatement = mock(SelectStatement.class);
         ProjectionsSegment subProjectionsSegment = mock(ProjectionsSegment.class);
-        TopProjectionSegment topProjectionSegment = mock(TopProjectionSegment.class);
-        when(topProjectionSegment.getAlias()).thenReturn("row_id");
-        when(topProjectionSegment.getTop()).thenReturn(new NumberLiteralRowNumberValueSegment(0, 0, 4L, false));
-        when(subProjectionsSegment.getProjections()).thenReturn(Collections.singletonList(topProjectionSegment));
         when(subSelectStatement.getProjections()).thenReturn(subProjectionsSegment);
         when(subquerySegment.getSelect()).thenReturn(subSelectStatement);
         when(subqueryTableSegment.getSubquery()).thenReturn(subquerySegment);
@@ -134,8 +128,9 @@ class RowNumberDecoratorMergedResultTest {
         SelectStatementContext selectStatementContext = new SelectStatementContext(databaseType, selectStatement, null, createShardingSphereMetaData(database), "foo_db", Collections.emptyList());
         MergedResult actual = resultMerger.merge(Arrays.asList(mockQueryResult(), mockQueryResult(), mockQueryResult(), mockQueryResult()), selectStatementContext, database,
                 mock(ConnectionContext.class));
-        assertTrue(actual.next());
-        assertTrue(actual.next());
+        for (int i = 0; i < 8; i++) {
+            assertTrue(actual.next());
+        }
         assertFalse(actual.next());
     }
     
@@ -154,10 +149,6 @@ class RowNumberDecoratorMergedResultTest {
         SubquerySegment subquerySegment = mock(SubquerySegment.class);
         SelectStatement subSelectStatement = mock(SelectStatement.class);
         ProjectionsSegment subProjectionsSegment = mock(ProjectionsSegment.class);
-        TopProjectionSegment topProjectionSegment = mock(TopProjectionSegment.class);
-        when(topProjectionSegment.getAlias()).thenReturn("row_id");
-        when(topProjectionSegment.getTop()).thenReturn(new NumberLiteralRowNumberValueSegment(0, 0, 4L, true));
-        when(subProjectionsSegment.getProjections()).thenReturn(Collections.singletonList(topProjectionSegment));
         when(subSelectStatement.getProjections()).thenReturn(subProjectionsSegment);
         when(subquerySegment.getSelect()).thenReturn(subSelectStatement);
         when(subqueryTableSegment.getSubquery()).thenReturn(subquerySegment);
@@ -169,9 +160,9 @@ class RowNumberDecoratorMergedResultTest {
         SelectStatementContext selectStatementContext = new SelectStatementContext(databaseType, selectStatement, null, createShardingSphereMetaData(database), "foo_db", Collections.emptyList());
         MergedResult actual =
                 resultMerger.merge(Arrays.asList(mockQueryResult(), mockQueryResult(), mockQueryResult(), mockQueryResult()), selectStatementContext, database, mock(ConnectionContext.class));
-        assertTrue(actual.next());
-        assertTrue(actual.next());
-        assertTrue(actual.next());
+        for (int i = 0; i < 8; i++) {
+            assertTrue(actual.next());
+        }
         assertFalse(actual.next());
     }
     
diff --git a/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/pagination/engine/PaginationContextEngine.java b/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/pagination/engine/PaginationContextEngine.java
index 326d1860e23..77448c084a4 100644
--- a/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/pagination/engine/PaginationContextEngine.java
+++ b/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/pagination/engine/PaginationContextEngine.java
@@ -22,17 +22,12 @@ import org.apache.shardingsphere.infra.binder.context.segment.select.pagination.
 import org.apache.shardingsphere.infra.binder.context.segment.select.projection.ProjectionsContext;
 import org.apache.shardingsphere.infra.database.core.metadata.database.metadata.option.pagination.DialectPaginationOption;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.ExpressionSegment;
-import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.ProjectionSegment;
-import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.SubqueryProjectionSegment;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.limit.LimitSegment;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.top.TopProjectionSegment;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.predicate.WhereSegment;
-import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.SubqueryTableSegment;
 import org.apache.shardingsphere.sql.parser.statement.core.statement.type.dml.SelectStatement;
-import org.apache.shardingsphere.sql.parser.statement.core.util.SQLUtils;
 
 import java.util.Collection;
-import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Optional;
@@ -43,7 +38,7 @@ import java.util.Optional;
 @RequiredArgsConstructor
 public final class PaginationContextEngine {
     
-    private final DialectPaginationOption paginationOption;
+    private final DialectPaginationOption option;
     
     /**
      * Create pagination context.
@@ -64,40 +59,15 @@ public final class PaginationContextEngine {
         for (WhereSegment each : whereSegments) {
             expressions.add(each.getExpr());
         }
-        Optional<TopProjectionSegment> topProjectionSegment = findTopProjection(selectStatement);
-        if (topProjectionSegment.isPresent()) {
-            return new TopPaginationContextEngine().createPaginationContext(topProjectionSegment.get(), expressions, params);
-        }
-        if (!expressions.isEmpty() && paginationOption.isContainsRowNumber()) {
-            return new RowNumberPaginationContextEngine(paginationOption).createPaginationContext(expressions, projectionsContext, params);
-        }
-        return new PaginationContext(null, null, params);
-    }
-    
-    private Optional<TopProjectionSegment> findTopProjection(final SelectStatement selectStatement) {
-        for (ProjectionSegment each : selectStatement.getProjections().getProjections()) {
-            if (each instanceof SubqueryProjectionSegment) {
-                return findTopProjection0(((SubqueryProjectionSegment) each).getSubquery().getSelect());
+        if (option.isContainsTop()) {
+            Optional<TopProjectionSegment> topProjectionSegment = TopProjectionExtractor.findTopProjection(selectStatement);
+            if (topProjectionSegment.isPresent()) {
+                return new TopPaginationContextEngine().createPaginationContext(topProjectionSegment.get(), expressions, params);
             }
         }
-        return findTopProjection0(selectStatement);
-    }
-    
-    private Optional<TopProjectionSegment> findTopProjection0(final SelectStatement selectStatement) {
-        for (ProjectionSegment each : selectStatement.getProjections().getProjections()) {
-            if (each instanceof TopProjectionSegment) {
-                return Optional.of((TopProjectionSegment) each);
-            }
+        if (!expressions.isEmpty() && option.isContainsRowNumber()) {
+            return new RowNumberPaginationContextEngine(option).createPaginationContext(expressions, projectionsContext, params);
         }
-        List<SubqueryTableSegment> subqueryTableSegments = selectStatement.getFrom().map(SQLUtils::getSubqueryTableSegmentFromTableSegment).orElse(Collections.emptyList());
-        for (SubqueryTableSegment subquery : subqueryTableSegments) {
-            SelectStatement subquerySelect = subquery.getSubquery().getSelect();
-            for (ProjectionSegment each : subquerySelect.getProjections().getProjections()) {
-                if (each instanceof TopProjectionSegment) {
-                    return Optional.of((TopProjectionSegment) each);
-                }
-            }
-        }
-        return Optional.empty();
+        return new PaginationContext(null, null, params);
     }
 }
diff --git a/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/pagination/engine/RowNumberPaginationContextEngine.java b/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/pagination/engine/RowNumberPaginationContextEngine.java
index 80eebe1c623..a7e2c56f849 100644
--- a/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/pagination/engine/RowNumberPaginationContextEngine.java
+++ b/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/pagination/engine/RowNumberPaginationContextEngine.java
@@ -45,7 +45,7 @@ import java.util.stream.Collectors;
 @RequiredArgsConstructor
 public final class RowNumberPaginationContextEngine {
     
-    private final DialectPaginationOption paginationOption;
+    private final DialectPaginationOption option;
     
     /**
      * Create pagination context.
@@ -76,7 +76,7 @@ public final class RowNumberPaginationContextEngine {
     }
     
     private Optional<String> findRowNumberAlias(final ProjectionsContext projectionsContext) {
-        String rowNumberColumnName = paginationOption.getRowNumberColumnName();
+        String rowNumberColumnName = option.getRowNumberColumnName();
         if (Strings.isNullOrEmpty(rowNumberColumnName)) {
             return Optional.empty();
         }
@@ -89,7 +89,7 @@ public final class RowNumberPaginationContextEngine {
             ExpressionSegment left = ((BinaryOperationExpression) predicate).getLeft();
             if (left instanceof ColumnSegment) {
                 String leftColumnValue = ((ColumnSegment) left).getIdentifier().getValue();
-                return leftColumnValue.equalsIgnoreCase(paginationOption.getRowNumberColumnName()) || leftColumnValue.equalsIgnoreCase(rowNumberAlias);
+                return leftColumnValue.equalsIgnoreCase(option.getRowNumberColumnName()) || leftColumnValue.equalsIgnoreCase(rowNumberAlias);
             }
             return false;
         }
diff --git a/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/pagination/engine/PaginationContextEngine.java b/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/pagination/engine/TopProjectionExtractor.java
similarity index 52%
copy from infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/pagination/engine/PaginationContextEngine.java
copy to infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/pagination/engine/TopProjectionExtractor.java
index 326d1860e23..dbb32b21e5b 100644
--- a/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/pagination/engine/PaginationContextEngine.java
+++ b/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/segment/select/pagination/engine/TopProjectionExtractor.java
@@ -17,64 +17,32 @@
 
 package org.apache.shardingsphere.infra.binder.context.segment.select.pagination.engine;
 
-import lombok.RequiredArgsConstructor;
-import org.apache.shardingsphere.infra.binder.context.segment.select.pagination.PaginationContext;
-import org.apache.shardingsphere.infra.binder.context.segment.select.projection.ProjectionsContext;
-import org.apache.shardingsphere.infra.database.core.metadata.database.metadata.option.pagination.DialectPaginationOption;
-import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.ExpressionSegment;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.ProjectionSegment;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.item.SubqueryProjectionSegment;
-import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.limit.LimitSegment;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.top.TopProjectionSegment;
-import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.predicate.WhereSegment;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.SubqueryTableSegment;
 import org.apache.shardingsphere.sql.parser.statement.core.statement.type.dml.SelectStatement;
 import org.apache.shardingsphere.sql.parser.statement.core.util.SQLUtils;
 
-import java.util.Collection;
 import java.util.Collections;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.Optional;
 
 /**
- * Pagination context engine.
+ * Top projection extractor.
  */
-@RequiredArgsConstructor
-public final class PaginationContextEngine {
-    
-    private final DialectPaginationOption paginationOption;
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class TopProjectionExtractor {
     
     /**
-     * Create pagination context.
+     * Find top projection.
      *
-     * @param selectStatement SQL statement
-     * @param projectionsContext projections context
-     * @param params SQL parameters
-     * @param whereSegments where segments
-     * @return pagination context
+     * @param selectStatement select statement
+     * @return top projection
      */
-    public PaginationContext createPaginationContext(final SelectStatement selectStatement, final ProjectionsContext projectionsContext,
-                                                     final List<Object> params, final Collection<WhereSegment> whereSegments) {
-        Optional<LimitSegment> limitSegment = selectStatement.getLimit();
-        if (limitSegment.isPresent()) {
-            return new LimitPaginationContextEngine().createPaginationContext(limitSegment.get(), params);
-        }
-        Collection<ExpressionSegment> expressions = new LinkedList<>();
-        for (WhereSegment each : whereSegments) {
-            expressions.add(each.getExpr());
-        }
-        Optional<TopProjectionSegment> topProjectionSegment = findTopProjection(selectStatement);
-        if (topProjectionSegment.isPresent()) {
-            return new TopPaginationContextEngine().createPaginationContext(topProjectionSegment.get(), expressions, params);
-        }
-        if (!expressions.isEmpty() && paginationOption.isContainsRowNumber()) {
-            return new RowNumberPaginationContextEngine(paginationOption).createPaginationContext(expressions, projectionsContext, params);
-        }
-        return new PaginationContext(null, null, params);
-    }
-    
-    private Optional<TopProjectionSegment> findTopProjection(final SelectStatement selectStatement) {
+    public static Optional<TopProjectionSegment> findTopProjection(final SelectStatement selectStatement) {
         for (ProjectionSegment each : selectStatement.getProjections().getProjections()) {
             if (each instanceof SubqueryProjectionSegment) {
                 return findTopProjection0(((SubqueryProjectionSegment) each).getSubquery().getSelect());
@@ -83,7 +51,7 @@ public final class PaginationContextEngine {
         return findTopProjection0(selectStatement);
     }
     
-    private Optional<TopProjectionSegment> findTopProjection0(final SelectStatement selectStatement) {
+    private static Optional<TopProjectionSegment> findTopProjection0(final SelectStatement selectStatement) {
         for (ProjectionSegment each : selectStatement.getProjections().getProjections()) {
             if (each instanceof TopProjectionSegment) {
                 return Optional.of((TopProjectionSegment) each);
diff --git a/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/context/segment/select/pagination/engine/PaginationContextEngineTest.java b/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/context/segment/select/pagination/engine/PaginationContextEngineTest.java
index 8e4887322e5..287c9bccdea 100644
--- a/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/context/segment/select/pagination/engine/PaginationContextEngineTest.java
+++ b/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/context/segment/select/pagination/engine/PaginationContextEngineTest.java
@@ -30,6 +30,7 @@ import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.paginatio
 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.NumberLiteralLimitValueSegment;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.rownum.NumberLiteralRowNumberValueSegment;
+import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.rownum.RowNumberValueSegment;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.pagination.top.TopProjectionSegment;
 import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.predicate.WhereSegment;
 import org.apache.shardingsphere.sql.parser.statement.core.statement.type.dml.SelectStatement;
@@ -52,7 +53,7 @@ class PaginationContextEngineTest {
         selectStatement.setLimit(new LimitSegment(0, 10, new NumberLiteralLimitValueSegment(0, 10, 100L),
                 new NumberLiteralLimitValueSegment(11, 20, 200L)));
         PaginationContext paginationContext = new PaginationContextEngine(
-                new DialectPaginationOption(false, "")).createPaginationContext(selectStatement, mock(ProjectionsContext.class), Collections.emptyList(), Collections.emptyList());
+                new DialectPaginationOption(false, "", false)).createPaginationContext(selectStatement, mock(ProjectionsContext.class), Collections.emptyList(), Collections.emptyList());
         assertTrue(paginationContext.getOffsetSegment().isPresent());
         assertThat(paginationContext.getOffsetSegment().get(), instanceOf(LimitValueSegment.class));
         assertTrue(paginationContext.getRowCountSegment().isPresent());
@@ -63,12 +64,24 @@ class PaginationContextEngineTest {
     void assertCreatePaginationContextWithTopSegment() {
         SelectStatement subquerySelectStatement = new SelectStatement();
         subquerySelectStatement.setProjections(new ProjectionsSegment(0, 0));
-        subquerySelectStatement.getProjections().getProjections().add(new TopProjectionSegment(0, 10, null, ""));
+        RowNumberValueSegment topValueSegment = new NumberLiteralRowNumberValueSegment(0, 0, 100L, false);
+        subquerySelectStatement.getProjections().getProjections().add(new TopProjectionSegment(0, 10, topValueSegment, ""));
         SelectStatement selectStatement = new SelectStatement();
         selectStatement.setProjections(new ProjectionsSegment(0, 0));
         selectStatement.getProjections().getProjections().add(new SubqueryProjectionSegment(new SubquerySegment(0, 0, subquerySelectStatement, ""), ""));
         PaginationContext paginationContext = new PaginationContextEngine(
-                new DialectPaginationOption(false, "")).createPaginationContext(selectStatement, mock(ProjectionsContext.class), Collections.emptyList(), Collections.emptyList());
+                new DialectPaginationOption(false, "", true)).createPaginationContext(selectStatement, mock(ProjectionsContext.class), Collections.emptyList(), Collections.emptyList());
+        assertFalse(paginationContext.getOffsetSegment().isPresent());
+        assertTrue(paginationContext.getRowCountSegment().isPresent());
+        assertThat(paginationContext.getRowCountSegment().get(), instanceOf(NumberLiteralRowNumberValueSegment.class));
+    }
+    
+    @Test
+    void assertCreatePaginationContextWithoutTopSegment() {
+        SelectStatement selectStatement = new SelectStatement();
+        selectStatement.setProjections(new ProjectionsSegment(0, 0));
+        PaginationContext paginationContext = new PaginationContextEngine(
+                new DialectPaginationOption(false, "", true)).createPaginationContext(selectStatement, mock(ProjectionsContext.class), Collections.emptyList(), Collections.emptyList());
         assertFalse(paginationContext.getOffsetSegment().isPresent());
         assertFalse(paginationContext.getRowCountSegment().isPresent());
     }
@@ -83,7 +96,7 @@ class PaginationContextEngineTest {
         selectStatement.setWhere(where);
         ProjectionsContext projectionsContext = new ProjectionsContext(0, 0, false, Collections.emptyList());
         PaginationContext paginationContext = new PaginationContextEngine(
-                new DialectPaginationOption(true, "ROW_NUMBER")).createPaginationContext(selectStatement, projectionsContext, Collections.emptyList(), Collections.singletonList(where));
+                new DialectPaginationOption(true, "ROW_NUMBER", false)).createPaginationContext(selectStatement, projectionsContext, Collections.emptyList(), Collections.singletonList(where));
         assertFalse(paginationContext.getOffsetSegment().isPresent());
         assertTrue(paginationContext.getRowCountSegment().isPresent());
         assertThat(paginationContext.getRowCountSegment().get(), instanceOf(NumberLiteralRowNumberValueSegment.class));
@@ -99,7 +112,7 @@ class PaginationContextEngineTest {
         selectStatement.setWhere(where);
         ProjectionsContext projectionsContext = new ProjectionsContext(0, 0, false, Collections.emptyList());
         PaginationContext paginationContext = new PaginationContextEngine(
-                new DialectPaginationOption(false, "")).createPaginationContext(selectStatement, projectionsContext, Collections.emptyList(), Collections.singletonList(where));
+                new DialectPaginationOption(false, "", false)).createPaginationContext(selectStatement, projectionsContext, Collections.emptyList(), Collections.singletonList(where));
         assertFalse(paginationContext.getOffsetSegment().isPresent());
         assertFalse(paginationContext.getRowCountSegment().isPresent());
     }
@@ -110,7 +123,7 @@ class PaginationContextEngineTest {
         selectStatement.setProjections(new ProjectionsSegment(0, 0));
         ProjectionsContext projectionsContext = new ProjectionsContext(0, 0, false, Collections.emptyList());
         PaginationContext paginationContext = new PaginationContextEngine(
-                new DialectPaginationOption(false, "")).createPaginationContext(selectStatement, projectionsContext, Collections.emptyList(), Collections.emptyList());
+                new DialectPaginationOption(false, "", false)).createPaginationContext(selectStatement, projectionsContext, Collections.emptyList(), Collections.emptyList());
         assertFalse(paginationContext.getOffsetSegment().isPresent());
         assertFalse(paginationContext.getRowCountSegment().isPresent());
     }
diff --git a/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/context/segment/select/pagination/engine/RowNumberPaginationContextEngineTest.java b/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/context/segment/select/pagination/engine/RowNumberPaginationContextEngineTest.java
index dd0c0748dad..31c8e149c24 100644
--- a/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/context/segment/select/pagination/engine/RowNumberPaginationContextEngineTest.java
+++ b/infra/binder/core/src/test/java/org/apache/shardingsphere/infra/binder/context/segment/select/pagination/engine/RowNumberPaginationContextEngineTest.java
@@ -50,7 +50,7 @@ class RowNumberPaginationContextEngineTest {
     
     private static final String ROW_NUMBER_COLUMN_ALIAS = "predicateRowNumberAlias";
     
-    private final RowNumberPaginationContextEngine paginationContextEngine = new RowNumberPaginationContextEngine(new DialectPaginationOption(true, "ROWNUM"));
+    private final RowNumberPaginationContextEngine paginationContextEngine = new RowNumberPaginationContextEngine(new DialectPaginationOption(true, "ROWNUM", false));
     
     @Test
     void assertCreatePaginationContextWhenRowNumberAliasNotPresent() {
diff --git a/infra/database/core/src/main/java/org/apache/shardingsphere/infra/database/core/metadata/database/metadata/DialectDatabaseMetaData.java b/infra/database/core/src/main/java/org/apache/shardingsphere/infra/database/core/metadata/database/metadata/DialectDatabaseMetaData.java
index c4b8eacb444..5296fb5c5ea 100644
--- a/infra/database/core/src/main/java/org/apache/shardingsphere/infra/database/core/metadata/database/metadata/DialectDatabaseMetaData.java
+++ b/infra/database/core/src/main/java/org/apache/shardingsphere/infra/database/core/metadata/database/metadata/DialectDatabaseMetaData.java
@@ -145,7 +145,7 @@ public interface DialectDatabaseMetaData extends DatabaseTypedSPI {
      * @return pagination option
      */
     default DialectPaginationOption getPaginationOption() {
-        return new DialectPaginationOption(false, "");
+        return new DialectPaginationOption(false, "", false);
     }
     
     /**
diff --git a/infra/database/core/src/main/java/org/apache/shardingsphere/infra/database/core/metadata/database/metadata/option/pagination/DialectPaginationOption.java b/infra/database/core/src/main/java/org/apache/shardingsphere/infra/database/core/metadata/database/metadata/option/pagination/DialectPaginationOption.java
index fea40c90a87..948fcbda0d1 100644
--- a/infra/database/core/src/main/java/org/apache/shardingsphere/infra/database/core/metadata/database/metadata/option/pagination/DialectPaginationOption.java
+++ b/infra/database/core/src/main/java/org/apache/shardingsphere/infra/database/core/metadata/database/metadata/option/pagination/DialectPaginationOption.java
@@ -30,4 +30,6 @@ public final class DialectPaginationOption {
     private final boolean containsRowNumber;
     
     private final String rowNumberColumnName;
+    
+    private final boolean containsTop;
 }
diff --git a/infra/database/type/oracle/src/main/java/org/apache/shardingsphere/infra/database/oracle/metadata/database/OracleDatabaseMetaData.java b/infra/database/type/oracle/src/main/java/org/apache/shardingsphere/infra/database/oracle/metadata/database/OracleDatabaseMetaData.java
index fe4a10333e7..c23a3e5c76f 100644
--- a/infra/database/type/oracle/src/main/java/org/apache/shardingsphere/infra/database/oracle/metadata/database/OracleDatabaseMetaData.java
+++ b/infra/database/type/oracle/src/main/java/org/apache/shardingsphere/infra/database/oracle/metadata/database/OracleDatabaseMetaData.java
@@ -74,7 +74,7 @@ public final class OracleDatabaseMetaData implements DialectDatabaseMetaData {
     
     @Override
     public DialectPaginationOption getPaginationOption() {
-        return new DialectPaginationOption(true, "ROWNUM");
+        return new DialectPaginationOption(true, "ROWNUM", false);
     }
     
     @Override
diff --git a/infra/database/type/sqlserver/src/main/java/org/apache/shardingsphere/infra/database/sqlserver/metadata/database/SQLServerDatabaseMetaData.java b/infra/database/type/sqlserver/src/main/java/org/apache/shardingsphere/infra/database/sqlserver/metadata/database/SQLServerDatabaseMetaData.java
index 2e7ffaf6787..3d17ae1a828 100644
--- a/infra/database/type/sqlserver/src/main/java/org/apache/shardingsphere/infra/database/sqlserver/metadata/database/SQLServerDatabaseMetaData.java
+++ b/infra/database/type/sqlserver/src/main/java/org/apache/shardingsphere/infra/database/sqlserver/metadata/database/SQLServerDatabaseMetaData.java
@@ -55,7 +55,7 @@ public final class SQLServerDatabaseMetaData implements DialectDatabaseMetaData
     
     @Override
     public DialectPaginationOption getPaginationOption() {
-        return new DialectPaginationOption(true, "ROW_NUMBER");
+        return new DialectPaginationOption(true, "ROW_NUMBER", true);
     }
     
     @Override
diff --git a/infra/executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/execute/result/query/QueryResult.java b/infra/executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/execute/result/query/QueryResult.java
index 32f47ca1c20..0ef5bdc7093 100644
--- a/infra/executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/execute/result/query/QueryResult.java
+++ b/infra/executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/execute/result/query/QueryResult.java
@@ -58,7 +58,7 @@ public interface QueryResult extends ExecuteResult, AutoCloseable {
      * @return calendar value
      * @throws SQLException SQL exception
      */
-    Object getCalendarValue(int columnIndex, Class<?> type, Calendar calendar) throws SQLException;
+    Object getCalendarValue(int columnIndex, Class<?> type, @SuppressWarnings("UseOfObsoleteDateTimeApi") Calendar calendar) throws SQLException;
     
     /**
      * Get input stream.