/*
 * 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.lang.reflect.Method;
import java.sql.*;
import java.util.Map;

import org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.sessions.*;
import org.eclipse.persistence.testing.framework.*;
import org.eclipse.persistence.testing.models.employee.domain.Address;

/**
 * This tests the use of batch writing for a large number of inserts.
 */
public class CacheStatementBatchWritingTest extends TransactionalTestCase {
    protected static int NUM_INSERTS = 102;
    protected boolean shouldCacheStatements;
    protected boolean shouldBindAllParams;

    public CacheStatementBatchWritingTest() {
        setDescription("Tests a large number of inserts using Batch Writing, verifies that statement cacheing is used");
    }

    @Override
    public void setup() {
        super.setup();
        this.shouldCacheStatements = getSession().getPlatform().shouldCacheAllStatements();
        this.shouldBindAllParams = getSession().getPlatform().shouldBindAllParameters();
        getSession().getPlatform().setShouldCacheAllStatements(true);
        getSession().getPlatform().setShouldBindAllParameters(true);
        //clear the statement cache for bug 245003
        ((DatabaseAccessor)getAbstractSession().getAccessor()).clearStatementCache((AbstractSession)getSession());
    }

    @Override
    public void reset() {
        super.reset();
        getSession().getPlatform().setShouldCacheAllStatements(this.shouldCacheStatements);
        getSession().getPlatform().setShouldBindAllParameters(this.shouldBindAllParams);
        ((DatabaseAccessor)getAbstractSession().getAccessor()).clearStatementCache((AbstractSession)getSession());
    }

    @Override
    public void test() {
        Address address;
        UnitOfWork uow = getSession().acquireUnitOfWork();
        for (int i = 0; i < NUM_INSERTS; i++) {
            address = new Address();
            address.setCity("city" + i);
            address.setProvince("province" + i);
            uow.registerObject(address);
        }
        uow.commit();
        //a little hack to force the remaining SQL to go to the Database
        ((DatabaseAccessor)uow.getParent().getAccessor()).getActiveBatchWritingMechanism(getAbstractSession()).executeBatchedStatements(uow.getParent());

        //get statement
        PreparedStatement statement = null;
        Map statementCache = null;
        String sql = getSession().getDescriptor(Address.class).getQueryManager().getInsertQuery().getSQLString();
        try {
            Method method = uow.getParent().getAccessor().getClass().getDeclaredMethod("getStatementCache");
            method.setAccessible(true);
            statementCache = (Map)method.invoke(uow.getParent().getAccessor(), new Object[] { });
            statement =  (PreparedStatement)statementCache.get(sql);
        } catch (Exception ex) {
            throw new TestErrorException("Failed to run test. Check java.policy file \"SupressAccessChecks\" perission required :" +
                                         ex.toString());
        }
        try {
            statement.close();
        } catch (SQLException ex) {
            throw new TestErrorException("Failed on modifying the statementCache");
        }
        //run again and verify the same statement.
        uow = getSession().acquireUnitOfWork();
        for (int i = 0; i < NUM_INSERTS; i++) {
            address = new Address();
            address.setCity("city" + (i + NUM_INSERTS));
            address.setProvince("province" + (i + NUM_INSERTS));
            uow.registerObject(address);
        }
        try {
            uow.commit();
            //a little hack to force the remaining SQL to go to the Database
            ((DatabaseAccessor)uow.getParent().getAccessor()).getActiveBatchWritingMechanism(getAbstractSession()).executeBatchedStatements(uow.getParent());
        } catch (Exception ex) {
            return; // if the exception is thrown then TopLink is caching correctly
        } finally {
            //removed the closed connection
            statementCache.remove(sql);
        }
        throw new TestErrorException("Statements were not cached correctly");
    }
}
