/**
 * 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.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.List;
import java.util.Set;

public abstract class PostgresBaseOperatorStatement extends PostgresDMLStatement
{
    private PostgresOperatorCompiler compiler;
    private Set<Table> 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;
        pbos.setAffectedTables(result.getAffectedTables());
        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<Table> getAffectedTables() {
        return affectedTables;
    }

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

@@ -788,24 +788,69 @@
 odel.Table;%0A
+import com.foundationdb.ais.model.TableName;%0A
 import com.f
@@ -1446,16 +1446,42 @@
 iptor;%0A%0A
+import java.util.HashSet;%0A
 import j
@@ -1661,32 +1661,36 @@
 rivate Set%3CTable
+Name
 %3E affectedTables
@@ -3071,39 +3071,186 @@
     
-pbos.setAffectedTables(result.g
+Set%3CTableName%3E affectedTables = new HashSet%3C%3E();%0A        for(Table table : result.getAffectedTables()) %7B%0A            affectedTables.add(table.getName());%0A        %7D%0A        pbos.s
 etAf
@@ -3262,17 +3262,30 @@
 dTables(
-)
+affectedTables
 );%0A     
@@ -4830,16 +4830,20 @@
 et%3CTable
+Name
 %3E getAff
@@ -4939,16 +4939,20 @@
 et%3CTable
+Name
 %3E affect

Replace the (unused) table list with a TableName list.