/*
 * Copyright (c) 2005, 2021 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 2005, 2015 SAP. 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:
//     SAP - initial API and implementation

package org.eclipse.persistence.testing.tests.wdf.jpa1.query;

import static jakarta.persistence.FlushModeType.AUTO;
import static jakarta.persistence.FlushModeType.COMMIT;
import static org.junit.Assert.assertEquals;

import java.sql.SQLException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import jakarta.persistence.EntityManager;
import jakarta.persistence.FlushModeType;
import jakarta.persistence.NoResultException;
import jakarta.persistence.NonUniqueResultException;
import jakarta.persistence.PersistenceException;
import jakarta.persistence.Query;

import org.eclipse.persistence.testing.framework.wdf.JPAEnvironment;
import org.eclipse.persistence.testing.framework.wdf.ToBeInvestigated;
import org.eclipse.persistence.testing.models.wdf.jpa1.employee.Department;
import org.eclipse.persistence.testing.models.wdf.jpa1.employee.Project;
import org.eclipse.persistence.testing.models.wdf.jpa1.types.BasicTypesFieldAccess;
import org.eclipse.persistence.testing.tests.wdf.jpa1.JPA1Base;
import org.junit.Test;

@SuppressWarnings("unchecked")
public class TestSimpleQuery extends JPA1Base {

    private final Set<Department> ALL_DEPARTMENTS = new HashSet<Department>();
    private final Department dep10 = new Department(10, "ten");
    private final Department dep20 = new Department(20, "twenty");

    private void init() throws SQLException {
        clearAllTables();
        ALL_DEPARTMENTS.add(dep10);
        ALL_DEPARTMENTS.add(dep20);
        JPAEnvironment env = getEnvironment();
        EntityManager em = env.getEntityManager();
        try {
            env.beginTransaction(em);
            em.persist(dep10);
            em.persist(dep20);
            env.commitTransactionAndClear(em);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testSelectAllDepartments() throws SQLException {
        init();
        EntityManager em = getEnvironment().getEntityManager();
        boolean extended = getEnvironment().usesExtendedPC();
        try {
            Query query = em.createQuery("select d from Department d");
            List result = query.getResultList();
            verify(result.size() == 2, "wrong resultcount");
            Iterator iter = result.iterator();
            Set<Department> actualSet = new HashSet<Department>();
            while (iter.hasNext()) {
                Department entity = (Department) iter.next();
                if (extended) {
                    verify(em.contains(entity), "entity manager doesn't contain result read outside transaction");
                } else {
                    verify(!em.contains(entity), "entity manager contains result read outside transaction");
                }
                actualSet.add(entity);
            }
            verify(ALL_DEPARTMENTS.equals(actualSet), "the sets are somehow different");
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testSelectDepartmentByName() throws SQLException {
        init();
        EntityManager em = getEnvironment().getEntityManager();
        boolean extended = getEnvironment().usesExtendedPC();
        try {
            Query query = em.createQuery("select d from Department d where d.name = ?1");
            query.setParameter(1, "twenty");
            List result = query.getResultList();
            Iterator iter = result.iterator();
            verify(iter.hasNext(), "row not found");
            Department entity = (Department) iter.next();
            if (extended) {
                verify(em.contains(entity), "entity manager doesn't contain result read outside transaction");
            } else {
                verify(!em.contains(entity), "entity manager contains result read outside transaction");
            }
            verify(entity.equals(dep20), " got wrong department");
            verify(!iter.hasNext(), "too many rows");
            query = em.createQuery("select distinct d from Department d where d.name = ?1");
            query.setParameter(1, "twenty");
            result = query.getResultList();
            iter = result.iterator();
            verify(iter.hasNext(), "row not found");
            entity = (Department) iter.next();
            if (extended) {
                verify(em.contains(entity), "entity manager doesn't contain result read outside transaction");
            } else {
                verify(!em.contains(entity), "entity manager contains result read outside transaction");
            }
            verify(entity.equals(dep20), " got wrong department");
            verify(!iter.hasNext(), "too many rows");
            query = em.createQuery("select d from Department d where d.name like 'twenty'");
            result = query.getResultList();
            iter = result.iterator();
            verify(iter.hasNext(), "row not found");
            entity = (Department) iter.next();
            if (extended) {
                verify(em.contains(entity), "entity manager doesn't contain result read outside transaction");
            } else {
                verify(!em.contains(entity), "entity manager contains result read outside transaction");
            }
            verify(entity.equals(dep20), " got wrong department");
            verify(!iter.hasNext(), "too many rows");
            query = em.createQuery("select d from Department d where d.name like 'twen%'");
            result = query.getResultList();
            iter = result.iterator();
            verify(iter.hasNext(), "row not found");
            entity = (Department) iter.next();
            if (extended) {
                verify(em.contains(entity), "entity manager doesn't contain result read outside transaction");
            } else {
                verify(!em.contains(entity), "entity manager contains result read outside transaction");
            }
            verify(entity.equals(dep20), " got wrong department");
            verify(!iter.hasNext(), "too many rows");
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testSelectInTransaction() throws SQLException {
        init();
        JPAEnvironment env = getEnvironment();
        EntityManager em = env.getEntityManager();
        try {
            env.beginTransaction(em);
            Query query = em.createQuery("select d from Department d");
            List result = query.getResultList();
            verify(result.size() == 2, "wrong resultcount");
            Iterator iter = result.iterator();
            while (iter.hasNext()) {
                Object entity = iter.next();
                verify(em.contains(entity), "entity manager doesn't contain result read inside transaction");
            }
            env.rollbackTransactionAndClear(em);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testIntIsNull() throws SQLException {
        init();
        JPAEnvironment env = getEnvironment();
        EntityManager em = env.getEntityManager();
        try {
            env.beginTransaction(em);
            Project project = new Project(null);
            em.persist(project);
            final int projectId = project.getId().intValue();
            env.commitTransactionAndClear(em);
            Query query = em.createQuery("select p from Project p where p.name IS NULL");
            List result = query.getResultList();
            verify(result.size() == 1, "wrong resultcount");
            Iterator iter = result.iterator();
            while (iter.hasNext()) {
                project = (Project) iter.next();
                verify(project.getId().intValue() == projectId, "wrong project");
            }
            query = em.createQuery("select distinct p from Project p where p.name IS NULL");
            result = query.getResultList();
            verify(result.size() == 1, "wrong resultcount");
            iter = result.iterator();
            while (iter.hasNext()) {
                project = (Project) iter.next();
                verify(project.getId().intValue() == projectId, "wrong project");
            }
        } finally {
            closeEntityManager(em);
        }
    }

    private void verifyComparisonPrepdicateResult(EntityManager em, String txt, int... ids) {
        Query query = em.createQuery(txt);
        List result = query.getResultList();
        Set<Integer> actual = new HashSet<Integer>();
        for (Object object : result) {
            BasicTypesFieldAccess fa = (BasicTypesFieldAccess) object;
            actual.add(Integer.valueOf(fa.getId()));
        }
        Set<Integer> expected = new HashSet<Integer>();
        for (int i : ids) {
            expected.add(Integer.valueOf(i));
        }
        verify(expected.equals(actual), "expecetd and actual sets are different for query >>" + txt + "<<");
    }

    @Test
    public void testComparisonPrepdicate() throws SQLException {
        init();
        JPAEnvironment env = getEnvironment();
        EntityManager em = env.getEntityManager();
        try {
            env.beginTransaction(em);
            BasicTypesFieldAccess fa = new BasicTypesFieldAccess(17);
            fa.setPrimitiveInt(17);
            em.persist(fa);
            fa = new BasicTypesFieldAccess(18);
            fa.setPrimitiveInt(18);
            em.persist(fa);
            fa = new BasicTypesFieldAccess(19);
            fa.setPrimitiveInt(19);
            em.persist(fa);
            fa = new BasicTypesFieldAccess(20);
            fa.setPrimitiveInt(20);
            em.persist(fa);
            env.commitTransactionAndClear(em);
            verifyComparisonPrepdicateResult(em, "Select Object(a) from BasicTypesFieldAccess a where a.primitiveInt = 17", 17);
            verifyComparisonPrepdicateResult(em, "Select Object(a) from BasicTypesFieldAccess a where a.primitiveInt > 17", 18,
                    19, 20);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testNamedQuery() throws SQLException {
        init();
        EntityManager em = getEnvironment().getEntityManager();
        boolean extended = getEnvironment().usesExtendedPC();
        try {
            Query query = em.createNamedQuery("getDepartmentByName"); // select d from Department d where d.name = ?1
            query.setParameter(1, "twenty");
            List result = query.getResultList();
            Iterator iter = result.iterator();
            verify(iter.hasNext(), "row not found");
            Department entity = (Department) iter.next();
            if (extended) {
                verify(em.contains(entity), "entity manager doesn't contain result read outside transaction");
            } else {
                verify(!em.contains(entity), "entity manager contains result read outside transaction");
            }
            verify(entity.equals(dep20), " got wrong department");
            verify(!iter.hasNext(), "too many rows");
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    @ToBeInvestigated
    public void testUndefinedNamedQuery() throws SQLException {
        init();
        EntityManager em = getEnvironment().getEntityManager();
        try {
            try {
                Query query = em.createNamedQuery("Hutzliputz");
                query.getResultList();
                flop("undefined query created");
            } catch (IllegalArgumentException e) {
            }
            try {
                Query query = em.createNamedQuery(null);
                query.getResultList();
                flop("undefined query created");
            } catch (IllegalArgumentException e) {
            }
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testNamedParameter() throws SQLException {
        init();
        EntityManager em = getEnvironment().getEntityManager();
        boolean extended = getEnvironment().usesExtendedPC();
        try {
            Query query = em.createQuery("select d from Department d where d.name = :name");
            query.setParameter("name", "twenty");
            List result = query.getResultList();
            Iterator iter = result.iterator();
            verify(iter.hasNext(), "row not found");
            Department entity = (Department) iter.next();
            if (extended) {
                verify(em.contains(entity), "entity manager doesn't contain result read outside transaction");
            } else {
                verify(!em.contains(entity), "entity manager contains result read outside transaction");
            }
            verify(entity.equals(dep20), " got wrong department");
            verify(!iter.hasNext(), "too many rows");
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testWrongParameter() throws SQLException {
        init();
        EntityManager em = getEnvironment().getEntityManager();
        try {
            try {
                Query query = em.createQuery("select d from Department d where d.name = :name");
                query.setParameter(1, "twenty");
                query.getResultList();
                flop("missing exception");
            } catch (RuntimeException e) {
            }
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testCachedQueryWithClear() throws SQLException {
        init();
        EntityManager em = getEnvironment().getEntityManager();
        try {
            Query query = em.createNamedQuery("getDepartmentCached");
            query.setParameter(1, "twenty");
            List<Department> result = query.getResultList();
            verify(result.size() == 1, "wrong result size");
            em.clear();
            result = query.getResultList();
            verify(result.size() == 1, "wrong result size");
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testCachedQueryWithoutClear() throws SQLException {
        init();
        EntityManager em = getEnvironment().getEntityManager();
        try {
            Query query = em.createNamedQuery("getDepartmentCached");
            query.setParameter(1, "twenty");
            List<Department> result = query.getResultList();
            verify(result.size() == 1, "wrong result size");
            result = query.getResultList();
            verify(result.size() == 1, "wrong result size");
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testUnCachedQuery() throws SQLException {
        init();
        EntityManager em = getEnvironment().getEntityManager();
        try {
            Query query = em.createNamedQuery("getDepartmentUnCached");
            query.setParameter(1, "twenty");
            List<Department> result = query.getResultList();
            verify(result.size() == 1, "wrong result size");
            result = query.getResultList();
            verify(result.size() == 1, "wrong result size");
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    @ToBeInvestigated
    public void testQueryStringNotValid() throws SQLException {
        // TODO enable test as soon as functionality is implemented
        init();
        EntityManager em = getEnvironment().getEntityManager();
        try {
            boolean caught = false;
            Query query;
            try {
                query = em.createQuery("this is not a valid query");
                try {
                    query.getResultList();
                } catch (PersistenceException ex) {
                    caught = true;
                }
            } catch (IllegalArgumentException e) {
                caught = true;
            }
            verify(caught,
                    "illegal query threw neither IllegalArgumentExceptionon create nor PersistenceException on getResultList");
            caught = false;
            try {
                query = em.createQuery((String) null);
                try {
                    query.getResultList();
                } catch (PersistenceException ex) {
                    caught = true;
                }
            } catch (IllegalArgumentException e) {
                caught = true;
            }
            verify(caught,
                    "null query threw neither IllegalArgumentExceptionon create nor PersistenceException on getResultList");
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testExecuteQueryMultipleTimesWithSameParameter() throws SQLException {
        init();
        EntityManager em = getEnvironment().getEntityManager();
        boolean extended = getEnvironment().usesExtendedPC();
        try {
            Query query = em.createQuery("select d from Department d where d.name = :name");
            query.setParameter("name", "twenty");
            List result = query.getResultList();
            result = query.getResultList();
            Iterator iter = result.iterator();
            verify(iter.hasNext(), "row not found");
            Department entity = (Department) iter.next();
            if (extended) {
                verify(em.contains(entity), "entity manager doesn't contain result read outside transaction");
            } else {
                verify(!em.contains(entity), "entity manager contains result read outside transaction");
            }
            verify(entity.equals(dep20), " got wrong department");
            verify(!iter.hasNext(), "too many rows");
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testExecuteQueryMultipleTimesWithDifferentParameter() throws SQLException {
        init();
        EntityManager em = getEnvironment().getEntityManager();
        boolean extended = getEnvironment().usesExtendedPC();
        try {
            Query query = em.createQuery("select d from Department d where d.name = ?1 and d.id = ?2");
            query.setParameter(1, "twenty");
            query.setParameter(2, Integer.valueOf(20));
            List result = query.getResultList();
            Iterator iter = result.iterator();
            verify(iter.hasNext(), "row not found");
            Department entity = (Department) iter.next();
            if (extended) {
                verify(em.contains(entity), "entity manager doesn't contain result read outside transaction");
            } else {
                verify(!em.contains(entity), "entity manager contains result read outside transaction");
            }
            verify(entity.equals(dep20), " got wrong department");
            verify(!iter.hasNext(), "too many rows");
            query.setParameter(1, "ten");
            query.setParameter(2, Integer.valueOf(10));
            result = query.getResultList();
            iter = result.iterator();
            verify(iter.hasNext(), "row not found");
            entity = (Department) iter.next();
            if (extended) {
                verify(em.contains(entity), "entity manager doesn't contain result read outside transaction");
            } else {
                verify(!em.contains(entity), "entity manager contains result read outside transaction");
            }
            verify(entity.equals(dep10), " got wrong department");
            verify(!iter.hasNext(), "too many rows");
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testSingleResultOk() throws SQLException {
        init();
        EntityManager em = getEnvironment().getEntityManager();
        boolean extended = getEnvironment().usesExtendedPC();
        try {
            Query query = em.createQuery("select d from Department d where d.name = :name");
            query.setParameter("name", "twenty");
            Object entity = query.getSingleResult();
            if (extended) {
                verify(em.contains(entity), "entity manager doesn't contain result read outside transaction");
            } else {
                verify(!em.contains(entity), "entity manager contains result read outside transaction");
            }
            verify(entity.equals(dep20), " got wrong department");
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testNoResult() throws SQLException {
        init();
        EntityManager em = getEnvironment().getEntityManager();
        try {
            Query query = em.createQuery("select d from Department d where d.name = :name");
            query.setParameter("name", "hutzliputz");
            try {
                query.getSingleResult();
                flop("missing NoResultException");
            } catch (NoResultException e) {
            }
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testNonUniqueResult() throws SQLException {
        init();
        EntityManager em = getEnvironment().getEntityManager();
        try {
            Query query = em.createQuery("select d from Department d");
            try {
                query.getSingleResult();
                flop("missing NonUniqueResultException");
            } catch (NonUniqueResultException e) {
            }
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testQueryWithFlush() throws SQLException {
        clearAllTables();
        JPAEnvironment env = getEnvironment();
        EntityManager em = env.getEntityManager();
        try {
            env.beginTransaction(em);
            em.persist(dep10);
            env.commitTransactionAndClear(em);
            env.beginTransaction(em);
            Department dep = em.find(Department.class, Integer.valueOf(10));
            dep.setName("newName");
            em.flush();
            Query query = em.createQuery("select d from Department d where d.name = :name");
            query.setParameter("name", "newName");
            Department entity = (Department) query.getSingleResult();
            verify(entity.getName().equals("newName"), " wrong department name");
            env.commitTransactionAndClear(em);
        } finally {
            closeEntityManager(em);
        }
    }

    private static boolean hasGetmaxRowsMethod() {
        try {
            return Query.class.getMethod("getMaxResults") != null;
        } catch (NoSuchMethodException e) {
            return false;
        }
    }

    private void verifyRowCount(Query query, int maxRows, int startPos, int expected) throws SecurityException, NoSuchMethodException {
        query.setMaxResults(maxRows);
        query.setFirstResult(startPos);

        if (hasGetmaxRowsMethod()) {
            assertEquals(query.getMaxResults(), maxRows);
            assertEquals(query.getFirstResult(), startPos);
        }

        int count = query.getResultList().size();
        verify(count == expected, "wrong row count: " + count);

        if (hasGetmaxRowsMethod()) {
            assertEquals(query.getMaxResults(), maxRows);
            assertEquals(query.getFirstResult(), startPos);
        }
    }

    @Test
    public void testMaxResult() throws SQLException, SecurityException, NoSuchMethodException {
        clearAllTables();
        JPAEnvironment env = getEnvironment();
        EntityManager em = env.getEntityManager();
        try {
            env.beginTransaction(em);
            for (int i = 0; i < 10; i++) {
                em.persist(new Project("P" + i));
            }
            env.commitTransaction(em);
            em.clear();
            Query query = em.createQuery("select p from Project p");
            verifyRowCount(query, 5, 0, 5);
            verifyRowCount(query, 10, 0, 10);
            verifyRowCount(query, 15, 0, 10);
            verifyRowCount(query, 5, 5, 5);
            verifyRowCount(query, 10, 5, 5);
            verifyRowCount(query, 15, 5, 5);
            verifyRowCount(query, 5, 7, 3);
            verifyRowCount(query, 10, 7, 3);
            verifyRowCount(query, 15, 7, 3);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testMaxResultUnlimited() throws SQLException, SecurityException, NoSuchMethodException {
        clearAllTables();
        JPAEnvironment env = getEnvironment();
        EntityManager em = env.getEntityManager();
        try {
            env.beginTransaction(em);
            for (int i = 0; i < 10; i++) {
                em.persist(new Project("P" + i));
            }
            env.commitTransaction(em);
            em.clear();
            Query query = em.createQuery("select p from Project p");
            verifyRowCount(query, Integer.MAX_VALUE, 0, 10);
            verifyRowCount(query, Integer.MAX_VALUE, 5, 5);
            verifyRowCount(query, Integer.MAX_VALUE, 7, 3);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testPagingDefaults() throws SQLException {
        if (!hasGetmaxRowsMethod()) {
            return;
        }
        JPAEnvironment env = getEnvironment();
        EntityManager em = env.getEntityManager();
        try {
            Query query = em.createQuery("select p from Project p");
            assertEquals(0, query.getFirstResult());
            assertEquals(Integer.MAX_VALUE, query.getMaxResults());
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testFlushMode() throws SQLException {
        testFlushMode(AUTO, null);
        testFlushMode(AUTO, AUTO);
        testFlushMode(AUTO, COMMIT);
        testFlushMode(COMMIT, null);
        testFlushMode(COMMIT, AUTO);
        testFlushMode(COMMIT, COMMIT);
    }

    private void testFlushMode(FlushModeType flushModeEM, FlushModeType flushModeQuery) throws SQLException {
        init();
        JPAEnvironment env = getEnvironment();
        EntityManager em = env.getEntityManager();
        try {
            env.beginTransaction(em);
            Query query = em.createQuery("select d from Department d where d.name = 'updated'");
            if (flushModeEM == COMMIT) {
                em.setFlushMode(COMMIT);
            }
            verify(em.getFlushMode() == flushModeEM, "wrong flushMode");
            if (flushModeQuery != null) {
                query.setFlushMode(flushModeQuery);
            }
            boolean flushExpected = isFlushExpected(flushModeEM, flushModeQuery);
            Department dep = em.find(Department.class, Integer.valueOf(10));
            dep.setName("updated");
            List result = query.getResultList();
            if (flushExpected) {
                verify(result.size() == 1, "wrong number of rows: " + result.size());
            } else {
                verify(result.size() == 0, "wrong number of rows: " + result.size());
            }
            env.commitTransaction(em);
        } finally {
            closeEntityManager(em);
        }
    }

    private boolean isFlushExpected(FlushModeType flushModeEM, FlushModeType flushModeQuery) {
        if (flushModeQuery == null) {
            if (flushModeEM == COMMIT) {
                return false;
            } else {
                return true;
            }
        } else if (flushModeQuery == COMMIT) {
            return false;
        } else if (flushModeQuery == AUTO) {
            return true;
        }
        throw new IllegalArgumentException("Illegal flushMode(s): flushModeEM = " + flushModeEM + ", flushModeQuery = "
                + flushModeQuery);
    }

    @Test
    public void testTransactionBoundaries() throws SQLException {
        init();
        JPAEnvironment env = getEnvironment();
        EntityManager em = env.getEntityManager();
        boolean extended = env.usesExtendedPC();
        boolean failureExpected = false;
        if (!extended) {
            failureExpected = true;
        }
        try {
            // create query outside transaction
            Query query = em.createQuery("select d from Department d where d.name = :name");
            query.setParameter("name", "twenty");
            List result = query.getResultList();
            verify(result.size() == 1, "wrong number of rows: " + result.size());
            verify(result.get(0).equals(dep20), "got wrong department");
            // execute again
            result = query.getResultList();
            verify(result.size() == 1, "wrong number of rows: " + result.size());
            verify(result.get(0).equals(dep20), "got wrong department");
            // execute inside transaction
            env.beginTransaction(em);
            try {
                result = query.getResultList();
                verify(result.size() == 1, "wrong number of rows: " + result.size());
                verify(result.get(0).equals(dep20), "got wrong department");
            } catch (PersistenceException e) {
                if (!failureExpected) {
                    throw e;
                }
            }
            env.rollbackTransaction(em);
            // create query inside transaction
            env.beginTransaction(em);
            query = em.createQuery("select d from Department d where d.name = :name");
            query.setParameter("name", "twenty");
            result = query.getResultList();
            verify(result.size() == 1, "wrong number of rows: " + result.size());
            verify(result.get(0).equals(dep20), "got wrong department");
            env.commitTransaction(em);
            // execute outside transaction
            try {
                result = query.getResultList();
                verify(result.size() == 1, "wrong number of rows: " + result.size());
                verify(result.get(0).equals(dep20), "got wrong department");
            } catch (IllegalStateException e) {
                if (!failureExpected) {
                    throw e;
                }
            }
            // execute inside new transaction
            env.beginTransaction(em);
            try {
                result = query.getResultList();
                verify(result.size() == 1, "wrong number of rows: " + result.size());
                verify(result.get(0).equals(dep20), "got wrong department");
            } catch (IllegalStateException e) {
                if (!failureExpected) {
                    throw e;
                }
            }
            env.rollbackTransaction(em);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testBooleanParameter() {
        EntityManager em = getEnvironment().getEntityManager();
        JPAEnvironment env = getEnvironment();
        try {
            env.beginTransaction(em);
            BasicTypesFieldAccess fieldAccess = new BasicTypesFieldAccess();
            fieldAccess.setId(1);
            fieldAccess.setPrimitiveBoolean(true);
            em.persist(fieldAccess);
            fieldAccess = new BasicTypesFieldAccess();
            fieldAccess.setId(2);
            fieldAccess.setPrimitiveBoolean(false);
            em.persist(fieldAccess);
            env.commitTransactionAndClear(em);
            Query query = em.createQuery("select b from BasicTypesFieldAccess b where b.primitiveBoolean = ?1");
            query.setParameter(1, Boolean.TRUE);
            List list = query.getResultList();
            Iterator iterator = list.iterator();
            verify(iterator.hasNext(), "no rows");
            BasicTypesFieldAccess value = (BasicTypesFieldAccess) iterator.next();
            verify(value.getId() == 1, "wrong id: " + value.getId());
            verify(!iterator.hasNext(), "too many rows");
        } finally {
            closeEntityManager(em);
        }
    }
}
