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.segment.projection;
19  
20  import lombok.AccessLevel;
21  import lombok.NoArgsConstructor;
22  import org.apache.shardingsphere.infra.binder.enums.SegmentType;
23  import org.apache.shardingsphere.infra.binder.segment.expression.ExpressionSegmentBinder;
24  import org.apache.shardingsphere.infra.binder.segment.from.TableSegmentBinderContext;
25  import org.apache.shardingsphere.infra.binder.segment.projection.impl.ColumnProjectionSegmentBinder;
26  import org.apache.shardingsphere.infra.binder.segment.projection.impl.ShorthandProjectionSegmentBinder;
27  import org.apache.shardingsphere.infra.binder.segment.projection.impl.SubqueryProjectionSegmentBinder;
28  import org.apache.shardingsphere.infra.binder.statement.SQLStatementBinderContext;
29  import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ColumnProjectionSegment;
30  import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ExpressionProjectionSegment;
31  import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionSegment;
32  import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionsSegment;
33  import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ShorthandProjectionSegment;
34  import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.SubqueryProjectionSegment;
35  import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.TableSegment;
36  
37  import java.util.LinkedHashMap;
38  import java.util.Map;
39  
40  /**
41   * Projections segment binder.
42   */
43  @NoArgsConstructor(access = AccessLevel.PRIVATE)
44  public final class ProjectionsSegmentBinder {
45      
46      /**
47       * Bind projections segment with metadata.
48       *
49       * @param segment table segment
50       * @param statementBinderContext statement binder context
51       * @param boundedTableSegment bounded table segment
52       * @param tableBinderContexts table binder contexts
53       * @param outerTableBinderContexts outer table binder contexts
54       * @return bounded projections segment
55       */
56      public static ProjectionsSegment bind(final ProjectionsSegment segment, final SQLStatementBinderContext statementBinderContext, final TableSegment boundedTableSegment,
57                                            final Map<String, TableSegmentBinderContext> tableBinderContexts, final Map<String, TableSegmentBinderContext> outerTableBinderContexts) {
58          ProjectionsSegment result = new ProjectionsSegment(segment.getStartIndex(), segment.getStopIndex());
59          result.setDistinctRow(segment.isDistinctRow());
60          segment.getProjections().forEach(each -> result.getProjections().add(bind(each, statementBinderContext, boundedTableSegment, tableBinderContexts, outerTableBinderContexts)));
61          return result;
62      }
63      
64      private static ProjectionSegment bind(final ProjectionSegment projectionSegment, final SQLStatementBinderContext statementBinderContext,
65                                            final TableSegment boundedTableSegment, final Map<String, TableSegmentBinderContext> tableBinderContexts,
66                                            final Map<String, TableSegmentBinderContext> outerTableBinderContexts) {
67          if (projectionSegment instanceof ColumnProjectionSegment) {
68              return ColumnProjectionSegmentBinder.bind((ColumnProjectionSegment) projectionSegment, statementBinderContext, tableBinderContexts);
69          }
70          if (projectionSegment instanceof ShorthandProjectionSegment) {
71              return ShorthandProjectionSegmentBinder.bind((ShorthandProjectionSegment) projectionSegment, boundedTableSegment, tableBinderContexts);
72          }
73          if (projectionSegment instanceof SubqueryProjectionSegment) {
74              Map<String, TableSegmentBinderContext> newOuterTableBinderContexts = new LinkedHashMap<>();
75              newOuterTableBinderContexts.putAll(outerTableBinderContexts);
76              newOuterTableBinderContexts.putAll(tableBinderContexts);
77              return SubqueryProjectionSegmentBinder.bind((SubqueryProjectionSegment) projectionSegment, statementBinderContext, newOuterTableBinderContexts);
78          }
79          if (projectionSegment instanceof ExpressionProjectionSegment) {
80              ExpressionProjectionSegment result = new ExpressionProjectionSegment(projectionSegment.getStartIndex(), projectionSegment.getStopIndex(),
81                      ((ExpressionProjectionSegment) projectionSegment).getText(), ExpressionSegmentBinder.bind(((ExpressionProjectionSegment) projectionSegment).getExpr(), SegmentType.PROJECTION,
82                              statementBinderContext, tableBinderContexts, outerTableBinderContexts));
83              result.setAlias(((ExpressionProjectionSegment) projectionSegment).getAliasSegment());
84              return result;
85          }
86          // TODO support more ProjectionSegment bind
87          return projectionSegment;
88      }
89  }