/*
 * Copyright (c) 1998, 2021 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.helper;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Vector;

import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.internal.databaseaccess.Accessor;
import org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor;
import org.eclipse.persistence.internal.databaseaccess.DatabaseCall;
import org.eclipse.persistence.internal.databaseaccess.DatabasePlatform;
import org.eclipse.persistence.internal.expressions.ForUpdateClause;
import org.eclipse.persistence.internal.expressions.SQLSelectStatement;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.platform.database.OraclePlatform;
import org.eclipse.persistence.queries.Call;
import org.eclipse.persistence.queries.DatabaseQuery;
import org.eclipse.persistence.queries.ObjectBuildingQuery;
import org.eclipse.persistence.queries.WriteObjectQuery;

/**
 * INTERNAL:
 * <p><b>Purpose</b>:LOBValueWriter is used to write a large size of object into an Oracle
 * CLOB/BLOB column through Oracle LOB Locator. It's a work-around object for the well-known 4k write
 * limits on an Oracle thin driver.
 *
 * <p><b>Responsibilities</b>:<ul>
 * <li> Build the Oracle empty lob method call string for the insert call.
 * <li> Build the minimal SELECT call to retrieve the locator.
 * <li> Write the lob value through the locator.
 * <li> Resolve the multiple table INSERT/SELECT orders.
 * <li> Resolve the nested unit of work commit issue.
 * </ul>
 *
 * @author King Wang
 * @since TopLink/Java 5.0. July 2002.
 */
public class LOBValueWriter {
    //DatabaseCalls still to be processed
    private Collection<DatabaseCall> calls = null;
    private Accessor accessor;
    private boolean isNativeConnectionRequired;

    /**
     * This is the default constructor for the class.
     *
     * Bug 2804663 - Each DatabaseAccessor will now hold on to its own instance
     * of this class, hence a singleton pattern is not applicable.
     */
    public LOBValueWriter(Accessor accessor) {
        this.accessor = accessor;
        DatabasePlatform platform = ((DatabaseAccessor)accessor).getPlatform();
        this.isNativeConnectionRequired = platform.isOracle() && ((OraclePlatform)platform).isNativeConnectionRequiredForLobLocator();
    }

    protected void buildAndExecuteCall(DatabaseCall dbCall, AbstractSession session) {
        DatabaseQuery query = dbCall.getQuery();
        if (!query.isWriteObjectQuery()) {
            //if not writequery, should not go through the locator writing..
            return;
        }
        WriteObjectQuery writeQuery = (WriteObjectQuery)query;
        writeQuery.setAccessor(accessor);
        //build a select statement form the query
        SQLSelectStatement selectStatement = buildSelectStatementForLocator(writeQuery, dbCall, session);

        //then build a call from the statement
        DatabaseCall call = buildCallFromSelectStatementForLocator(selectStatement, writeQuery, dbCall, session);

        accessor.executeCall(call, call.getQuery().getTranslationRow(), session);
    }

    /**
    * Fetch the locator(s) from the result set and write LOB value to the table
    */
    public void fetchLocatorAndWriteValue(DatabaseCall dbCall, Object resultSet) throws SQLException {
        Enumeration<DatabaseField> enumFields = dbCall.getContexts().getFields().elements();
        Enumeration<?> enumValues = dbCall.getContexts().getValues().elements();
        AbstractSession executionSession = dbCall.getQuery().getSession().getExecutionSession(dbCall.getQuery());
        while (enumFields.hasMoreElements()) {
            DatabaseField field = enumFields.nextElement();
            Object value = enumValues.nextElement();

            //write the value through the locator
            executionSession.getPlatform().writeLOB(field, value, (ResultSet)resultSet, executionSession);
        }
    }

    /**
    * Build the select statement for selecting the locator
    */
    private SQLSelectStatement buildSelectStatementForLocator(WriteObjectQuery writeQuery, DatabaseCall call, AbstractSession session) {
        SQLSelectStatement selectStatement = new SQLSelectStatement();
        Vector<DatabaseTable> tables = writeQuery.getDescriptor().getTables();
        selectStatement.setTables(tables);
        //rather than get ALL fields from the descriptor, only use the LOB-related fields to build the minimal SELECT statement.
        selectStatement.setFields(call.getContexts().getFields());
        //the where clause setting here is sufficient if the object does not map to multiple tables.
        selectStatement.setWhereClause(writeQuery.getDescriptor().getObjectBuilder().buildPrimaryKeyExpressionFromObject(writeQuery.getObject(), session));
        //need pessimistic locking for the locator select
        selectStatement.setLockingClause(ForUpdateClause.newInstance(ObjectBuildingQuery.LOCK));

        if (tables.size() > 1) {
            //the primary key expression from the primary table
            Expression expression = selectStatement.getWhereClause();

            //additional join from the non-primary tables
            Expression additionalJoin = writeQuery.getDescriptor().getQueryManager().getAdditionalJoinExpression();
            if (additionalJoin != null) {
                expression = expression.and(additionalJoin);
            }

            //where clause now contains extra joins across all tables
            selectStatement.setWhereClause(expression);
        }

        //normalize the statement at the end, such as assign alias to all tables, and build sorting statement
        selectStatement.normalize(session, writeQuery.getDescriptor());
        return selectStatement;
    }

    /**
    * Build the sql call from the select statement for selecting the locator
    */
    private DatabaseCall buildCallFromSelectStatementForLocator(SQLSelectStatement selectStatement, WriteObjectQuery writeQuery, DatabaseCall dbCall, AbstractSession session) {
        DatabaseCall call = selectStatement.buildCall(session);
        // Locator LOB must not be wrapped (WLS wraps LOBs).
        call.setIsNativeConnectionRequired(this.isNativeConnectionRequired);

        //the LOB context must be passed into the new call object
        call.setContexts(dbCall.getContexts());
        //need to explicitly define one row return, otherwise, EL assumes multiple rows return and confuses the accessor
        call.returnOneRow();
        //the query object has to be set in order to access to the platform and login objects
        call.setQuery(writeQuery);
        // prepare it
        call.prepare(session);
        //finally do the translation
        call.translate(writeQuery.getTranslationRow(), writeQuery.getModifyRow(), session);
        return call;
    }

    // Building of SELECT statements is no longer done in DatabaseAccessor.basicExecuteCall
    // for updates because DatabaseCall.isUpdateCall() can't recognize update in case
    // StoredProcedureCall is used. Therefore in all cases: insert(single or multiple tables)
    // and update the original (insert and update) calls are saved
    // and both building and executing of SELECT statements postponed until
    // buildAndExecuteSelectCalls method is called.

    /**
    * Add original (insert or update) call to the collection
    */
    public void addCall(Call call) {
        if (calls == null) {
            //use lazy initialization
            calls = new ArrayList<>(2);
        }
        calls.add((DatabaseCall) call);
    }

    // Bug 3110860: RETURNINGPOLICY-OBTAINED PK CAUSES LOB TO BE INSERTED INCORRECTLY
    // The deferred locator SELECT calls should be generated and executed after ReturningPolicy
    // merges PK obtained from the db into the object held by the query.
    // That's why original (insert or update) calls are saved,
    // and both building and executing of SELECT statements postponed until
    // this method is called.

    /**
    * Build and execute the deferred select calls.
    */
    public void buildAndExecuteSelectCalls(AbstractSession session) {
        if ((calls == null) || calls.isEmpty()) {
            //no deferred select calls (it means no locator is required)
            return;
        }

        //all INSERTs have been executed, time to execute the SELECTs
        try {
            for (Iterator<DatabaseCall> callIt = calls.iterator(); callIt.hasNext();) {
                DatabaseCall dbCall = callIt.next();
                buildAndExecuteCall(dbCall, session);
            }
        } finally {
            //after executing all select calls, need to empty the collection.
            //this is necessary in the nested unit of work cases.
            calls.clear();
        }
    }
}
