/*
 * Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.internal.expressions;

import java.io.*;
import java.util.*;
import org.eclipse.persistence.exceptions.*;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.queries.*;
import org.eclipse.persistence.internal.databaseaccess.DatabaseCall;
import org.eclipse.persistence.internal.databaseaccess.DatasourcePlatform;
import org.eclipse.persistence.internal.helper.*;
import org.eclipse.persistence.internal.sessions.AbstractSession;

/**
 * <p><b>Purpose</b>: Print DELETE statement with non trivial WHERE clause
 * <p><b>Responsibilities</b>:<ul>
 * <li> Print DELETE statement.
 * </ul>
 * @author Andrei Ilitchev
 * @since TOPLink 10.1.3
 */
public class SQLDeleteAllStatement extends SQLDeleteStatement {

    protected Expression inheritanceExpression;

    protected SQLCall selectCallForExist;
    protected String tableAliasInSelectCallForExist;

    protected SQLCall selectCallForNotExist;
    protected String tableAliasInSelectCallForNotExist;

    // A pair of Vectors for join expression
    protected Vector aliasedFields;
    protected Vector originalFields;

    protected boolean shouldExtractWhereClauseFromSelectCallForExist;

    public void setSelectCallForExist(SQLCall selectCallForExist) {
        this.selectCallForExist = selectCallForExist;
    }
    public SQLCall getSelectCallForExist() {
        return selectCallForExist;
    }
    public void setSelectCallForNotExist(SQLCall selectCallForNotExist) {
        this.selectCallForNotExist = selectCallForNotExist;
    }
    public SQLCall getSelectCallForNotExist() {
        return selectCallForNotExist;
    }
    public void setTableAliasInSelectCallForExist(String tableAliasInSelectCallForExist) {
        this.tableAliasInSelectCallForExist = tableAliasInSelectCallForExist;
    }
    public String getTableAliasInSelectCallForExist() {
        return tableAliasInSelectCallForExist;
    }
    public void setTableAliasInSelectCallForNotExist(String tableAliasInSelectCallForNotExist) {
        this.tableAliasInSelectCallForNotExist = tableAliasInSelectCallForNotExist;
    }
    public String getTableAliasInSelectCallForNotExist() {
        return tableAliasInSelectCallForNotExist;
    }
    public void setPrimaryKeyFieldsForAutoJoin(Collection primaryKeyFields) {
        if(primaryKeyFields != null) {
            if(primaryKeyFields instanceof Vector) {
                setOriginalFieldsForJoin((Vector)primaryKeyFields);
            } else {
                setOriginalFieldsForJoin(new Vector(primaryKeyFields));
            }
            setAliasedFieldsForJoin((Vector)getOriginalFieldsForJoin().clone());
        } else {
            setOriginalFieldsForJoin(null);
            setAliasedFieldsForJoin(null);
        }
    }
    public void setOriginalFieldsForJoin(Vector originalFields) {
        this.originalFields = originalFields;
    }
    public Vector getOriginalFieldsForJoin() {
        return originalFields;
    }
    public void setAliasedFieldsForJoin(Vector aliasedFields) {
        this.aliasedFields = aliasedFields;
    }
    public Vector getAliasedFieldsForExpression() {
        return aliasedFields;
    }
    public void setInheritanceExpression(Expression inheritanceExpression) {
        this.inheritanceExpression = inheritanceExpression;
    }
    public Expression getInheritanceExpression() {
        return inheritanceExpression;
    }

    public void setShouldExtractWhereClauseFromSelectCallForExist(boolean shouldExtractWhereClauseFromSelectCallForExist) {
        this.shouldExtractWhereClauseFromSelectCallForExist = shouldExtractWhereClauseFromSelectCallForExist;
    }
    public boolean shouldExtractWhereClauseFromSelectCallForExist() {
        return shouldExtractWhereClauseFromSelectCallForExist;
    }

    /**
     * Return SQL call for the statement, through generating the SQL string.
     */
    @Override
    public DatabaseCall buildCall(AbstractSession session) {
        SQLCall call = (SQLCall)super.buildCall(session);

        Writer writer = new CharArrayWriter(100);
        try {
            // because where clause is null,
            // call.sqlString == "DELETE FROM getTable().getQualifiedName()"
            writer.write(call.getSQLString());

            boolean whereWasPrinted = true;
            if(selectCallForExist != null) {
                if(shouldExtractWhereClauseFromSelectCallForExist) {
                    // Should get here only in case selectCallForExist doesn't have aliases and
                    // targets the same table as the statement.
                    // Instead of making selectCallForExist part of " WHERE EXIST("
                    // just extract its where clause.
                    // Example: selectCallForExist.sqlString:
                    // "SELECT PROJ_ID FROM PROJECT WHERE (LEADER_ID IS NULL)
                    whereWasPrinted = writeWhere(writer, selectCallForExist, call);
                    // The result is:
                    // "WHERE (LEADER_ID IS NULL)"
                } else {
                    writer.write(" WHERE EXISTS(");
                    // EXIST Example: selectCallForExist.sqlString:
                    // "SELECT t0.EMP_ID FROM EMPLOYEE t0, SALARY t1 WHERE (((t0.F_NAME LIKE 'a') AND (t1.SALARY = 0)) AND (t1.EMP_ID = t0.EMP_ID))"
                    writeSelect(writer, selectCallForExist, tableAliasInSelectCallForExist, call, session.getPlatform());
                    // closing bracket for EXISTS
                    writer.write(")");
                    // The result is (target table is SALARY):
                    // "WHERE EXISTS(SELECT t0.EMP_ID FROM EMPLOYEE t0, SALARY t1 WHERE (((t0.F_NAME LIKE 'a') AND (t1.SALARY = 0)) AND (t1.EMP_ID = t0.EMP_ID)) AND t1.EMP_ID = SALARY.EMP_ID)"
                }
                // Bug 301888 - DB2: UpdateAll/DeleteAll using WHERE EXIST fail.
                // If selectCallForExist has been explicitly set to not use binding then call should be set the same way.
                if(selectCallForExist.isUsesBindingSet() && !selectCallForExist.usesBinding(session)) {
                    call.setUsesBinding(false);
                }
            } else if (inheritanceExpression != null) {
                writer.write(" WHERE ");
                // Example: (PROJ_TYPE = 'L')
                ExpressionSQLPrinter printer = new ExpressionSQLPrinter(session, getTranslationRow(), call, false, getBuilder());
                printer.setWriter(writer);
                printer.printExpression(inheritanceExpression);
                // The result is:
                // "(PROJ_TYPE = 'L')"
            } else {
                whereWasPrinted = false;
            }

            if(selectCallForNotExist != null) {
                if(whereWasPrinted) {
                    writer.write(" AND");
                } else {
                    writer.write(" WHERE");
                }
                writer.write(" NOT EXISTS(");
                // NOT EXIST Example: selectCall.sqlString:
                // "SELECT t0.EMP_ID FROM EMPLOYEE t0, SALARY t1 WHERE (t1.EMP_ID = t0.EMP_ID)"
                writeSelect(writer, selectCallForNotExist, tableAliasInSelectCallForNotExist, call, session.getPlatform());
                // closing bracket for EXISTS
                writer.write(")");
                // The result is (target table is EMPLOYEE):
                // "WHERE NOT EXISTS(SELECT t0.EMP_ID FROM EMPLOYEE t0, SALARY t1 WHERE ((t1.EMP_ID = t0.EMP_ID)) AND t0.EMP_ID = EMPLOYEE.EMP_ID)"
            }

            call.setSQLString(writer.toString());

        } catch (IOException exception) {
            throw ValidationException.fileError(exception);
        }

        return call;
    }

    protected void writeSelect(Writer writer, SQLCall selectCall, String tableAliasInSelectCall, SQLCall call, DatasourcePlatform platform) throws IOException {
        String str = selectCall.getSQLString();
        writer.write(str);

        boolean hasWhereClause = str.toUpperCase().indexOf(" WHERE ") >= 0;

        // join aliased fields to original fields
        // Examples:
        //   table aliase provided: AND t0.EMP_ID = EMPLOYEE.EMP_ID
        //   table aliase not provided: AND EMP_ID = EMPLOYEE.EMP_ID
        for(int i=0; i < originalFields.size(); i++) {
            if(i==0 && !hasWhereClause) {
            // there is no where clause - should print WHERE
                writer.write(" WHERE ");
            } else {
                writer.write(" AND ");
            }
            if(tableAliasInSelectCall != null) {
                writer.write(tableAliasInSelectCall);
                writer.write('.');
            }
            writer.write(((DatabaseField)aliasedFields.elementAt(i)).getNameDelimited(platform));
            writer.write(" = ");
            writer.write(table.getQualifiedNameDelimited(platform));
            writer.write('.');
            writer.write(((DatabaseField)originalFields.elementAt(i)).getNameDelimited(platform));
        }

        // add parameters
        call.getParameters().addAll(selectCall.getParameters());
        call.getParameterTypes().addAll(selectCall.getParameterTypes());
    }

    protected boolean writeWhere(Writer writer, SQLCall selectCall, SQLCall call) throws IOException {
        String selectStr = selectCallForExist.getSQLString();

        int index = selectStr.toUpperCase().indexOf(" WHERE ");
        if(index < 0) {
            // no where clause - nothing to do
            return false;
        }

        // print the where clause
        String str = selectStr.substring(index);
        writer.write(str);

        // add parameters
        call.getParameters().addAll(selectCall.getParameters());
        call.getParameterTypes().addAll(selectCall.getParameterTypes());

        return true;
    }
}
