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.insert.values;
19  
20  import com.google.common.base.Preconditions;
21  import lombok.Getter;
22  import lombok.ToString;
23  import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.assignment.ColumnAssignmentSegment;
24  import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
25  import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
26  import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.FunctionSegment;
27  import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.LiteralExpressionSegment;
28  import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.ParameterMarkerExpressionSegment;
29  import org.apache.shardingsphere.sql.parser.sql.common.util.ExpressionExtractUtils;
30  
31  import java.util.ArrayList;
32  import java.util.Collection;
33  import java.util.Collections;
34  import java.util.List;
35  import java.util.stream.Collectors;
36  
37  @Getter
38  @ToString
39  public final class OnDuplicateUpdateContext {
40      
41      private final int parameterCount;
42      
43      private final List<ExpressionSegment> valueExpressions;
44      
45      private final List<ParameterMarkerExpressionSegment> parameterMarkerExpressions;
46      
47      private final List<Object> parameters;
48      
49      private final List<ColumnSegment> columns;
50      
51      public OnDuplicateUpdateContext(final Collection<ColumnAssignmentSegment> assignments, final List<Object> params, final int parametersOffset) {
52          List<ExpressionSegment> expressionSegments = assignments.stream().map(ColumnAssignmentSegment::getValue).collect(Collectors.toList());
53          valueExpressions = getValueExpressions(expressionSegments);
54          parameterMarkerExpressions = ExpressionExtractUtils.getParameterMarkerExpressions(expressionSegments);
55          parameterCount = parameterMarkerExpressions.size();
56          parameters = getParameters(params, parametersOffset);
57          columns = assignments.stream().map(each -> each.getColumns().get(0)).collect(Collectors.toList());
58      }
59      
60      private List<ExpressionSegment> getValueExpressions(final Collection<ExpressionSegment> assignments) {
61          List<ExpressionSegment> result = new ArrayList<>(assignments.size());
62          result.addAll(assignments);
63          return result;
64      }
65      
66      private List<Object> getParameters(final List<Object> params, final int paramsOffset) {
67          if (params.isEmpty() || 0 == parameterCount) {
68              return Collections.emptyList();
69          }
70          List<Object> result = new ArrayList<>(parameterCount);
71          result.addAll(params.subList(paramsOffset, paramsOffset + parameterCount));
72          return result;
73      }
74      
75      /**
76       * Get value.
77       *
78       * @param index index
79       * @return value
80       */
81      public Object getValue(final int index) {
82          ExpressionSegment valueExpression = valueExpressions.get(index);
83          if (valueExpression instanceof ParameterMarkerExpressionSegment) {
84              return parameters.get(getParameterIndex((ParameterMarkerExpressionSegment) valueExpression));
85          }
86          if (valueExpression instanceof FunctionSegment) {
87              return valueExpression;
88          }
89          return ((LiteralExpressionSegment) valueExpression).getLiterals();
90      }
91      
92      private int getParameterIndex(final ParameterMarkerExpressionSegment paramMarkerExpression) {
93          int result = parameterMarkerExpressions.indexOf(paramMarkerExpression);
94          Preconditions.checkArgument(result >= 0, "Can not get parameter index.");
95          return result;
96      }
97      
98      /**
99       * Get on duplicate key update column by index of this clause.
100      *
101      * @param index index
102      * @return columnSegment
103      */
104     public ColumnSegment getColumn(final int index) {
105         return columns.get(index);
106     }
107 }