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.encrypt.merge.dal.show;
19  
20  import org.apache.shardingsphere.encrypt.exception.syntax.UnsupportedEncryptSQLException;
21  import org.apache.shardingsphere.encrypt.rule.EncryptRule;
22  import org.apache.shardingsphere.encrypt.rule.EncryptTable;
23  import org.apache.shardingsphere.infra.binder.context.statement.SQLStatementContext;
24  import org.apache.shardingsphere.infra.binder.context.type.TableAvailable;
25  import org.apache.shardingsphere.infra.merge.result.MergedResult;
26  import org.apache.shardingsphere.infra.exception.core.ShardingSpherePreconditions;
27  
28  import java.io.InputStream;
29  import java.io.Reader;
30  import java.sql.SQLException;
31  import java.sql.SQLFeatureNotSupportedException;
32  import java.util.Calendar;
33  import java.util.Optional;
34  
35  /**
36   * Encrypt show columns merged result.
37   */
38  public abstract class EncryptShowColumnsMergedResult implements MergedResult {
39      
40      private static final int COLUMN_FIELD_INDEX = 1;
41      
42      private final String tableName;
43      
44      private final EncryptRule encryptRule;
45      
46      protected EncryptShowColumnsMergedResult(final SQLStatementContext sqlStatementContext, final EncryptRule encryptRule) {
47          ShardingSpherePreconditions.checkState(sqlStatementContext instanceof TableAvailable && 1 == ((TableAvailable) sqlStatementContext).getAllTables().size(),
48                  () -> new UnsupportedEncryptSQLException("SHOW COLUMNS FOR MULTI TABLE"));
49          tableName = ((TableAvailable) sqlStatementContext).getAllTables().iterator().next().getTableName().getIdentifier().getValue();
50          this.encryptRule = encryptRule;
51      }
52      
53      @Override
54      public final boolean next() throws SQLException {
55          boolean hasNext = nextValue();
56          Optional<EncryptTable> encryptTable = encryptRule.findEncryptTable(tableName);
57          if (hasNext && !encryptTable.isPresent()) {
58              return true;
59          }
60          if (!hasNext) {
61              return false;
62          }
63          String columnName = getOriginalValue(COLUMN_FIELD_INDEX, String.class).toString();
64          while (isDerivedColumn(encryptTable.get(), columnName)) {
65              hasNext = nextValue();
66              if (!hasNext) {
67                  return false;
68              }
69              columnName = getOriginalValue(COLUMN_FIELD_INDEX, String.class).toString();
70          }
71          return true;
72      }
73      
74      private boolean isDerivedColumn(final EncryptTable encryptTable, final String columnName) {
75          return encryptTable.isAssistedQueryColumn(columnName) || encryptTable.isLikeQueryColumn(columnName);
76      }
77      
78      @Override
79      public final Object getValue(final int columnIndex, final Class<?> type) throws SQLException {
80          if (COLUMN_FIELD_INDEX == columnIndex) {
81              String columnName = getOriginalValue(COLUMN_FIELD_INDEX, type).toString();
82              Optional<EncryptTable> encryptTable = encryptRule.findEncryptTable(tableName);
83              if (!encryptTable.isPresent()) {
84                  return columnName;
85              }
86              Optional<String> logicColumn = encryptTable.get().isCipherColumn(columnName) ? Optional.of(encryptTable.get().getLogicColumnByCipherColumn(columnName)) : Optional.empty();
87              return logicColumn.orElse(columnName);
88          }
89          return getOriginalValue(columnIndex, type);
90      }
91      
92      @Override
93      public final Object getCalendarValue(final int columnIndex, final Class<?> type, final Calendar calendar) throws SQLException {
94          throw new SQLFeatureNotSupportedException("");
95      }
96      
97      @Override
98      public final InputStream getInputStream(final int columnIndex, final String type) throws SQLException {
99          throw new SQLFeatureNotSupportedException("");
100     }
101     
102     @Override
103     public Reader getCharacterStream(final int columnIndex) throws SQLException {
104         throw new SQLFeatureNotSupportedException("");
105     }
106     
107     protected abstract boolean nextValue() throws SQLException;
108     
109     protected abstract Object getOriginalValue(int columnIndex, Class<?> type) throws SQLException;
110 }