/*
 * 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.shardingproxy.frontend.postgresql.command.query.binary.parse;

import org.apache.shardingsphere.core.constant.DatabaseType;
import org.apache.shardingsphere.core.parse.entry.ShardingSQLParseEntry;
import org.apache.shardingsphere.core.parse.sql.statement.SQLStatement;
import org.apache.shardingsphere.core.rule.ShardingRule;
import org.apache.shardingsphere.shardingproxy.backend.communication.jdbc.connection.BackendConnection;
import org.apache.shardingsphere.shardingproxy.backend.schema.LogicSchema;
import org.apache.shardingsphere.shardingproxy.backend.schema.MasterSlaveSchema;
import org.apache.shardingsphere.shardingproxy.backend.schema.ShardingSchema;
import org.apache.shardingsphere.shardingproxy.frontend.api.CommandExecutor;
import org.apache.shardingsphere.shardingproxy.transport.packet.DatabasePacket;
import org.apache.shardingsphere.shardingproxy.transport.postgresql.packet.command.query.binary.BinaryStatementRegistry;
import org.apache.shardingsphere.shardingproxy.transport.postgresql.packet.command.query.binary.ConnectionScopeBinaryStatementRegistry;
import org.apache.shardingsphere.shardingproxy.transport.postgresql.packet.command.query.binary.parse.PostgreSQLComParsePacket;
import org.apache.shardingsphere.shardingproxy.transport.postgresql.packet.command.query.binary.parse.PostgreSQLParseCompletePacket;

import java.util.Collection;
import java.util.Collections;

/**
 * PostgreSQL command parse executor.
 *
 * @author zhangyonglun
 * @author zhangliang
 */
public final class PostgreSQLComParseExecutor implements CommandExecutor {
    
    private final PostgreSQLComParsePacket packet;
    
    private final LogicSchema logicSchema;
    
    private final ConnectionScopeBinaryStatementRegistry binaryStatementRegistry;
    
    public PostgreSQLComParseExecutor(final PostgreSQLComParsePacket packet, final BackendConnection backendConnection) {
        this.packet = packet;
        logicSchema = backendConnection.getLogicSchema();
        binaryStatementRegistry = BinaryStatementRegistry.getInstance().get(backendConnection.getConnectionId());
    }
    
    @Override
    public Collection<DatabasePacket> execute() {
        // TODO we should use none-sharding parsing engine in future.
        ShardingSQLParseEntry shardingSQLParseEntry = new ShardingSQLParseEntry(
                DatabaseType.PostgreSQL, getShardingRule(logicSchema), logicSchema.getMetaData().getTable(), logicSchema.getParsingResultCache());
        if (!packet.getSql().isEmpty()) {
            SQLStatement sqlStatement = shardingSQLParseEntry.parse(packet.getSql(), true);
            int parametersIndex = sqlStatement.getParametersIndex();
            binaryStatementRegistry.register(packet.getStatementId(), packet.getSql(), parametersIndex, packet.getBinaryStatementParameterTypes());
        }
        return Collections.<DatabasePacket>singletonList(new PostgreSQLParseCompletePacket());
    }
    
    private ShardingRule getShardingRule(final LogicSchema logicSchema) {
        return logicSchema instanceof MasterSlaveSchema ? ((MasterSlaveSchema) logicSchema).getDefaultShardingRule() : ((ShardingSchema) logicSchema).getShardingRule();
    }
}

@@ -1256,24 +1256,101 @@
 Connection;%0A
+import org.apache.shardingsphere.shardingproxy.backend.schema.EncryptSchema;%0A
 import org.a
@@ -3919,23 +3919,152 @@
         
-return 
+if (logicSchema instanceof ShardingSchema) %7B%0A            return ((ShardingSchema) logicSchema).getShardingRule();%0A        %7D%0A        if (
 logicSch
@@ -4099,10 +4099,30 @@
 hema
- ?
+) %7B%0A            return
  ((M
@@ -4180,21 +4180,44 @@
 le()
- : ((Sharding
+;%0A        %7D%0A        return ((Encrypt
 Sche
@@ -4228,32 +4228,39 @@
 logicSchema).get
+Default
 ShardingRule();%0A

modify getShardingRule()