/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.openjpa.persistence.query;

import java.util.Iterator;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.Query;

import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
import org.apache.openjpa.jdbc.sql.DBDictionary;
import org.apache.openjpa.jdbc.sql.DerbyDictionary;
import org.apache.openjpa.jdbc.sql.SolidDBDictionary;
import org.apache.openjpa.persistence.simple.AllFieldTypes;
import org.apache.openjpa.persistence.test.SingleEMTestCase;

/**
 * <p>Tests grouping and having capabilities.</p>
 *
 * @author Abe White
 */
public abstract class GroupingTestCase
    extends SingleEMTestCase {

    protected abstract void prepareQuery(Query q);

    @Override
    public void setUp() {
        super.setUp(AllFieldTypes.class, CLEAR_TABLES,
            "openjpa.Compatibility", "JPQL=warn");

        AllFieldTypes pc1 = new AllFieldTypes();
        AllFieldTypes pc2 = new AllFieldTypes();
        AllFieldTypes pc3 = new AllFieldTypes();
        AllFieldTypes pc4 = new AllFieldTypes();

        // pc1 and pc2, pc3 and pc4 grouped on intField, shortField
        pc1.setIntField(1);
        pc1.setShortField((short) -1);
        pc2.setIntField(1);
        pc2.setShortField((short) -1);
        pc3.setIntField(2);
        pc3.setShortField((short) -2);
        pc4.setIntField(2);
        pc4.setShortField((short) -2);

        // pc1 and pc2 grouped on stringField
        pc1.setStringField("abc");
        pc2.setStringField("acd");
        pc3.setStringField("def");
        pc4.setStringField("efg");

        // pc2 and pc3 grouped on byteField
        pc2.setByteField((byte) 1);
        pc3.setByteField((byte) 1);
        pc1.setByteField((byte) 0);
        pc4.setByteField((byte) 2);

        // longField is unique id
        pc1.setLongField(1L);
        pc2.setLongField(2L);
        pc3.setLongField(3L);
        pc4.setLongField(4L);

        // set up some relations
        pc1.setSelfOneOne(pc4);
        pc2.setSelfOneOne(pc3);
        pc3.setSelfOneOne(pc2);
        pc4.setSelfOneOne(pc1);

        // if variable testing, set up some 1-Ms instead of the 1-1s above
        if (getName().startsWith("testVariable")) {
            pc1.setSelfOneOne(pc1);
            pc2.setSelfOneOne(pc1);
            pc1.getSelfOneMany().add(pc1);
            pc1.getSelfOneMany().add(pc2);

            pc3.setSelfOneOne(pc3);
            pc4.setSelfOneOne(pc3);
            pc3.getSelfOneMany().add(pc3);
            pc3.getSelfOneMany().add(pc4);
        }

        EntityManager em = emf.createEntityManager();
        em.getTransaction().begin();
        em.persist(pc1);
        em.persist(pc2);
        em.persist(pc3);
        em.persist(pc4);
        em.getTransaction().commit();
        em.close();
    }

    public void testSimpleGroup() {
        Query q = em.createQuery("select o.intField from AllFieldTypes o " +
            "group by o.intField order by o.intField asc");
        prepareQuery(q);
        List res = q.getResultList();
        assertEquals(2, res.size());
        Iterator itr = res.iterator();
        assertEquals(1, itr.next());
        assertEquals(2, itr.next());
        assertTrue(!itr.hasNext());
    }

    public void testOrderByAggregate() {
        // this is an extension of JPQL
        Query q = em.createQuery("select sum(o.shortField) " +
            "from AllFieldTypes o"
            + " group by o.intField order by sum(o.shortField) asc");
        prepareQuery(q);
        // this might fail in MySQL/MariaDB
        List res = q.getResultList();
        assertEquals(2, res.size());
        Iterator itr = res.iterator();
        assertEquals((long) -4, itr.next());
        assertEquals((long) -2, itr.next());
        assertTrue(!itr.hasNext());
    }

    public void testCompoundGroupSame() {
        Query q = em.createQuery("select o.intField from AllFieldTypes o " +
            "group by o.intField, o.shortField order by o.shortField asc");
        prepareQuery(q);
        List res = q.getResultList();
        assertEquals(2, res.size());
        Iterator itr = res.iterator();
        assertEquals(2, itr.next());
        assertEquals(1, itr.next());
        assertTrue(!itr.hasNext());
    }

    public void testCompoundGroupDifferent() {
        Query q = em.createQuery("select o.intField from AllFieldTypes o " +
            "group by o.intField, o.byteField order by o.intField asc");
        prepareQuery(q);
        List res = q.getResultList();
        assertEquals(4, res.size());
        Iterator itr = res.iterator();
        assertEquals(1, itr.next());
        assertEquals(1, itr.next());
        assertEquals(2, itr.next());
        assertEquals(2, itr.next());
        assertTrue(!itr.hasNext());
    }

    public void testDifferentGroupLengths() {
        Query q = em.createQuery("select o.byteField from AllFieldTypes o"
            + " group by o.byteField order by o.byteField asc");
        prepareQuery(q);
        List res = q.getResultList();
        assertEquals(3, res.size());
        Iterator itr = res.iterator();
        assertEquals((byte) 0, itr.next());
        assertEquals((byte) 1, itr.next());
        assertEquals((byte) 2, itr.next());
        assertTrue(!itr.hasNext());
    }

    public void testGroupRelationField() {
        Query q = em.createQuery("select o.selfOneOne.intField " +
            "from AllFieldTypes o group by o.selfOneOne.intField " +
            "order by o.selfOneOne.intField asc");
        prepareQuery(q);
        List res = q.getResultList();
        assertEquals(2, res.size());
        Iterator itr = res.iterator();
        assertEquals(1, itr.next());
        assertEquals(2, itr.next());
        assertTrue(!itr.hasNext());
    }

    public void testSubstringInGroupBy() {
        DBDictionary dict = ((JDBCConfiguration)emf.getConfiguration()).getDBDictionaryInstance();
        if (dict instanceof SolidDBDictionary)
            return;

        // this is an extension of JPQL
        Query q = em.createQuery("select substring(o.stringField, 1, 1), " +
            "count(o) from AllFieldTypes o " +
            "group by substring(o.stringField, 1, 1)");
        prepareQuery(q);
        List res = q.getResultList();
        assertEquals(3, res.size());

        q = em.createQuery("select substring(o.stringField, 1, 2), count(o) " +
            "from AllFieldTypes o group by substring(o.stringField, 1, 2)");
        prepareQuery(q);
        res = q.getResultList();
        assertEquals(4, res.size());
    }

    public void testGroupedAggregate() {
        Query q = em.createQuery("select count(o) from AllFieldTypes o " +
            "group by o.byteField order by o.byteField asc");
        prepareQuery(q);
        List res = q.getResultList();
        assertEquals(3, res.size());
        Iterator itr = res.iterator();
        assertEquals(1L, itr.next());
        assertEquals(2L, itr.next());
        assertEquals(1L, itr.next());
        assertTrue(!itr.hasNext());
    }

    public void testGroupedRelationAggregate() {
        Query q = em.createQuery("select count(o), max(o.selfOneOne.longField)"
            + " from AllFieldTypes o group by o.intField"
            + " order by o.intField asc");
        List res = q.getResultList();
        assertEquals(2, res.size());
        Iterator itr = res.iterator();
        Object[] o = (Object[]) itr.next();
        assertEquals(2L, o[0]);
        assertEquals(4L, o[1]);
        o = (Object[]) itr.next();
        assertEquals(2L, o[0]);
        assertEquals(2L, o[1]);
        assertTrue(!itr.hasNext());
    }

    public void testGroupedMixedProjection() {
        Query q = em.createQuery("select count(o), o.shortField " +
            "from AllFieldTypes o group by o.intField, o.shortField " +
            "order by o.intField asc");
        prepareQuery(q);
        List res = q.getResultList();
        assertEquals(2, res.size());
        Iterator itr = res.iterator();
        Object[] o = (Object[]) itr.next();
        assertEquals(2L, o[0]);
        assertEquals((short) -1, o[1]);
        o = (Object[]) itr.next();
        assertEquals(2L, o[0]);
        assertEquals((short) -2, o[1]);
        assertTrue(!itr.hasNext());
    }

    public void testSimpleHaving() {
        Query q = em.createQuery("select o.intField from AllFieldTypes o " +
            "group by o.intField having o.intField < 2");
        prepareQuery(q);
        assertEquals(1, q.getSingleResult());
    }

    public void testAggregateHaving() {
        Query q = em.createQuery("select o.byteField from AllFieldTypes o " +
            "group by o.byteField having count(o) > 1");
        prepareQuery(q);
        assertEquals((byte) 1, q.getSingleResult());
    }

    public void testMixedHaving() {
        Query q = em.createQuery("select o.byteField from AllFieldTypes o " +
            "group by o.byteField having count(o) > 1 or o.byteField = 0 " +
            "order by o.byteField asc");
        prepareQuery(q);
        List res = q.getResultList();
        assertEquals(2, res.size());
        Iterator itr = res.iterator();
        assertEquals((byte) 0, itr.next());
        assertEquals((byte) 1, itr.next());
        assertTrue(!itr.hasNext());
    }

    public void testVariableGroup() {
        Query q = em.createQuery("select max(other.longField) " +
            "from AllFieldTypes o, AllFieldTypes other " +
            "where other member of o.selfOneMany " +
            "group by other.intField order by other.intField asc");
        prepareQuery(q);
        List res = q.getResultList();
        assertEquals(2, res.size());
        Iterator itr = res.iterator();
        assertEquals(2L, itr.next());
        assertEquals(4L, itr.next());
        assertTrue(!itr.hasNext());
    }

    public void testVariableHaving() {
        JDBCConfiguration conf = (JDBCConfiguration) em.getConfiguration();
        DBDictionary dict = conf.getDBDictionaryInstance();
        if (dict instanceof DerbyDictionary) {
            // This test fails on Derby 10.5.3.0, so just skip it...
            return;
        }

        Query q = em.createQuery("select max(o.longField), other.byteField " +
            "from AllFieldTypes o, AllFieldTypes other " +
            "where other member of o.selfOneMany " +
            "group by other.byteField having sum(other.intField) = 2");
        prepareQuery(q);
        assertEquals(3L, ((Object[])q.getSingleResult())[0]);
    }
}
