/**
 * Copyright (C) 2009-2013 FoundationDB, LLC
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.foundationdb.sql.pg;

import com.foundationdb.ais.model.Table;
import com.foundationdb.ais.model.TableName;
import com.foundationdb.server.types.TInstance;
import com.foundationdb.server.types.common.types.TypesTranslator;
import com.foundationdb.sql.optimizer.plan.BasePlannable;
import com.foundationdb.sql.optimizer.plan.PhysicalSelect;
import com.foundationdb.sql.optimizer.plan.PhysicalUpdate;
import com.foundationdb.sql.optimizer.rule.PlanContext;
import com.foundationdb.sql.parser.DMLStatementNode;
import com.foundationdb.sql.parser.ParameterNode;
import com.foundationdb.sql.parser.StatementNode;
import com.foundationdb.sql.server.ServerPlanContext;
import com.foundationdb.sql.types.DataTypeDescriptor;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

public abstract class PostgresBaseOperatorStatement extends PostgresDMLStatement
{
    private PostgresOperatorCompiler compiler;
    private Set<TableName> affectedTables;

    protected PostgresBaseOperatorStatement(PostgresOperatorCompiler compiler) {
        this.compiler = compiler;
    }

    @Override
    public PostgresStatement finishGenerating(PostgresServerSession server,
                                              String sql, StatementNode stmt,
                                              List<ParameterNode> params, int[] paramTypes) {
        DMLStatementNode dmlStmt = (DMLStatementNode)stmt;
        PlanContext planContext = new ServerPlanContext(compiler, new PostgresQueryContext(server));
        BasePlannable result = compiler.compile(dmlStmt, params, planContext);
        PostgresType[] parameterTypes = getParameterTypes(result.getParameterTypes(),
                                                          paramTypes,
                                                          server.typesTranslator());

        final PostgresBaseOperatorStatement pbos;
        if (result.isUpdate())
            pbos = compiler.generateUpdate(this,
                                           (PhysicalUpdate)result, stmt.statementToString(),
                                           parameterTypes);
        else
            pbos = compiler.generateSelect(this,
                                           (PhysicalSelect)result,
                                           parameterTypes);
        pbos.compiler = null;
        Set<TableName> affectedTables = new HashSet<>();
        for(Table table : result.getAffectedTables()) {
            affectedTables.add(table.getName());
        }
        pbos.setAffectedTables(affectedTables);
        return pbos;
    }

    protected PostgresType[] getParameterTypes(DataTypeDescriptor[] sqlTypes,
                                               int[] paramTypes,
                                               TypesTranslator typesTranslator) {
        if (sqlTypes == null) 
            return null;
        int nparams = sqlTypes.length;
        PostgresType[] parameterTypes = new PostgresType[nparams];
        for (int i = 0; i < nparams; i++) {
            DataTypeDescriptor sqlType = sqlTypes[i];
            PostgresType pgType = null;
            if (sqlType != null) {
                TInstance tInstance = typesTranslator.toTInstance(sqlType);
                pgType = PostgresType.fromDerby(sqlType, tInstance);
            }
            if ((paramTypes != null) && (i < paramTypes.length)) {
                // Make a type that has the target that the query wants, with the
                // OID that the client proposed to send so that we
                // decode it properly.
                PostgresType.TypeOid oid = PostgresType.TypeOid.fromOid(paramTypes[i]);
                if (oid != null) {
                    if (pgType == null)
                        pgType = new PostgresType(oid, (short)-1, -1, null);
                    else
                        pgType = new PostgresType(oid,  (short)-1, -1,
                                                  pgType.getInstance());
                }
            }
            parameterTypes[i] = pgType;
        }
        return parameterTypes;
    }

    public Set<TableName> getAffectedTables() {
        return affectedTables;
    }

    public void setAffectedTables(Set<TableName> affectedTables) {
        this.affectedTables = affectedTables;
    }
}

@@ -1651,51 +1651,8 @@
 ler;
-%0A    private Set%3CTableName%3E affectedTables;
 %0A%0A  
@@ -3192,56 +3192,8 @@
   %7D%0A
-        pbos.setAffectedTables(affectedTables);%0A
     
@@ -4673,32 +4673,32 @@
 Type;%0A        %7D%0A
+
         return p
@@ -4721,213 +4721,7 @@
    %7D
-%0A%0A    public Set%3CTableName%3E getAffectedTables() %7B%0A        return affectedTables;%0A    %7D%0A%0A    public void setAffectedTables(Set%3CTableName%3E affectedTables) %7B%0A        this.affectedTables = affectedTables;%0A    %7D
 %0A%7D%0A

Remove the affectedTables altogether.