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

chengzhang 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 9b332d98386 Split BaseContext and BindingContext in 
SQLStatementContext (#36194)
9b332d98386 is described below

commit 9b332d9838687a93d0d84f609d06ffea622274e6
Author: Zhengqiang Duan <[email protected]>
AuthorDate: Wed Aug 6 13:38:26 2025 +0800

    Split BaseContext and BindingContext in SQLStatementContext (#36194)
---
 .../type/dml/InsertStatementBaseContext.java       | 187 ++++++++++
 .../type/dml/InsertStatementBindingContext.java    | 172 +++++++++
 .../statement/type/dml/InsertStatementContext.java | 264 ++++----------
 ...ontext.java => SelectStatementBaseContext.java} |  39 +-
 .../type/dml/SelectStatementBindingContext.java    |  57 +++
 .../statement/type/dml/SelectStatementContext.java | 397 +++++++--------------
 6 files changed, 607 insertions(+), 509 deletions(-)

diff --git 
a/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/statement/type/dml/InsertStatementBaseContext.java
 
b/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/statement/type/dml/InsertStatementBaseContext.java
new file mode 100644
index 00000000000..972476dc2c0
--- /dev/null
+++ 
b/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/statement/type/dml/InsertStatementBaseContext.java
@@ -0,0 +1,187 @@
+/*
+ * 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.infra.binder.context.statement.type.dml;
+
+import com.cedarsoftware.util.CaseInsensitiveMap;
+import lombok.Getter;
+import 
org.apache.shardingsphere.infra.binder.context.segment.table.TablesContext;
+import 
org.apache.shardingsphere.infra.binder.context.statement.SQLStatementContext;
+import org.apache.shardingsphere.infra.database.core.type.DatabaseTypeRegistry;
+import 
org.apache.shardingsphere.infra.exception.core.ShardingSpherePreconditions;
+import 
org.apache.shardingsphere.infra.exception.dialect.exception.syntax.database.NoDatabaseSelectedException;
+import 
org.apache.shardingsphere.infra.exception.dialect.exception.syntax.database.UnknownDatabaseException;
+import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
+import 
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
+import 
org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereSchema;
+import 
org.apache.shardingsphere.sql.parser.statement.core.extractor.TableExtractor;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.assignment.ColumnAssignmentSegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.assignment.InsertValuesSegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.assignment.SetAssignmentSegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.column.ColumnSegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.ExpressionSegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.SimpleTableSegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.statement.type.dml.InsertStatement;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+/**
+ * Insert SQL statement base context.
+ */
+@Getter
+public final class InsertStatementBaseContext implements SQLStatementContext {
+    
+    private final ShardingSphereMetaData metaData;
+    
+    private final ShardingSphereSchema schema;
+    
+    private final InsertStatement sqlStatement;
+    
+    private final TablesContext tablesContext;
+    
+    private final String currentDatabaseName;
+    
+    private final Map<String, Integer> insertColumnNamesAndIndexes;
+    
+    private final List<List<ExpressionSegment>> valueExpressions;
+    
+    private final List<String> columnNames;
+    
+    public InsertStatementBaseContext(final InsertStatement sqlStatement, 
final List<Object> params, final ShardingSphereMetaData metaData, final String 
currentDatabaseName) {
+        this.metaData = metaData;
+        this.sqlStatement = sqlStatement;
+        this.currentDatabaseName = currentDatabaseName;
+        valueExpressions = getAllValueExpressions(sqlStatement);
+        tablesContext = new TablesContext(getAllSimpleTableSegments());
+        List<String> insertColumnNames = getInsertColumnNames();
+        schema = getSchema(metaData, currentDatabaseName);
+        columnNames = containsInsertColumns()
+                ? insertColumnNames
+                : sqlStatement.getTable().map(optional -> 
schema.getVisibleColumnNames(optional.getTableName().getIdentifier().getValue())).orElseGet(Collections::emptyList);
+        insertColumnNamesAndIndexes = 
createInsertColumnNamesAndIndexes(insertColumnNames);
+    }
+    
+    private Map<String, Integer> createInsertColumnNamesAndIndexes(final 
List<String> insertColumnNames) {
+        if (containsInsertColumns()) {
+            Map<String, Integer> result = new 
CaseInsensitiveMap<>(insertColumnNames.size(), 1F);
+            int index = 0;
+            for (String each : insertColumnNames) {
+                result.put(each, index++);
+            }
+            return result;
+        }
+        return Collections.emptyMap();
+    }
+    
+    private ShardingSphereSchema getSchema(final ShardingSphereMetaData 
metaData, final String currentDatabaseName) {
+        String databaseName = 
tablesContext.getDatabaseName().orElse(currentDatabaseName);
+        ShardingSpherePreconditions.checkNotNull(databaseName, 
NoDatabaseSelectedException::new);
+        ShardingSphereDatabase database = metaData.getDatabase(databaseName);
+        ShardingSpherePreconditions.checkNotNull(database, () -> new 
UnknownDatabaseException(databaseName));
+        String defaultSchema = new 
DatabaseTypeRegistry(sqlStatement.getDatabaseType()).getDefaultSchemaName(databaseName);
+        return 
tablesContext.getSchemaName().map(database::getSchema).orElseGet(() -> 
database.getSchema(defaultSchema));
+    }
+    
+    private Collection<SimpleTableSegment> getAllSimpleTableSegments() {
+        TableExtractor tableExtractor = new TableExtractor();
+        tableExtractor.extractTablesFromInsert(sqlStatement);
+        return tableExtractor.getRewriteTables();
+    }
+    
+    /**
+     * Get column names for descending order.
+     *
+     * @return column names for descending order
+     */
+    public Iterator<String> getDescendingColumnNames() {
+        return new LinkedList<>(columnNames).descendingIterator();
+    }
+    
+    /**
+     * Judge whether contains insert columns.
+     *
+     * @return contains insert columns or not
+     */
+    public boolean containsInsertColumns() {
+        InsertStatement insertStatement = sqlStatement;
+        return !insertStatement.getColumns().isEmpty() || 
insertStatement.getSetAssignment().isPresent();
+    }
+    
+    /**
+     * Get value list count.
+     *
+     * @return value list count
+     */
+    public int getValueListCount() {
+        InsertStatement insertStatement = sqlStatement;
+        return insertStatement.getSetAssignment().isPresent() ? 1 : 
insertStatement.getValues().size();
+    }
+    
+    /**
+     * Get insert column names.
+     *
+     * @return column names collection
+     */
+    public List<String> getInsertColumnNames() {
+        return 
sqlStatement.getSetAssignment().map(this::getColumnNamesForSetAssignment).orElseGet(()
 -> getColumnNamesForInsertColumns(sqlStatement.getColumns()));
+    }
+    
+    private List<String> getColumnNamesForSetAssignment(final 
SetAssignmentSegment setAssignment) {
+        List<String> result = new LinkedList<>();
+        for (ColumnAssignmentSegment each : setAssignment.getAssignments()) {
+            
result.add(each.getColumns().get(0).getIdentifier().getValue().toLowerCase());
+        }
+        return result;
+    }
+    
+    private List<String> getColumnNamesForInsertColumns(final 
Collection<ColumnSegment> columns) {
+        List<String> result = new LinkedList<>();
+        for (ColumnSegment each : columns) {
+            result.add(each.getIdentifier().getValue().toLowerCase());
+        }
+        return result;
+    }
+    
+    private List<List<ExpressionSegment>> getAllValueExpressions(final 
InsertStatement insertStatement) {
+        Optional<SetAssignmentSegment> setAssignment = 
insertStatement.getSetAssignment();
+        return setAssignment
+                .map(optional -> 
Collections.singletonList(getAllValueExpressionsFromSetAssignment(optional))).orElseGet(()
 -> getAllValueExpressionsFromValues(insertStatement.getValues()));
+    }
+    
+    private List<ExpressionSegment> 
getAllValueExpressionsFromSetAssignment(final SetAssignmentSegment 
setAssignment) {
+        List<ExpressionSegment> result = new 
ArrayList<>(setAssignment.getAssignments().size());
+        for (ColumnAssignmentSegment each : setAssignment.getAssignments()) {
+            result.add(each.getValue());
+        }
+        return result;
+    }
+    
+    private List<List<ExpressionSegment>> 
getAllValueExpressionsFromValues(final Collection<InsertValuesSegment> values) {
+        List<List<ExpressionSegment>> result = new ArrayList<>(values.size());
+        for (InsertValuesSegment each : values) {
+            result.add(each.getValues());
+        }
+        return result;
+    }
+}
diff --git 
a/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/statement/type/dml/InsertStatementBindingContext.java
 
b/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/statement/type/dml/InsertStatementBindingContext.java
new file mode 100644
index 00000000000..0dddc337854
--- /dev/null
+++ 
b/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/statement/type/dml/InsertStatementBindingContext.java
@@ -0,0 +1,172 @@
+/*
+ * 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.infra.binder.context.statement.type.dml;
+
+import lombok.Getter;
+import 
org.apache.shardingsphere.infra.binder.context.segment.insert.keygen.GeneratedKeyContext;
+import 
org.apache.shardingsphere.infra.binder.context.segment.insert.keygen.engine.GeneratedKeyContextEngine;
+import 
org.apache.shardingsphere.infra.binder.context.segment.insert.values.InsertSelectContext;
+import 
org.apache.shardingsphere.infra.binder.context.segment.insert.values.InsertValueContext;
+import 
org.apache.shardingsphere.infra.binder.context.segment.insert.values.OnDuplicateUpdateContext;
+import 
org.apache.shardingsphere.infra.binder.context.segment.table.TablesContext;
+import 
org.apache.shardingsphere.infra.binder.context.statement.SQLStatementContext;
+import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
+import org.apache.shardingsphere.sql.parser.statement.core.enums.SubqueryType;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.assignment.ColumnAssignmentSegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.column.OnDuplicateKeyColumnsSegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.combine.CombineSegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.ExpressionSegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.subquery.SubquerySegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.statement.type.dml.InsertStatement;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.Optional;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Insert SQL statement binding context.
+ */
+public final class InsertStatementBindingContext implements 
SQLStatementContext {
+    
+    private final InsertStatementBaseContext baseContext;
+    
+    @Getter
+    private final List<InsertValueContext> insertValueContexts;
+    
+    @Getter
+    private final InsertSelectContext insertSelectContext;
+    
+    @Getter
+    private final OnDuplicateUpdateContext onDuplicateKeyUpdateValueContext;
+    
+    private final GeneratedKeyContext generatedKeyContext;
+    
+    public InsertStatementBindingContext(final InsertStatementBaseContext 
baseContext, final List<Object> params, final ShardingSphereMetaData metaData, 
final String currentDatabaseName) {
+        this.baseContext = baseContext;
+        AtomicInteger parametersOffset = new AtomicInteger(0);
+        insertValueContexts = getInsertValueContexts(params, parametersOffset, 
baseContext.getValueExpressions());
+        insertSelectContext = getInsertSelectContext(params, parametersOffset, 
metaData, currentDatabaseName).orElse(null);
+        onDuplicateKeyUpdateValueContext = 
getOnDuplicateKeyUpdateValueContext(params, parametersOffset).orElse(null);
+        generatedKeyContext = new 
GeneratedKeyContextEngine(baseContext.getSqlStatement(), 
baseContext.getSchema())
+                
.createGenerateKeyContext(baseContext.getInsertColumnNamesAndIndexes(), 
insertValueContexts, params).orElse(null);
+    }
+    
+    private List<InsertValueContext> getInsertValueContexts(final List<Object> 
params, final AtomicInteger paramsOffset, final List<List<ExpressionSegment>> 
valueExpressions) {
+        List<InsertValueContext> result = new LinkedList<>();
+        for (Collection<ExpressionSegment> each : valueExpressions) {
+            InsertValueContext insertValueContext = new 
InsertValueContext(each, params, paramsOffset.get());
+            result.add(insertValueContext);
+            paramsOffset.addAndGet(insertValueContext.getParameterCount());
+        }
+        return result;
+    }
+    
+    private Optional<InsertSelectContext> getInsertSelectContext(final 
List<Object> params, final AtomicInteger paramsOffset,
+                                                                 final 
ShardingSphereMetaData metaData, final String currentDatabaseName) {
+        if (!baseContext.getSqlStatement().getInsertSelect().isPresent()) {
+            return Optional.empty();
+        }
+        SubquerySegment insertSelectSegment = 
baseContext.getSqlStatement().getInsertSelect().get();
+        SelectStatementContext selectStatementContext = new 
SelectStatementContext(insertSelectSegment.getSelect(), params, metaData, 
currentDatabaseName, Collections.emptyList());
+        selectStatementContext.setSubqueryType(SubqueryType.INSERT_SELECT);
+        setCombineSelectSubqueryType(selectStatementContext);
+        setProjectionSelectSubqueryType(selectStatementContext);
+        InsertSelectContext insertSelectContext = new 
InsertSelectContext(selectStatementContext, params, paramsOffset.get());
+        
paramsOffset.addAndGet(insertSelectContext.getSelectStatementContext().getSqlStatement().getParameterCount());
+        return Optional.of(insertSelectContext);
+    }
+    
+    private void setCombineSelectSubqueryType(final SelectStatementContext 
selectStatementContext) {
+        if (selectStatementContext.getSqlStatement().getCombine().isPresent()) 
{
+            CombineSegment combineSegment = 
selectStatementContext.getSqlStatement().getCombine().get();
+            
Optional.ofNullable(selectStatementContext.getSubqueryContexts().get(combineSegment.getLeft().getStartIndex()))
+                    .ifPresent(optional -> 
optional.setSubqueryType(SubqueryType.INSERT_SELECT));
+            
Optional.ofNullable(selectStatementContext.getSubqueryContexts().get(combineSegment.getRight().getStartIndex()))
+                    .ifPresent(optional -> 
optional.setSubqueryType(SubqueryType.INSERT_SELECT));
+        }
+    }
+    
+    private void setProjectionSelectSubqueryType(final SelectStatementContext 
selectStatementContext) {
+        for (Entry<Integer, SelectStatementContext> entry : 
selectStatementContext.getSubqueryContexts().entrySet()) {
+            if (entry.getKey() >= 
selectStatementContext.getProjectionsContext().getStartIndex() && 
entry.getKey() <= 
selectStatementContext.getProjectionsContext().getStopIndex()) {
+                entry.getValue().setSubqueryType(SubqueryType.INSERT_SELECT);
+            }
+        }
+    }
+    
+    private Optional<OnDuplicateUpdateContext> 
getOnDuplicateKeyUpdateValueContext(final List<Object> params, final 
AtomicInteger parametersOffset) {
+        Optional<OnDuplicateKeyColumnsSegment> onDuplicateKeyColumnsSegment = 
baseContext.getSqlStatement().getOnDuplicateKeyColumns();
+        if (!onDuplicateKeyColumnsSegment.isPresent()) {
+            return Optional.empty();
+        }
+        Collection<ColumnAssignmentSegment> onDuplicateKeyColumns = 
onDuplicateKeyColumnsSegment.get().getColumns();
+        OnDuplicateUpdateContext onDuplicateUpdateContext = new 
OnDuplicateUpdateContext(onDuplicateKeyColumns, params, parametersOffset.get());
+        
parametersOffset.addAndGet(onDuplicateUpdateContext.getParameterCount());
+        return Optional.of(onDuplicateUpdateContext);
+    }
+    
+    /**
+     * Get grouped parameters.
+     *
+     * @return grouped parameters
+     */
+    public List<List<Object>> getGroupedParameters() {
+        List<List<Object>> result = new LinkedList<>();
+        for (InsertValueContext each : insertValueContexts) {
+            result.add(each.getParameters());
+        }
+        if (null != insertSelectContext && 
!insertSelectContext.getParameters().isEmpty()) {
+            result.add(insertSelectContext.getParameters());
+        }
+        return result;
+    }
+    
+    /**
+     * Get on duplicate key update parameters.
+     *
+     * @return on duplicate key update parameters
+     */
+    @SuppressWarnings("CollectionWithoutInitialCapacity")
+    public List<Object> getOnDuplicateKeyUpdateParameters() {
+        return null == onDuplicateKeyUpdateValueContext ? new ArrayList<>() : 
onDuplicateKeyUpdateValueContext.getParameters();
+    }
+    
+    /**
+     * Get generated key context.
+     *
+     * @return generated key context
+     */
+    public Optional<GeneratedKeyContext> getGeneratedKeyContext() {
+        return Optional.ofNullable(generatedKeyContext);
+    }
+    
+    @Override
+    public InsertStatement getSqlStatement() {
+        return baseContext.getSqlStatement();
+    }
+    
+    @Override
+    public TablesContext getTablesContext() {
+        return baseContext.getTablesContext();
+    }
+}
diff --git 
a/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/statement/type/dml/InsertStatementContext.java
 
b/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/statement/type/dml/InsertStatementContext.java
index b3b62a25c9a..148aed81f9c 100644
--- 
a/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/statement/type/dml/InsertStatementContext.java
+++ 
b/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/statement/type/dml/InsertStatementContext.java
@@ -17,181 +17,50 @@
 
 package org.apache.shardingsphere.infra.binder.context.statement.type.dml;
 
-import com.cedarsoftware.util.CaseInsensitiveMap;
 import lombok.Getter;
 import 
org.apache.shardingsphere.infra.binder.context.available.WhereContextAvailable;
 import org.apache.shardingsphere.infra.binder.context.aware.ParameterAware;
 import 
org.apache.shardingsphere.infra.binder.context.segment.insert.keygen.GeneratedKeyContext;
-import 
org.apache.shardingsphere.infra.binder.context.segment.insert.keygen.engine.GeneratedKeyContextEngine;
 import 
org.apache.shardingsphere.infra.binder.context.segment.insert.values.InsertSelectContext;
 import 
org.apache.shardingsphere.infra.binder.context.segment.insert.values.InsertValueContext;
 import 
org.apache.shardingsphere.infra.binder.context.segment.insert.values.OnDuplicateUpdateContext;
 import 
org.apache.shardingsphere.infra.binder.context.segment.table.TablesContext;
 import 
org.apache.shardingsphere.infra.binder.context.statement.SQLStatementContext;
-import org.apache.shardingsphere.infra.database.core.type.DatabaseTypeRegistry;
-import 
org.apache.shardingsphere.infra.exception.core.ShardingSpherePreconditions;
-import 
org.apache.shardingsphere.infra.exception.dialect.exception.syntax.database.NoDatabaseSelectedException;
-import 
org.apache.shardingsphere.infra.exception.dialect.exception.syntax.database.UnknownDatabaseException;
 import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
-import 
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
-import 
org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereSchema;
-import org.apache.shardingsphere.sql.parser.statement.core.enums.SubqueryType;
-import 
org.apache.shardingsphere.sql.parser.statement.core.extractor.TableExtractor;
-import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.assignment.ColumnAssignmentSegment;
-import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.assignment.InsertValuesSegment;
-import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.assignment.SetAssignmentSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.column.ColumnSegment;
-import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.column.OnDuplicateKeyColumnsSegment;
-import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.combine.CombineSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.BinaryOperationExpression;
-import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.ExpressionSegment;
-import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.subquery.SubquerySegment;
 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.statement.type.dml.InsertStatement;
 
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Iterator;
-import java.util.LinkedList;
 import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
 import java.util.Optional;
-import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * Insert SQL statement context.
  */
 public final class InsertStatementContext implements SQLStatementContext, 
ParameterAware, WhereContextAvailable {
     
-    private final ShardingSphereMetaData metaData;
-    
-    @Getter
-    private final InsertStatement sqlStatement;
-    
-    @Getter
-    private final TablesContext tablesContext;
-    
-    private final String currentDatabaseName;
-    
-    private final Map<String, Integer> insertColumnNamesAndIndexes;
-    
-    private final List<List<ExpressionSegment>> valueExpressions;
-    
-    @Getter
-    private final List<String> columnNames;
-    
-    @Getter
-    private List<InsertValueContext> insertValueContexts;
-    
-    @Getter
-    private InsertSelectContext insertSelectContext;
-    
     @Getter
-    private OnDuplicateUpdateContext onDuplicateKeyUpdateValueContext;
+    private final InsertStatementBaseContext baseContext;
     
-    private GeneratedKeyContext generatedKeyContext;
+    private InsertStatementBindingContext bindingContext;
     
     public InsertStatementContext(final InsertStatement sqlStatement, final 
List<Object> params, final ShardingSphereMetaData metaData, final String 
currentDatabaseName) {
-        this.metaData = metaData;
-        this.sqlStatement = sqlStatement;
-        this.currentDatabaseName = currentDatabaseName;
-        valueExpressions = getAllValueExpressions(sqlStatement);
-        AtomicInteger parametersOffset = new AtomicInteger(0);
-        insertValueContexts = getInsertValueContexts(params, parametersOffset, 
valueExpressions);
-        insertSelectContext = getInsertSelectContext(params, parametersOffset, 
metaData, currentDatabaseName).orElse(null);
-        onDuplicateKeyUpdateValueContext = 
getOnDuplicateKeyUpdateValueContext(params, parametersOffset).orElse(null);
-        tablesContext = new TablesContext(getAllSimpleTableSegments());
-        List<String> insertColumnNames = getInsertColumnNames();
-        ShardingSphereSchema schema = getSchema(metaData, currentDatabaseName);
-        columnNames = containsInsertColumns()
-                ? insertColumnNames
-                : sqlStatement.getTable().map(optional -> 
schema.getVisibleColumnNames(optional.getTableName().getIdentifier().getValue())).orElseGet(Collections::emptyList);
-        insertColumnNamesAndIndexes = 
createInsertColumnNamesAndIndexes(insertColumnNames);
-        generatedKeyContext = new GeneratedKeyContextEngine(sqlStatement, 
schema).createGenerateKeyContext(insertColumnNamesAndIndexes, 
insertValueContexts, params).orElse(null);
+        baseContext = new InsertStatementBaseContext(sqlStatement, params, 
metaData, currentDatabaseName);
+        bindingContext = new InsertStatementBindingContext(baseContext, 
params, metaData, currentDatabaseName);
     }
     
-    private Map<String, Integer> createInsertColumnNamesAndIndexes(final 
List<String> insertColumnNames) {
-        if (containsInsertColumns()) {
-            Map<String, Integer> result = new 
CaseInsensitiveMap<>(insertColumnNames.size(), 1F);
-            int index = 0;
-            for (String each : insertColumnNames) {
-                result.put(each, index++);
-            }
-            return result;
-        }
-        return Collections.emptyMap();
+    public InsertStatementContext(final InsertStatementBaseContext 
baseContext, final ShardingSphereMetaData metaData, final List<Object> params, 
final String currentDatabaseName) {
+        this.baseContext = baseContext;
+        bindingContext = new InsertStatementBindingContext(baseContext, 
params, metaData, currentDatabaseName);
     }
     
-    private List<InsertValueContext> getInsertValueContexts(final List<Object> 
params, final AtomicInteger paramsOffset, final List<List<ExpressionSegment>> 
valueExpressions) {
-        List<InsertValueContext> result = new LinkedList<>();
-        for (Collection<ExpressionSegment> each : valueExpressions) {
-            InsertValueContext insertValueContext = new 
InsertValueContext(each, params, paramsOffset.get());
-            result.add(insertValueContext);
-            paramsOffset.addAndGet(insertValueContext.getParameterCount());
-        }
-        return result;
-    }
-    
-    private Optional<InsertSelectContext> getInsertSelectContext(final 
List<Object> params, final AtomicInteger paramsOffset,
-                                                                 final 
ShardingSphereMetaData metaData, final String currentDatabaseName) {
-        if (!sqlStatement.getInsertSelect().isPresent()) {
-            return Optional.empty();
-        }
-        SubquerySegment insertSelectSegment = 
sqlStatement.getInsertSelect().get();
-        SelectStatementContext selectStatementContext = new 
SelectStatementContext(insertSelectSegment.getSelect(), params, metaData, 
currentDatabaseName, Collections.emptyList());
-        selectStatementContext.setSubqueryType(SubqueryType.INSERT_SELECT);
-        setCombineSelectSubqueryType(selectStatementContext);
-        setProjectionSelectSubqueryType(selectStatementContext);
-        InsertSelectContext insertSelectContext = new 
InsertSelectContext(selectStatementContext, params, paramsOffset.get());
-        
paramsOffset.addAndGet(insertSelectContext.getSelectStatementContext().getSqlStatement().getParameterCount());
-        return Optional.of(insertSelectContext);
-    }
-    
-    private void setCombineSelectSubqueryType(final SelectStatementContext 
selectStatementContext) {
-        if (selectStatementContext.getSqlStatement().getCombine().isPresent()) 
{
-            CombineSegment combineSegment = 
selectStatementContext.getSqlStatement().getCombine().get();
-            
Optional.ofNullable(selectStatementContext.getSubqueryContexts().get(combineSegment.getLeft().getStartIndex()))
-                    .ifPresent(optional -> 
optional.setSubqueryType(SubqueryType.INSERT_SELECT));
-            
Optional.ofNullable(selectStatementContext.getSubqueryContexts().get(combineSegment.getRight().getStartIndex()))
-                    .ifPresent(optional -> 
optional.setSubqueryType(SubqueryType.INSERT_SELECT));
-        }
-    }
-    
-    private void setProjectionSelectSubqueryType(final SelectStatementContext 
selectStatementContext) {
-        for (Entry<Integer, SelectStatementContext> entry : 
selectStatementContext.getSubqueryContexts().entrySet()) {
-            if (entry.getKey() >= 
selectStatementContext.getProjectionsContext().getStartIndex() && 
entry.getKey() <= 
selectStatementContext.getProjectionsContext().getStopIndex()) {
-                entry.getValue().setSubqueryType(SubqueryType.INSERT_SELECT);
-            }
-        }
-    }
-    
-    private Optional<OnDuplicateUpdateContext> 
getOnDuplicateKeyUpdateValueContext(final List<Object> params, final 
AtomicInteger parametersOffset) {
-        Optional<OnDuplicateKeyColumnsSegment> onDuplicateKeyColumnsSegment = 
sqlStatement.getOnDuplicateKeyColumns();
-        if (!onDuplicateKeyColumnsSegment.isPresent()) {
-            return Optional.empty();
-        }
-        Collection<ColumnAssignmentSegment> onDuplicateKeyColumns = 
onDuplicateKeyColumnsSegment.get().getColumns();
-        OnDuplicateUpdateContext onDuplicateUpdateContext = new 
OnDuplicateUpdateContext(onDuplicateKeyColumns, params, parametersOffset.get());
-        
parametersOffset.addAndGet(onDuplicateUpdateContext.getParameterCount());
-        return Optional.of(onDuplicateUpdateContext);
-    }
-    
-    private Collection<SimpleTableSegment> getAllSimpleTableSegments() {
-        TableExtractor tableExtractor = new TableExtractor();
-        tableExtractor.extractTablesFromInsert(sqlStatement);
-        return tableExtractor.getRewriteTables();
-    }
-    
-    private ShardingSphereSchema getSchema(final ShardingSphereMetaData 
metaData, final String currentDatabaseName) {
-        String databaseName = 
tablesContext.getDatabaseName().orElse(currentDatabaseName);
-        ShardingSpherePreconditions.checkNotNull(databaseName, 
NoDatabaseSelectedException::new);
-        ShardingSphereDatabase database = metaData.getDatabase(databaseName);
-        ShardingSpherePreconditions.checkNotNull(database, () -> new 
UnknownDatabaseException(databaseName));
-        String defaultSchema = new 
DatabaseTypeRegistry(sqlStatement.getDatabaseType()).getDefaultSchemaName(databaseName);
-        return 
tablesContext.getSchemaName().map(database::getSchema).orElseGet(() -> 
database.getSchema(defaultSchema));
+    public InsertStatementContext(final InsertStatementBaseContext 
baseContext, final InsertStatementBindingContext bindingContext) {
+        this.baseContext = baseContext;
+        this.bindingContext = bindingContext;
     }
     
     /**
@@ -200,7 +69,7 @@ public final class InsertStatementContext implements 
SQLStatementContext, Parame
      * @return column names for descending order
      */
     public Iterator<String> getDescendingColumnNames() {
-        return new LinkedList<>(columnNames).descendingIterator();
+        return baseContext.getDescendingColumnNames();
     }
     
     /**
@@ -209,14 +78,7 @@ public final class InsertStatementContext implements 
SQLStatementContext, Parame
      * @return grouped parameters
      */
     public List<List<Object>> getGroupedParameters() {
-        List<List<Object>> result = new LinkedList<>();
-        for (InsertValueContext each : insertValueContexts) {
-            result.add(each.getParameters());
-        }
-        if (null != insertSelectContext && 
!insertSelectContext.getParameters().isEmpty()) {
-            result.add(insertSelectContext.getParameters());
-        }
-        return result;
+        return bindingContext.getGroupedParameters();
     }
     
     /**
@@ -224,9 +86,8 @@ public final class InsertStatementContext implements 
SQLStatementContext, Parame
      *
      * @return on duplicate key update parameters
      */
-    @SuppressWarnings("CollectionWithoutInitialCapacity")
     public List<Object> getOnDuplicateKeyUpdateParameters() {
-        return null == onDuplicateKeyUpdateValueContext ? new ArrayList<>() : 
onDuplicateKeyUpdateValueContext.getParameters();
+        return bindingContext.getOnDuplicateKeyUpdateParameters();
     }
     
     /**
@@ -235,7 +96,7 @@ public final class InsertStatementContext implements 
SQLStatementContext, Parame
      * @return generated key context
      */
     public Optional<GeneratedKeyContext> getGeneratedKeyContext() {
-        return Optional.ofNullable(generatedKeyContext);
+        return bindingContext.getGeneratedKeyContext();
     }
     
     /**
@@ -244,8 +105,7 @@ public final class InsertStatementContext implements 
SQLStatementContext, Parame
      * @return contains insert columns or not
      */
     public boolean containsInsertColumns() {
-        InsertStatement insertStatement = sqlStatement;
-        return !insertStatement.getColumns().isEmpty() || 
insertStatement.getSetAssignment().isPresent();
+        return baseContext.containsInsertColumns();
     }
     
     /**
@@ -254,8 +114,7 @@ public final class InsertStatementContext implements 
SQLStatementContext, Parame
      * @return value list count
      */
     public int getValueListCount() {
-        InsertStatement insertStatement = sqlStatement;
-        return insertStatement.getSetAssignment().isPresent() ? 1 : 
insertStatement.getValues().size();
+        return baseContext.getValueListCount();
     }
     
     /**
@@ -264,69 +123,72 @@ public final class InsertStatementContext implements 
SQLStatementContext, Parame
      * @return column names collection
      */
     public List<String> getInsertColumnNames() {
-        return 
sqlStatement.getSetAssignment().map(this::getColumnNamesForSetAssignment).orElseGet(()
 -> getColumnNamesForInsertColumns(sqlStatement.getColumns()));
-    }
-    
-    private List<String> getColumnNamesForSetAssignment(final 
SetAssignmentSegment setAssignment) {
-        List<String> result = new LinkedList<>();
-        for (ColumnAssignmentSegment each : setAssignment.getAssignments()) {
-            
result.add(each.getColumns().get(0).getIdentifier().getValue().toLowerCase());
-        }
-        return result;
-    }
-    
-    private List<String> getColumnNamesForInsertColumns(final 
Collection<ColumnSegment> columns) {
-        List<String> result = new LinkedList<>();
-        for (ColumnSegment each : columns) {
-            result.add(each.getIdentifier().getValue().toLowerCase());
-        }
-        return result;
+        return baseContext.getInsertColumnNames();
     }
     
-    private List<List<ExpressionSegment>> getAllValueExpressions(final 
InsertStatement insertStatement) {
-        Optional<SetAssignmentSegment> setAssignment = 
insertStatement.getSetAssignment();
-        return setAssignment
-                .map(optional -> 
Collections.singletonList(getAllValueExpressionsFromSetAssignment(optional))).orElseGet(()
 -> getAllValueExpressionsFromValues(insertStatement.getValues()));
-    }
-    
-    private List<ExpressionSegment> 
getAllValueExpressionsFromSetAssignment(final SetAssignmentSegment 
setAssignment) {
-        List<ExpressionSegment> result = new 
ArrayList<>(setAssignment.getAssignments().size());
-        for (ColumnAssignmentSegment each : setAssignment.getAssignments()) {
-            result.add(each.getValue());
-        }
-        return result;
+    @Override
+    public InsertStatement getSqlStatement() {
+        return baseContext.getSqlStatement();
     }
     
-    private List<List<ExpressionSegment>> 
getAllValueExpressionsFromValues(final Collection<InsertValuesSegment> values) {
-        List<List<ExpressionSegment>> result = new ArrayList<>(values.size());
-        for (InsertValuesSegment each : values) {
-            result.add(each.getValues());
-        }
-        return result;
+    @Override
+    public TablesContext getTablesContext() {
+        return baseContext.getTablesContext();
     }
     
     @Override
     public void setUpParameters(final List<Object> params) {
-        AtomicInteger parametersOffset = new AtomicInteger(0);
-        insertValueContexts = getInsertValueContexts(params, parametersOffset, 
valueExpressions);
-        insertSelectContext = getInsertSelectContext(params, parametersOffset, 
metaData, currentDatabaseName).orElse(null);
-        onDuplicateKeyUpdateValueContext = 
getOnDuplicateKeyUpdateValueContext(params, parametersOffset).orElse(null);
-        ShardingSphereSchema schema = getSchema(metaData, currentDatabaseName);
-        generatedKeyContext = new GeneratedKeyContextEngine(sqlStatement, 
schema).createGenerateKeyContext(insertColumnNamesAndIndexes, 
insertValueContexts, params).orElse(null);
+        bindingContext = new InsertStatementBindingContext(baseContext, 
params, baseContext.getMetaData(), baseContext.getCurrentDatabaseName());
     }
     
     @Override
     public Collection<WhereSegment> getWhereSegments() {
-        return null == insertSelectContext ? Collections.emptyList() : 
insertSelectContext.getSelectStatementContext().getWhereSegments();
+        return null == bindingContext.getInsertSelectContext() ? 
Collections.emptyList() : 
bindingContext.getInsertSelectContext().getSelectStatementContext().getWhereSegments();
     }
     
     @Override
     public Collection<ColumnSegment> getColumnSegments() {
-        return null == insertSelectContext ? Collections.emptyList() : 
insertSelectContext.getSelectStatementContext().getColumnSegments();
+        return null == bindingContext.getInsertSelectContext() ? 
Collections.emptyList() : 
bindingContext.getInsertSelectContext().getSelectStatementContext().getColumnSegments();
     }
     
     @Override
     public Collection<BinaryOperationExpression> getJoinConditions() {
-        return null == insertSelectContext ? Collections.emptyList() : 
insertSelectContext.getSelectStatementContext().getJoinConditions();
+        return null == bindingContext.getInsertSelectContext() ? 
Collections.emptyList() : 
bindingContext.getInsertSelectContext().getSelectStatementContext().getJoinConditions();
+    }
+    
+    /**
+     * Get insert select context.
+     *
+     * @return insert select context
+     */
+    public InsertSelectContext getInsertSelectContext() {
+        return bindingContext.getInsertSelectContext();
+    }
+    
+    /**
+     * Get insert value contexts.
+     *
+     * @return insert value contexts
+     */
+    public List<InsertValueContext> getInsertValueContexts() {
+        return bindingContext.getInsertValueContexts();
+    }
+    
+    /**
+     * Get column names.
+     *
+     * @return column names
+     */
+    public List<String> getColumnNames() {
+        return baseContext.getColumnNames();
+    }
+    
+    /**
+     * Get on duplicate key update value context.
+     *
+     * @return on duplicate key update value context
+     */
+    public OnDuplicateUpdateContext getOnDuplicateKeyUpdateValueContext() {
+        return bindingContext.getOnDuplicateKeyUpdateValueContext();
     }
 }
diff --git 
a/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/statement/type/dml/SelectStatementContext.java
 
b/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/statement/type/dml/SelectStatementBaseContext.java
similarity index 90%
copy from 
infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/statement/type/dml/SelectStatementContext.java
copy to 
infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/statement/type/dml/SelectStatementBaseContext.java
index 7a0e4a2cba9..350c6349fa1 100644
--- 
a/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/statement/type/dml/SelectStatementContext.java
+++ 
b/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/statement/type/dml/SelectStatementBaseContext.java
@@ -20,15 +20,11 @@ package 
org.apache.shardingsphere.infra.binder.context.statement.type.dml;
 import com.google.common.base.Preconditions;
 import lombok.Getter;
 import lombok.Setter;
-import 
org.apache.shardingsphere.infra.binder.context.available.WhereContextAvailable;
-import org.apache.shardingsphere.infra.binder.context.aware.ParameterAware;
 import 
org.apache.shardingsphere.infra.binder.context.segment.select.groupby.GroupByContext;
 import 
org.apache.shardingsphere.infra.binder.context.segment.select.groupby.engine.GroupByContextEngine;
 import 
org.apache.shardingsphere.infra.binder.context.segment.select.orderby.OrderByContext;
 import 
org.apache.shardingsphere.infra.binder.context.segment.select.orderby.OrderByItem;
 import 
org.apache.shardingsphere.infra.binder.context.segment.select.orderby.engine.OrderByContextEngine;
-import 
org.apache.shardingsphere.infra.binder.context.segment.select.pagination.PaginationContext;
-import 
org.apache.shardingsphere.infra.binder.context.segment.select.pagination.engine.PaginationContextEngine;
 import 
org.apache.shardingsphere.infra.binder.context.segment.select.projection.Projection;
 import 
org.apache.shardingsphere.infra.binder.context.segment.select.projection.ProjectionsContext;
 import 
org.apache.shardingsphere.infra.binder.context.segment.select.projection.engine.ProjectionsContextEngine;
@@ -39,8 +35,6 @@ import 
org.apache.shardingsphere.infra.binder.context.segment.select.projection.
 import 
org.apache.shardingsphere.infra.binder.context.segment.select.projection.impl.SubqueryProjection;
 import 
org.apache.shardingsphere.infra.binder.context.segment.table.TablesContext;
 import 
org.apache.shardingsphere.infra.binder.context.statement.SQLStatementContext;
-import 
org.apache.shardingsphere.infra.database.core.metadata.database.metadata.option.pagination.DialectPaginationOption;
-import org.apache.shardingsphere.infra.database.core.type.DatabaseTypeRegistry;
 import 
org.apache.shardingsphere.infra.exception.core.ShardingSpherePreconditions;
 import 
org.apache.shardingsphere.infra.exception.dialect.exception.syntax.database.NoDatabaseSelectedException;
 import 
org.apache.shardingsphere.infra.exception.dialect.exception.syntax.database.UnknownDatabaseException;
@@ -83,11 +77,11 @@ import java.util.Map;
 import java.util.Optional;
 
 /**
- * Select SQL statement context.
+ * Select SQL statement base context.
  */
 @Getter
 @Setter
-public final class SelectStatementContext implements SQLStatementContext, 
WhereContextAvailable, ParameterAware {
+public final class SelectStatementBaseContext implements SQLStatementContext {
     
     private final SelectStatement sqlStatement;
     
@@ -113,10 +107,8 @@ public final class SelectStatementContext implements 
SQLStatementContext, WhereC
     
     private boolean needAggregateRewrite;
     
-    private PaginationContext paginationContext;
-    
-    public SelectStatementContext(final SelectStatement sqlStatement,
-                                  final List<Object> params, final 
ShardingSphereMetaData metaData, final String currentDatabaseName, final 
Collection<TableSegment> inheritedTables) {
+    public SelectStatementBaseContext(final SelectStatement sqlStatement,
+                                      final List<Object> params, final 
ShardingSphereMetaData metaData, final String currentDatabaseName, final 
Collection<TableSegment> inheritedTables) {
         this.sqlStatement = sqlStatement;
         whereSegments = createWhereSegments(sqlStatement);
         columnSegments = ColumnExtractor.extractColumnSegments(whereSegments);
@@ -127,8 +119,6 @@ public final class SelectStatementContext implements 
SQLStatementContext, WhereC
         groupByContext = new 
GroupByContextEngine().createGroupByContext(sqlStatement);
         orderByContext = new 
OrderByContextEngine(sqlStatement.getDatabaseType()).createOrderBy(sqlStatement,
 groupByContext);
         projectionsContext = new 
ProjectionsContextEngine(sqlStatement.getDatabaseType()).createProjectionsContext(sqlStatement.getProjections(),
 groupByContext, orderByContext);
-        DialectPaginationOption paginationOption = new 
DatabaseTypeRegistry(sqlStatement.getDatabaseType()).getDialectDatabaseMetaData().getPaginationOption();
-        paginationContext = new 
PaginationContextEngine(paginationOption).createPaginationContext(sqlStatement, 
projectionsContext, params, whereSegments);
         containsEnhancedTable = isContainsEnhancedTable(metaData, 
tablesContext.getDatabaseNames(), currentDatabaseName);
     }
     
@@ -410,25 +400,4 @@ public final class SelectStatementContext implements 
SQLStatementContext, WhereC
     public boolean containsDerivedProjections() {
         return containsEnhancedTable && 
!projectionsContext.getExpandProjections().isEmpty();
     }
-    
-    @Override
-    public Collection<WhereSegment> getWhereSegments() {
-        return whereSegments;
-    }
-    
-    @Override
-    public Collection<ColumnSegment> getColumnSegments() {
-        return columnSegments;
-    }
-    
-    @Override
-    public Collection<BinaryOperationExpression> getJoinConditions() {
-        return joinConditions;
-    }
-    
-    @Override
-    public void setUpParameters(final List<Object> params) {
-        DialectPaginationOption paginationOption = new 
DatabaseTypeRegistry(sqlStatement.getDatabaseType()).getDialectDatabaseMetaData().getPaginationOption();
-        paginationContext = new 
PaginationContextEngine(paginationOption).createPaginationContext(sqlStatement, 
projectionsContext, params, whereSegments);
-    }
 }
diff --git 
a/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/statement/type/dml/SelectStatementBindingContext.java
 
b/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/statement/type/dml/SelectStatementBindingContext.java
new file mode 100644
index 00000000000..136f5b6a652
--- /dev/null
+++ 
b/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/statement/type/dml/SelectStatementBindingContext.java
@@ -0,0 +1,57 @@
+/*
+ * 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.infra.binder.context.statement.type.dml;
+
+import lombok.Getter;
+import 
org.apache.shardingsphere.infra.binder.context.segment.select.pagination.PaginationContext;
+import 
org.apache.shardingsphere.infra.binder.context.segment.select.pagination.engine.PaginationContextEngine;
+import 
org.apache.shardingsphere.infra.binder.context.segment.table.TablesContext;
+import 
org.apache.shardingsphere.infra.binder.context.statement.SQLStatementContext;
+import 
org.apache.shardingsphere.infra.database.core.metadata.database.metadata.option.pagination.DialectPaginationOption;
+import org.apache.shardingsphere.infra.database.core.type.DatabaseTypeRegistry;
+import 
org.apache.shardingsphere.sql.parser.statement.core.statement.type.dml.SelectStatement;
+
+import java.util.List;
+
+/**
+ * Select SQL statement binding context.
+ */
+public final class SelectStatementBindingContext implements 
SQLStatementContext {
+    
+    private final SelectStatementBaseContext baseContext;
+    
+    @Getter
+    private final PaginationContext paginationContext;
+    
+    public SelectStatementBindingContext(final List<Object> params, final 
SelectStatementBaseContext baseContext) {
+        this.baseContext = baseContext;
+        DialectPaginationOption paginationOption = new 
DatabaseTypeRegistry(baseContext.getSqlStatement().getDatabaseType()).getDialectDatabaseMetaData().getPaginationOption();
+        paginationContext =
+                new 
PaginationContextEngine(paginationOption).createPaginationContext(baseContext.getSqlStatement(),
 baseContext.getProjectionsContext(), params, baseContext.getWhereSegments());
+    }
+    
+    @Override
+    public SelectStatement getSqlStatement() {
+        return baseContext.getSqlStatement();
+    }
+    
+    @Override
+    public TablesContext getTablesContext() {
+        return baseContext.getTablesContext();
+    }
+}
diff --git 
a/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/statement/type/dml/SelectStatementContext.java
 
b/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/statement/type/dml/SelectStatementContext.java
index 7a0e4a2cba9..2a9259f3193 100644
--- 
a/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/statement/type/dml/SelectStatementContext.java
+++ 
b/infra/binder/core/src/main/java/org/apache/shardingsphere/infra/binder/context/statement/type/dml/SelectStatementContext.java
@@ -17,67 +17,26 @@
 
 package org.apache.shardingsphere.infra.binder.context.statement.type.dml;
 
-import com.google.common.base.Preconditions;
 import lombok.Getter;
 import lombok.Setter;
 import 
org.apache.shardingsphere.infra.binder.context.available.WhereContextAvailable;
 import org.apache.shardingsphere.infra.binder.context.aware.ParameterAware;
 import 
org.apache.shardingsphere.infra.binder.context.segment.select.groupby.GroupByContext;
-import 
org.apache.shardingsphere.infra.binder.context.segment.select.groupby.engine.GroupByContextEngine;
 import 
org.apache.shardingsphere.infra.binder.context.segment.select.orderby.OrderByContext;
-import 
org.apache.shardingsphere.infra.binder.context.segment.select.orderby.OrderByItem;
-import 
org.apache.shardingsphere.infra.binder.context.segment.select.orderby.engine.OrderByContextEngine;
 import 
org.apache.shardingsphere.infra.binder.context.segment.select.pagination.PaginationContext;
-import 
org.apache.shardingsphere.infra.binder.context.segment.select.pagination.engine.PaginationContextEngine;
-import 
org.apache.shardingsphere.infra.binder.context.segment.select.projection.Projection;
 import 
org.apache.shardingsphere.infra.binder.context.segment.select.projection.ProjectionsContext;
-import 
org.apache.shardingsphere.infra.binder.context.segment.select.projection.engine.ProjectionsContextEngine;
-import 
org.apache.shardingsphere.infra.binder.context.segment.select.projection.impl.AggregationDistinctProjection;
-import 
org.apache.shardingsphere.infra.binder.context.segment.select.projection.impl.AggregationProjection;
-import 
org.apache.shardingsphere.infra.binder.context.segment.select.projection.impl.ColumnProjection;
-import 
org.apache.shardingsphere.infra.binder.context.segment.select.projection.impl.ParameterMarkerProjection;
-import 
org.apache.shardingsphere.infra.binder.context.segment.select.projection.impl.SubqueryProjection;
 import 
org.apache.shardingsphere.infra.binder.context.segment.table.TablesContext;
 import 
org.apache.shardingsphere.infra.binder.context.statement.SQLStatementContext;
-import 
org.apache.shardingsphere.infra.database.core.metadata.database.metadata.option.pagination.DialectPaginationOption;
-import org.apache.shardingsphere.infra.database.core.type.DatabaseTypeRegistry;
-import 
org.apache.shardingsphere.infra.exception.core.ShardingSpherePreconditions;
-import 
org.apache.shardingsphere.infra.exception.dialect.exception.syntax.database.NoDatabaseSelectedException;
-import 
org.apache.shardingsphere.infra.exception.dialect.exception.syntax.database.UnknownDatabaseException;
 import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
-import 
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
-import 
org.apache.shardingsphere.infra.rule.attribute.table.TableMapperRuleAttribute;
-import 
org.apache.shardingsphere.sql.parser.statement.core.enums.ParameterMarkerType;
 import org.apache.shardingsphere.sql.parser.statement.core.enums.SubqueryType;
-import 
org.apache.shardingsphere.sql.parser.statement.core.extractor.ColumnExtractor;
-import 
org.apache.shardingsphere.sql.parser.statement.core.extractor.ExpressionExtractor;
-import 
org.apache.shardingsphere.sql.parser.statement.core.extractor.SubqueryExtractor;
-import 
org.apache.shardingsphere.sql.parser.statement.core.extractor.TableExtractor;
-import 
org.apache.shardingsphere.sql.parser.statement.core.extractor.WhereExtractor;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.column.ColumnSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.BinaryOperationExpression;
-import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.ExpressionSegment;
-import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.simple.ParameterMarkerExpressionSegment;
-import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.subquery.SubquerySegment;
-import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.order.item.ColumnOrderByItemSegment;
-import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.order.item.ExpressionOrderByItemSegment;
-import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.order.item.IndexOrderByItemSegment;
-import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.order.item.OrderByItemSegment;
-import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.order.item.TextOrderByItemSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.predicate.WhereSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.bound.ColumnSegmentBoundInfo;
-import 
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.JoinTableSegment;
-import 
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.SimpleTableSegment;
-import 
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.SubqueryTableSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.TableSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.statement.type.dml.SelectStatement;
-import org.apache.shardingsphere.sql.parser.statement.core.util.SQLUtils;
-import 
org.apache.shardingsphere.sql.parser.statement.core.value.identifier.IdentifierValue;
 
 import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
@@ -89,118 +48,19 @@ import java.util.Optional;
 @Setter
 public final class SelectStatementContext implements SQLStatementContext, 
WhereContextAvailable, ParameterAware {
     
-    private final SelectStatement sqlStatement;
+    private final SelectStatementBaseContext baseContext;
     
-    private final TablesContext tablesContext;
+    private SelectStatementBindingContext bindingContext;
     
-    private final ProjectionsContext projectionsContext;
-    
-    private final GroupByContext groupByContext;
-    
-    private final OrderByContext orderByContext;
-    
-    private final Map<Integer, SelectStatementContext> subqueryContexts;
-    
-    private final Collection<WhereSegment> whereSegments;
-    
-    private final Collection<ColumnSegment> columnSegments;
-    
-    private final Collection<BinaryOperationExpression> joinConditions = new 
LinkedList<>();
-    
-    private final boolean containsEnhancedTable;
-    
-    private SubqueryType subqueryType;
-    
-    private boolean needAggregateRewrite;
-    
-    private PaginationContext paginationContext;
-    
-    public SelectStatementContext(final SelectStatement sqlStatement,
-                                  final List<Object> params, final 
ShardingSphereMetaData metaData, final String currentDatabaseName, final 
Collection<TableSegment> inheritedTables) {
-        this.sqlStatement = sqlStatement;
-        whereSegments = createWhereSegments(sqlStatement);
-        columnSegments = ColumnExtractor.extractColumnSegments(whereSegments);
-        Collection<TableSegment> tableSegments = 
getAllTableSegments(inheritedTables);
-        ExpressionExtractor.extractJoinConditions(joinConditions, 
whereSegments);
-        subqueryContexts = createSubqueryContexts(params, metaData, 
currentDatabaseName, tableSegments);
-        tablesContext = new TablesContext(tableSegments, subqueryContexts);
-        groupByContext = new 
GroupByContextEngine().createGroupByContext(sqlStatement);
-        orderByContext = new 
OrderByContextEngine(sqlStatement.getDatabaseType()).createOrderBy(sqlStatement,
 groupByContext);
-        projectionsContext = new 
ProjectionsContextEngine(sqlStatement.getDatabaseType()).createProjectionsContext(sqlStatement.getProjections(),
 groupByContext, orderByContext);
-        DialectPaginationOption paginationOption = new 
DatabaseTypeRegistry(sqlStatement.getDatabaseType()).getDialectDatabaseMetaData().getPaginationOption();
-        paginationContext = new 
PaginationContextEngine(paginationOption).createPaginationContext(sqlStatement, 
projectionsContext, params, whereSegments);
-        containsEnhancedTable = isContainsEnhancedTable(metaData, 
tablesContext.getDatabaseNames(), currentDatabaseName);
-    }
-    
-    private Collection<WhereSegment> createWhereSegments(final SelectStatement 
selectStatement) {
-        Collection<WhereSegment> result = new LinkedList<>();
-        selectStatement.getWhere().ifPresent(result::add);
-        
result.addAll(WhereExtractor.extractSubqueryWhereSegments(selectStatement));
-        
result.addAll(WhereExtractor.extractJoinWhereSegments(selectStatement));
-        return result;
-    }
-    
-    private Collection<TableSegment> getAllTableSegments(final 
Collection<TableSegment> inheritedTables) {
-        TableExtractor tableExtractor = new TableExtractor();
-        appendInheritedSimpleTables(inheritedTables, tableExtractor);
-        tableExtractor.extractTablesFromSelect(sqlStatement);
-        Collection<TableSegment> result = new 
LinkedList<>(tableExtractor.getRewriteTables());
-        for (TableSegment each : tableExtractor.getTableContext()) {
-            if (each instanceof SubqueryTableSegment) {
-                result.add(each);
-            }
-        }
-        return result;
-    }
-    
-    private void appendInheritedSimpleTables(final Collection<TableSegment> 
inheritedTables, final TableExtractor tableExtractor) {
-        for (TableSegment each : inheritedTables) {
-            if (each instanceof SimpleTableSegment) {
-                tableExtractor.getTableContext().add(each);
-            }
-        }
-    }
-    
-    private boolean isContainsEnhancedTable(final ShardingSphereMetaData 
metaData, final Collection<String> databaseNames, final String 
currentDatabaseName) {
-        for (String each : databaseNames) {
-            if (isContainsEnhancedTable(metaData, each, 
getTablesContext().getTableNames())) {
-                return true;
-            }
-        }
-        return null != currentDatabaseName && 
isContainsEnhancedTable(metaData, currentDatabaseName, 
getTablesContext().getTableNames());
-    }
-    
-    private boolean isContainsEnhancedTable(final ShardingSphereMetaData 
metaData, final String databaseName, final Collection<String> tableNames) {
-        for (TableMapperRuleAttribute each : 
getTableMapperRuleAttributes(metaData, databaseName)) {
-            for (String tableName : tableNames) {
-                if (each.getEnhancedTableNames().contains(tableName)) {
-                    return true;
-                }
-            }
-        }
-        return false;
+    public SelectStatementContext(final SelectStatement sqlStatement, final 
List<Object> params, final ShardingSphereMetaData metaData,
+                                  final String currentDatabaseName, final 
Collection<TableSegment> inheritedTables) {
+        baseContext = new SelectStatementBaseContext(sqlStatement, params, 
metaData, currentDatabaseName, inheritedTables);
+        bindingContext = new SelectStatementBindingContext(params, 
baseContext);
     }
     
-    private Collection<TableMapperRuleAttribute> 
getTableMapperRuleAttributes(final ShardingSphereMetaData metaData, final 
String databaseName) {
-        if (null == databaseName) {
-            
ShardingSpherePreconditions.checkMustEmpty(tablesContext.getSimpleTables(), 
NoDatabaseSelectedException::new);
-            return Collections.emptyList();
-        }
-        ShardingSphereDatabase database = metaData.getDatabase(databaseName);
-        ShardingSpherePreconditions.checkNotNull(database, () -> new 
UnknownDatabaseException(databaseName));
-        return 
database.getRuleMetaData().getAttributes(TableMapperRuleAttribute.class);
-    }
-    
-    private Map<Integer, SelectStatementContext> createSubqueryContexts(final 
List<Object> params, final ShardingSphereMetaData metaData,
-                                                                        final 
String currentDatabaseName, final Collection<TableSegment> tableSegments) {
-        Collection<SubquerySegment> subquerySegments = 
SubqueryExtractor.extractSubquerySegments(sqlStatement, false);
-        Map<Integer, SelectStatementContext> result = new 
HashMap<>(subquerySegments.size(), 1F);
-        for (SubquerySegment each : subquerySegments) {
-            SelectStatementContext subqueryContext = new 
SelectStatementContext(each.getSelect(), params, metaData, currentDatabaseName, 
tableSegments);
-            
each.getSelect().getSubqueryType().ifPresent(subqueryContext::setSubqueryType);
-            result.put(each.getStartIndex(), subqueryContext);
-        }
-        return result;
+    public SelectStatementContext(final SelectStatementBaseContext 
baseContext, final List<Object> params) {
+        this.baseContext = baseContext;
+        bindingContext = new SelectStatementBindingContext(params, 
baseContext);
     }
     
     /**
@@ -209,7 +69,7 @@ public final class SelectStatementContext implements 
SQLStatementContext, WhereC
      * @return whether contains join query or not
      */
     public boolean isContainsJoinQuery() {
-        return sqlStatement.getFrom().isPresent() && 
sqlStatement.getFrom().get() instanceof JoinTableSegment;
+        return baseContext.isContainsJoinQuery();
     }
     
     /**
@@ -218,7 +78,7 @@ public final class SelectStatementContext implements 
SQLStatementContext, WhereC
      * @return whether contains subquery or not
      */
     public boolean isContainsSubquery() {
-        return !subqueryContexts.isEmpty();
+        return baseContext.isContainsSubquery();
     }
     
     /**
@@ -227,7 +87,7 @@ public final class SelectStatementContext implements 
SQLStatementContext, WhereC
      * @return whether contains having or not
      */
     public boolean isContainsHaving() {
-        return sqlStatement.getHaving().isPresent();
+        return baseContext.isContainsHaving();
     }
     
     /**
@@ -236,7 +96,7 @@ public final class SelectStatementContext implements 
SQLStatementContext, WhereC
      * @return whether contains combine or not
      */
     public boolean isContainsCombine() {
-        return sqlStatement.getCombine().isPresent();
+        return baseContext.isContainsCombine();
     }
     
     /**
@@ -245,25 +105,7 @@ public final class SelectStatementContext implements 
SQLStatementContext, WhereC
      * @return whether contains dollar parameter marker or not
      */
     public boolean isContainsDollarParameterMarker() {
-        for (Projection each : projectionsContext.getProjections()) {
-            if (each instanceof ParameterMarkerProjection && 
ParameterMarkerType.DOLLAR == ((ParameterMarkerProjection) 
each).getParameterMarkerType()) {
-                return true;
-            }
-        }
-        for (ParameterMarkerExpressionSegment each : 
getParameterMarkerExpressions()) {
-            if (ParameterMarkerType.DOLLAR == each.getParameterMarkerType()) {
-                return true;
-            }
-        }
-        return false;
-    }
-    
-    private Collection<ParameterMarkerExpressionSegment> 
getParameterMarkerExpressions() {
-        Collection<ExpressionSegment> expressions = new LinkedList<>();
-        for (WhereSegment each : whereSegments) {
-            expressions.add(each.getExpr());
-        }
-        return ExpressionExtractor.getParameterMarkerExpressions(expressions);
+        return baseContext.isContainsDollarParameterMarker();
     }
     
     /**
@@ -272,19 +114,7 @@ public final class SelectStatementContext implements 
SQLStatementContext, WhereC
      * @return whether contains partial distinct aggregation
      */
     public boolean isContainsPartialDistinctAggregation() {
-        Collection<Projection> aggregationProjections = 
getAggregationProjections(projectionsContext.getProjections());
-        Collection<AggregationDistinctProjection> 
aggregationDistinctProjections = 
projectionsContext.getAggregationDistinctProjections();
-        return aggregationProjections.size() > 1 && 
!aggregationDistinctProjections.isEmpty() && aggregationProjections.size() != 
aggregationDistinctProjections.size();
-    }
-    
-    private Collection<Projection> getAggregationProjections(final 
Collection<Projection> projections) {
-        Collection<Projection> result = new LinkedList<>();
-        for (Projection each : projections) {
-            if (each instanceof AggregationProjection) {
-                result.add(each);
-            }
-        }
-        return result;
+        return baseContext.isContainsPartialDistinctAggregation();
     }
     
     /**
@@ -293,74 +123,7 @@ public final class SelectStatementContext implements 
SQLStatementContext, WhereC
      * @param columnLabelIndexMap map for column label and index
      */
     public void setIndexes(final Map<String, Integer> columnLabelIndexMap) {
-        setIndexForAggregationProjection(columnLabelIndexMap);
-        setIndexForOrderItem(columnLabelIndexMap, orderByContext.getItems());
-        setIndexForOrderItem(columnLabelIndexMap, groupByContext.getItems());
-    }
-    
-    private void setIndexForAggregationProjection(final Map<String, Integer> 
columnLabelIndexMap) {
-        for (AggregationProjection each : 
projectionsContext.getAggregationProjections()) {
-            String columnLabel = 
SQLUtils.getExactlyValue(each.getAlias().map(IdentifierValue::getValue).orElse(each.getColumnName()));
-            
Preconditions.checkState(columnLabelIndexMap.containsKey(columnLabel), "Can't 
find index: %s, please add alias for aggregate selections", each);
-            each.setIndex(columnLabelIndexMap.get(columnLabel));
-            for (AggregationProjection derived : 
each.getDerivedAggregationProjections()) {
-                String derivedColumnLabel = 
SQLUtils.getExactlyValue(derived.getAlias().map(IdentifierValue::getValue).orElse(each.getColumnName()));
-                
Preconditions.checkState(columnLabelIndexMap.containsKey(derivedColumnLabel), 
"Can't find index: %s", derived);
-                derived.setIndex(columnLabelIndexMap.get(derivedColumnLabel));
-            }
-        }
-    }
-    
-    private void setIndexForOrderItem(final Map<String, Integer> 
columnLabelIndexMap, final Collection<OrderByItem> orderByItems) {
-        for (OrderByItem each : orderByItems) {
-            if (each.getSegment() instanceof IndexOrderByItemSegment) {
-                each.setIndex(((IndexOrderByItemSegment) 
each.getSegment()).getColumnIndex());
-                continue;
-            }
-            if (each.getSegment() instanceof ColumnOrderByItemSegment && 
((ColumnOrderByItemSegment) 
each.getSegment()).getColumn().getOwner().isPresent()) {
-                Optional<Integer> itemIndex = 
projectionsContext.findProjectionIndex(((ColumnOrderByItemSegment) 
each.getSegment()).getText());
-                if (itemIndex.isPresent()) {
-                    each.setIndex(itemIndex.get());
-                    continue;
-                }
-            }
-            String columnLabel = getAlias(each.getSegment()).orElseGet(() -> 
getOrderItemText((TextOrderByItemSegment) each.getSegment()));
-            
Preconditions.checkState(columnLabelIndexMap.containsKey(columnLabel), "Can't 
find index: %s", each);
-            if (columnLabelIndexMap.containsKey(columnLabel)) {
-                each.setIndex(columnLabelIndexMap.get(columnLabel));
-            }
-        }
-    }
-    
-    private Optional<String> getAlias(final OrderByItemSegment orderByItem) {
-        if (projectionsContext.isUnqualifiedShorthandProjection()) {
-            return Optional.empty();
-        }
-        String rawName = SQLUtils.getExactlyValue(((TextOrderByItemSegment) 
orderByItem).getText());
-        for (Projection each : projectionsContext.getProjections()) {
-            Optional<String> result = 
each.getAlias().map(IdentifierValue::getValue);
-            if 
(SQLUtils.getExactlyExpression(rawName).equalsIgnoreCase(SQLUtils.getExactlyExpression(SQLUtils.getExactlyValue(each.getExpression()))))
 {
-                return result;
-            }
-            if (rawName.equalsIgnoreCase(result.orElse(null))) {
-                return Optional.of(rawName);
-            }
-            if (isSameColumnName(each, rawName)) {
-                return result;
-            }
-        }
-        return Optional.empty();
-    }
-    
-    private boolean isSameColumnName(final Projection projection, final String 
name) {
-        return projection instanceof ColumnProjection && 
name.equalsIgnoreCase(((ColumnProjection) projection).getName().getValue());
-    }
-    
-    private String getOrderItemText(final TextOrderByItemSegment 
orderByItemSegment) {
-        if (orderByItemSegment instanceof ColumnOrderByItemSegment) {
-            return SQLUtils.getExactlyValue(((ColumnOrderByItemSegment) 
orderByItemSegment).getColumn().getIdentifier().getValue());
-        }
-        return SQLUtils.getExactlyValue(((ExpressionOrderByItemSegment) 
orderByItemSegment).getExpression());
+        baseContext.setIndexes(columnLabelIndexMap);
     }
     
     /**
@@ -369,7 +132,7 @@ public final class SelectStatementContext implements 
SQLStatementContext, WhereC
      * @return group by and order by sequence is same or not
      */
     public boolean isSameGroupByAndOrderByItems() {
-        return !groupByContext.getItems().isEmpty() && 
groupByContext.getItems().equals(orderByContext.getItems());
+        return baseContext.isSameGroupByAndOrderByItems();
     }
     
     /**
@@ -379,18 +142,7 @@ public final class SelectStatementContext implements 
SQLStatementContext, WhereC
      * @return column bound info
      */
     public Optional<ColumnSegmentBoundInfo> findColumnBoundInfo(final int 
columnIndex) {
-        List<Projection> expandProjections = 
projectionsContext.getExpandProjections();
-        if (expandProjections.size() < columnIndex) {
-            return Optional.empty();
-        }
-        Projection projection = expandProjections.get(columnIndex - 1);
-        if (projection instanceof ColumnProjection) {
-            return Optional.of(((ColumnProjection) 
projection).getColumnBoundInfo());
-        }
-        if (projection instanceof SubqueryProjection && ((SubqueryProjection) 
projection).getProjection() instanceof ColumnProjection) {
-            return Optional.of(((ColumnProjection) ((SubqueryProjection) 
projection).getProjection()).getColumnBoundInfo());
-        }
-        return Optional.empty();
+        return baseContext.findColumnBoundInfo(columnIndex);
     }
     
     /**
@@ -399,7 +151,7 @@ public final class SelectStatementContext implements 
SQLStatementContext, WhereC
      * @return whether sql statement contains table subquery segment or not
      */
     public boolean containsTableSubquery() {
-        return sqlStatement.getFrom().isPresent() && 
sqlStatement.getFrom().get() instanceof SubqueryTableSegment || 
sqlStatement.getWith().isPresent();
+        return baseContext.containsTableSubquery();
     }
     
     /**
@@ -408,27 +160,126 @@ public final class SelectStatementContext implements 
SQLStatementContext, WhereC
      * @return contains derived projections or not
      */
     public boolean containsDerivedProjections() {
-        return containsEnhancedTable && 
!projectionsContext.getExpandProjections().isEmpty();
+        return baseContext.containsDerivedProjections();
     }
     
     @Override
     public Collection<WhereSegment> getWhereSegments() {
-        return whereSegments;
+        return baseContext.getWhereSegments();
     }
     
     @Override
     public Collection<ColumnSegment> getColumnSegments() {
-        return columnSegments;
+        return baseContext.getColumnSegments();
     }
     
     @Override
     public Collection<BinaryOperationExpression> getJoinConditions() {
-        return joinConditions;
+        return baseContext.getJoinConditions();
+    }
+    
+    @Override
+    public SelectStatement getSqlStatement() {
+        return baseContext.getSqlStatement();
+    }
+    
+    @Override
+    public TablesContext getTablesContext() {
+        return baseContext.getTablesContext();
+    }
+    
+    /**
+     * Set subquery type.
+     *
+     * @param subqueryType subquery type
+     */
+    public void setSubqueryType(final SubqueryType subqueryType) {
+        baseContext.setSubqueryType(subqueryType);
+    }
+    
+    /**
+     * Get subquery type.
+     *
+     * @return subquery type
+     */
+    public SubqueryType getSubqueryType() {
+        return baseContext.getSubqueryType();
+    }
+    
+    /**
+     * Get subquery contexts.
+     *
+     * @return subquery contexts
+     */
+    public Map<Integer, SelectStatementContext> getSubqueryContexts() {
+        return baseContext.getSubqueryContexts();
+    }
+    
+    /**
+     * Get projections context.
+     *
+     * @return projections context
+     */
+    public ProjectionsContext getProjectionsContext() {
+        return baseContext.getProjectionsContext();
+    }
+    
+    /**
+     * Get group by context.
+     *
+     * @return group by context
+     */
+    public GroupByContext getGroupByContext() {
+        return baseContext.getGroupByContext();
+    }
+    
+    /**
+     * Get order by context.
+     *
+     * @return order by context
+     */
+    public OrderByContext getOrderByContext() {
+        return baseContext.getOrderByContext();
+    }
+    
+    /**
+     * Set need aggregate rewrite.
+     *
+     * @param needAggregateRewrite need aggregate rewrite
+     */
+    public void setNeedAggregateRewrite(final boolean needAggregateRewrite) {
+        baseContext.setNeedAggregateRewrite(needAggregateRewrite);
+    }
+    
+    /**
+     * Judge whether need aggregate rewrite or not.
+     *
+     * @return whether need aggregate rewrite or not
+     */
+    public boolean isNeedAggregateRewrite() {
+        return baseContext.isNeedAggregateRewrite();
+    }
+    
+    /**
+     * Judge whether contains enhanced table or not.
+     *
+     * @return whether contains enhanced table or not
+     */
+    public boolean isContainsEnhancedTable() {
+        return baseContext.isContainsEnhancedTable();
+    }
+    
+    /**
+     * Get pagination context.
+     *
+     * @return pagination context
+     */
+    public PaginationContext getPaginationContext() {
+        return bindingContext.getPaginationContext();
     }
     
     @Override
     public void setUpParameters(final List<Object> params) {
-        DialectPaginationOption paginationOption = new 
DatabaseTypeRegistry(sqlStatement.getDatabaseType()).getDialectDatabaseMetaData().getPaginationOption();
-        paginationContext = new 
PaginationContextEngine(paginationOption).createPaginationContext(sqlStatement, 
projectionsContext, params, whereSegments);
+        bindingContext = new SelectStatementBindingContext(params, 
baseContext);
     }
 }

Reply via email to