EncryptPredicateColumnTokenGenerator.java 5.7 KB
Newer Older
L
Liang Zhang 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/*
 * 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.
 */

18
package org.apache.shardingsphere.encrypt.rewrite.token.generator.impl;
L
Liang Zhang 已提交
19 20 21

import com.google.common.base.Preconditions;
import lombok.Setter;
22 23
import org.apache.shardingsphere.encrypt.rewrite.aware.QueryWithCipherColumnAware;
import org.apache.shardingsphere.encrypt.rewrite.token.generator.BaseEncryptSQLTokenGenerator;
24
import org.apache.shardingsphere.encrypt.rule.EncryptTable;
J
JingShang Lu 已提交
25 26 27
import org.apache.shardingsphere.infra.rewrite.sql.token.generator.CollectionSQLTokenGenerator;
import org.apache.shardingsphere.infra.rewrite.sql.token.generator.aware.SchemaMetaDataAware;
import org.apache.shardingsphere.infra.rewrite.sql.token.pojo.generic.SubstitutableColumnNameToken;
28
import org.apache.shardingsphere.infra.metadata.schema.ShardingSphereSchema;
29 30
import org.apache.shardingsphere.infra.binder.statement.SQLStatementContext;
import org.apache.shardingsphere.infra.binder.type.WhereAvailable;
J
JingShang Lu 已提交
31 32
import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
T
tristaZero 已提交
33
import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.AndPredicate;
J
JingShang Lu 已提交
34
import org.apache.shardingsphere.sql.parser.sql.common.util.ExpressionBuilder;
35
import org.apache.shardingsphere.sql.parser.sql.common.util.ColumnExtractor;
L
Liang Zhang 已提交
36 37

import java.util.Collection;
38
import java.util.LinkedHashSet;
L
Liang Zhang 已提交
39
import java.util.LinkedList;
L
Liang Zhang 已提交
40
import java.util.Optional;
L
Liang Zhang 已提交
41 42 43 44 45

/**
 * Predicate column token generator for encrypt.
 */
@Setter
46
public final class EncryptPredicateColumnTokenGenerator extends BaseEncryptSQLTokenGenerator implements CollectionSQLTokenGenerator, SchemaMetaDataAware, QueryWithCipherColumnAware {
L
Liang Zhang 已提交
47
    
48
    private ShardingSphereSchema schema;
L
Liang Zhang 已提交
49 50 51 52
    
    private boolean queryWithCipherColumn;
    
    @Override
53
    protected boolean isGenerateSQLTokenForEncrypt(final SQLStatementContext sqlStatementContext) {
54
        return sqlStatementContext instanceof WhereAvailable && ((WhereAvailable) sqlStatementContext).getWhere().isPresent();
L
Liang Zhang 已提交
55 56 57
    }
    
    @Override
L
Liang Zhang 已提交
58
    public Collection<SubstitutableColumnNameToken> generateSQLTokens(final SQLStatementContext sqlStatementContext) {
59
        Preconditions.checkState(((WhereAvailable) sqlStatementContext).getWhere().isPresent());
60
        Collection<SubstitutableColumnNameToken> result = new LinkedHashSet<>();
J
JingShang Lu 已提交
61
        ExpressionSegment expression = ((WhereAvailable) sqlStatementContext).getWhere().get().getExpr();
J
JingShang Lu 已提交
62 63
        ExpressionBuilder expressionBuilder = new ExpressionBuilder(expression);
        Collection<AndPredicate> andPredicates = new LinkedList<>(expressionBuilder.extractAndPredicates().getAndPredicates());
J
JingShang Lu 已提交
64
        for (AndPredicate each : andPredicates) {
L
Liang Zhang 已提交
65
            result.addAll(generateSQLTokens(sqlStatementContext, each));
L
Liang Zhang 已提交
66 67 68 69
        }
        return result;
    }
    
L
Liang Zhang 已提交
70 71
    private Collection<SubstitutableColumnNameToken> generateSQLTokens(final SQLStatementContext sqlStatementContext, final AndPredicate andPredicate) {
        Collection<SubstitutableColumnNameToken> result = new LinkedList<>();
J
JingShang Lu 已提交
72
        for (ExpressionSegment each : andPredicate.getPredicates()) {
73
            Optional<ColumnSegment> column = ColumnExtractor.extract(each);
J
fix  
JingShang Lu 已提交
74
            if (!column.isPresent()) {
J
JingShang Lu 已提交
75 76
                continue;
            }
J
fix  
JingShang Lu 已提交
77 78
            Optional<EncryptTable> encryptTable = findEncryptTable(sqlStatementContext, column.get());
            if (!encryptTable.isPresent() || !encryptTable.get().findEncryptorName(column.get().getIdentifier().getValue()).isPresent()) {
L
Liang Zhang 已提交
79 80
                continue;
            }
J
fix  
JingShang Lu 已提交
81 82
            int startIndex = column.get().getOwner().isPresent() ? column.get().getOwner().get().getStopIndex() + 2 : column.get().getStartIndex();
            int stopIndex = column.get().getStopIndex();
J
JingShang Lu 已提交
83
            if (!queryWithCipherColumn) {
J
fix  
JingShang Lu 已提交
84
                Optional<String> plainColumn = encryptTable.get().findPlainColumn(column.get().getIdentifier().getValue());
L
Liang Zhang 已提交
85
                if (plainColumn.isPresent()) {
L
Liang Zhang 已提交
86
                    result.add(new SubstitutableColumnNameToken(startIndex, stopIndex, plainColumn.get()));
L
Liang Zhang 已提交
87 88 89
                    continue;
                }
            }
J
fix  
JingShang Lu 已提交
90
            Optional<String> assistedQueryColumn = encryptTable.get().findAssistedQueryColumn(column.get().getIdentifier().getValue());
L
Liang Zhang 已提交
91
            SubstitutableColumnNameToken encryptColumnNameToken = assistedQueryColumn.map(columnName -> new SubstitutableColumnNameToken(startIndex, stopIndex, columnName))
J
fix  
JingShang Lu 已提交
92
                    .orElseGet(() -> new SubstitutableColumnNameToken(startIndex, stopIndex, encryptTable.get().getCipherColumn(column.get().getIdentifier().getValue())));
L
Liang Zhang 已提交
93 94 95 96 97
            result.add(encryptColumnNameToken);
        }
        return result;
    }
    
J
JingShang Lu 已提交
98
    private Optional<EncryptTable> findEncryptTable(final SQLStatementContext sqlStatementContext, final ColumnSegment column) {
99
        return sqlStatementContext.getTablesContext().findTableName(column, schema).flatMap(tableName -> getEncryptRule().findEncryptTable(tableName));
L
Liang Zhang 已提交
100 101
    }
}