View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.shardingsphere.infra.binder.context.segment.select.pagination;
19  
20  import lombok.Getter;
21  import org.apache.shardingsphere.infra.binder.context.statement.dml.SelectStatementContext;
22  import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.NumberLiteralPaginationValueSegment;
23  import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.PaginationValueSegment;
24  import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.ParameterMarkerPaginationValueSegment;
25  import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.limit.LimitValueSegment;
26  import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.rownum.ExpressionRowNumberValueSegment;
27  
28  import java.util.List;
29  import java.util.Optional;
30  
31  /**
32   * Pagination context.
33   */
34  public final class PaginationContext {
35      
36      @Getter
37      private final boolean hasPagination;
38      
39      private final PaginationValueSegment offsetSegment;
40      
41      private final PaginationValueSegment rowCountSegment;
42      
43      private final long actualOffset;
44      
45      private final Long actualRowCount;
46      
47      public PaginationContext(final PaginationValueSegment offsetSegment, final PaginationValueSegment rowCountSegment, final List<Object> params) {
48          hasPagination = null != offsetSegment || null != rowCountSegment;
49          this.offsetSegment = offsetSegment;
50          this.rowCountSegment = rowCountSegment;
51          actualOffset = null == offsetSegment ? 0L : getValue(offsetSegment, params);
52          actualRowCount = null == rowCountSegment ? null : getValue(rowCountSegment, params);
53      }
54      
55      private long getValue(final PaginationValueSegment paginationValueSegment, final List<Object> params) {
56          if (paginationValueSegment instanceof ParameterMarkerPaginationValueSegment) {
57              Object obj = null == params || params.isEmpty() ? 0L : params.get(((ParameterMarkerPaginationValueSegment) paginationValueSegment).getParameterIndex());
58              return obj instanceof Long ? (long) obj : (int) obj;
59          }
60          if (paginationValueSegment instanceof ExpressionRowNumberValueSegment) {
61              return ((ExpressionRowNumberValueSegment) paginationValueSegment).getValue(params);
62          }
63          return ((NumberLiteralPaginationValueSegment) paginationValueSegment).getValue();
64      }
65      
66      /**
67       * Get offset segment.
68       * 
69       * @return offset segment
70       */
71      public Optional<PaginationValueSegment> getOffsetSegment() {
72          return Optional.ofNullable(offsetSegment);
73      }
74      
75      /**
76       * Get row count segment.
77       *
78       * @return row count segment
79       */
80      public Optional<PaginationValueSegment> getRowCountSegment() {
81          return Optional.ofNullable(rowCountSegment);
82      }
83      
84      /**
85       * Get actual offset.
86       * 
87       * @return actual offset
88       */
89      public long getActualOffset() {
90          if (null == offsetSegment) {
91              return 0L;
92          }
93          return offsetSegment.isBoundOpened() ? actualOffset - 1 : actualOffset;
94      }
95      
96      /**
97       * Get actual row count.
98       *
99       * @return actual row count
100      */
101     public Optional<Long> getActualRowCount() {
102         if (null == rowCountSegment) {
103             return Optional.empty();
104         }
105         return Optional.of(rowCountSegment.isBoundOpened() ? actualRowCount + 1L : actualRowCount);
106     }
107     
108     /**
109      * Get offset parameter index.
110      *
111      * @return offset parameter index
112      */
113     public Optional<Integer> getOffsetParameterIndex() {
114         // TODO handle offsetSegment instance of ExpressionRowNumberValueSegment
115         return offsetSegment instanceof ParameterMarkerPaginationValueSegment ? Optional.of(((ParameterMarkerPaginationValueSegment) offsetSegment).getParameterIndex()) : Optional.empty();
116     }
117     
118     /**
119      * Get row count parameter index.
120      *
121      * @return row count parameter index
122      */
123     public Optional<Integer> getRowCountParameterIndex() {
124         // TODO handle offsetSegment instance of ExpressionRowNumberValueSegment
125         return rowCountSegment instanceof ParameterMarkerPaginationValueSegment
126                 ? Optional.of(((ParameterMarkerPaginationValueSegment) rowCountSegment).getParameterIndex())
127                 : Optional.empty();
128     }
129     
130     /**
131      * Get revised offset.
132      *
133      * @return revised offset
134      */
135     public long getRevisedOffset() {
136         return 0L;
137     }
138     
139     /**
140      * Get revised row count.
141      * 
142      * @param selectStatementContext select statement context
143      * @return revised row count
144      */
145     public long getRevisedRowCount(final SelectStatementContext selectStatementContext) {
146         if (isMaxRowCount(selectStatementContext)) {
147             return Integer.MAX_VALUE;
148         }
149         return rowCountSegment instanceof LimitValueSegment ? actualOffset + actualRowCount : actualRowCount;
150     }
151     
152     private boolean isMaxRowCount(final SelectStatementContext selectStatementContext) {
153         return (!selectStatementContext.getGroupByContext().getItems().isEmpty()
154                 || !selectStatementContext.getProjectionsContext().getAggregationProjections().isEmpty()) && !selectStatementContext.isSameGroupByAndOrderByItems();
155     }
156 }