/*
 * 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.testing.tests.feature;

import java.util.List;

import org.eclipse.persistence.descriptors.DescriptorQueryManager;
import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.queries.DataModifyQuery;
import org.eclipse.persistence.sessions.UnitOfWork;

/**
 * Bug 214910:  Add query timeout support to batched update queries (Oracle DB 9.0.1+)</p>
 * Test the query timeout feature in batch queries.
 * For data queries , a queryTimeout on the largest DatabaseQuery of the batch will be used.
 * For object queries, a queryTimeout on the largest DescriptorQueryManager (parent) or DatabaseQuery
 * of the batch will be used.
 */
public abstract class QueryTimeoutBatchDatabaseQueryTest extends QueryTimeoutBatchTestCase {

    @Override
    protected  int getParentQueryTimeout() { return 2; }
    @Override
    protected  int getChildQueryTimeout() { return 2; }

    @Override
    protected String getQuerySQLPostfix() {
        return ", SUM(e.address_id) as version from address e, address b, address b, address c, address c, address c, address b";
    }

    @Override
    public void test() {
        UnitOfWork uow = null;
        try {
            uow = setupPlatform();
            initializeDatabase(uow);
            // Get new UOW
            uow = getSession().acquireUnitOfWork();

            int queryCount = 0;
            for (int i = 0; i < getNumberOfInserts(); i++) {
                DataModifyQuery query = new DataModifyQuery();
                queryCount++;
                // The following insert will take around 5.2 seconds per row (the last (address c) is significant)
                // insert into employee (emp_id, version) SELECT 40003, SUM(e.address_id) as version from address e, address b, address b, address c, address c;
                StringBuffer sBuffer = new StringBuffer(getQuerySQLPrefix());
                sBuffer.append(getCurrentIDSequence() + i);
                //sBuffer.append(i);
                sBuffer.append(getQuerySQLPostfix());

                query.setSQLString(sBuffer.toString());
                // set different query timeouts - the largest will be used
                query.setQueryTimeout(getChildQueryTimeout());
                //session.executeQuery(query);
                StringBuilder queryName = new StringBuilder("query");
                queryName.append(i);

                // Force the last query to execute
                if(queryCount == getNumberOfInserts()) {
                    query.setForceBatchStatementExecution(true);
                    // clear last queryTimeout - so we pick up one from a previous appendCall
                    //query.setQueryTimeout(0);
                }
                uow.addQuery(queryName.toString(), query);
                uow.executeQuery(query);
            }

            uow.commit();
        } catch (Exception e) {
            /** Throws
             * Internal Exception: java.sql.SQLException: ORA-01013: user requested cancel of current operation
             */
            //e.printStackTrace();
            //System.err.print(e.getMessage());
            if (e instanceof DatabaseException) {
                limitExceeded = true;
                vendorErrorCodeEncountered = ((DatabaseException)e).getDatabaseErrorCode();
                //System.out.println("test completed with timeout of " + getChildQueryTimeout() + " seconds and exception: " + vendorErrorCodeEncountered);
            } else {
                //e.printStackTrace();
            }
            // Release transaction mutex
            ((AbstractSession)uow).rollbackTransaction();
        } finally {
            resetPlatform();
        }
    }

    @Override
    protected List  registerObjects(UnitOfWork uow) {
        return null;
    }

    /**
     * This is a callback from the object loop in registerObjects that allows the test
     * to set a timeout globally on the DescriptorQueryManager
     */
    @Override
    public void setDescriptorLevelQueryTimeout(DescriptorQueryManager queryManager) {
    }

    /**
     * This is a callback from the object loop in registerObjects that allows the test
     * to set a timeout on individual queries
     */
    @Override
    public void setQueryLevelQueryTimeout(UnitOfWork uow, Object object) {
    }

}
