/*
 * TestSQLQueries.java
 *
 * Created on October 5, 2006, 4:59 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

/*
 * 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.jdbc.query;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ByteArrayOutputStream;
import java.util.*;
import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
import org.apache.openjpa.jdbc.meta.ClassMapping;
import org.apache.openjpa.jdbc.meta.MappingRepository;
import org.apache.openjpa.jdbc.sql.DBDictionary;
import org.apache.openjpa.kernel.OpenJPAStateManager;
import org.apache.openjpa.persistence.OpenJPAQuery;

import org.apache.openjpa.persistence.jdbc.common.apps.*;


import java.lang.annotation.Annotation;
import junit.framework.*;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import org.apache.openjpa.persistence.OpenJPAEntityManagerFactory;
import org.apache.openjpa.persistence.OpenJPAEntityManager;
import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI;
import org.apache.openjpa.persistence.OpenJPAPersistence;


public class TestSQLQueries extends org.apache.openjpa.persistence.jdbc.kernel.BaseJDBCTest{
     
    
    /** Creates a new instance of TestSQLQueries */
    public TestSQLQueries(String name) 
    {
    	super(name);
    }
    
    public TestSQLQueries() 
    {}
    
    private String _tableName = null;
    private String _fullTableName = null;
    private String _pkColName = null;
    private String _intColName = null;
    private String _stringColName = null;
    private String _relColName = null;
    
    public void setUp() {
       deleteAll(RuntimeTest1.class);
        
        RuntimeTest1 pc1 = new RuntimeTest1("1", 1);
        RuntimeTest1 pc2 = new RuntimeTest1("2", 2);
        pc1.setSelfOneOne(pc2);
        
        OpenJPAEntityManager pm =(OpenJPAEntityManager)currentEntityManager();
        startTx(pm);;
        pm.persist(pc1);
        endTx(pm);;
        
        JDBCConfiguration conf = (JDBCConfiguration) ((OpenJPAEntityManagerFactorySPI) pm).getConfiguration();
        DBDictionary dict = conf.getDBDictionaryInstance();
        MappingRepository repos = conf.getMappingRepositoryInstance();
        ClassMapping mapping = repos.getMapping(RuntimeTest1.class,
                pm.getClassLoader(), true);
        
        _tableName = mapping.getTable().getName();
        _fullTableName = dict.getFullName(mapping.getTable(), false);
        _pkColName = mapping.getTable().getPrimaryKey().
                getColumns()[0].getName();
        _intColName = mapping.getFieldMapping("intField").
                getColumns()[0].getName();
        _stringColName = mapping.getFieldMapping("stringField").
                getColumns()[0].getName();
        _relColName = mapping.getFieldMapping("selfOneOne").
                getColumns()[0].getName();
        
        pm.close();
    }
    
    public void testStarQuery() {
        OpenJPAEntityManager pm =(OpenJPAEntityManager)currentEntityManager();
        OpenJPAQuery q = pm.createQuery("javax.jdo.query.SQL",
                "select * from " + _fullTableName + " order by " + _intColName);
        q.setResultClass(RuntimeTest1.class);
        Iterator itr = ((Collection) q.getCandidateCollection()).iterator();
        assertTrue(itr.hasNext());
        assertEquals("1", ((RuntimeTest1) itr.next()).getStringField());
        assertTrue(itr.hasNext());
        assertEquals("2", ((RuntimeTest1) itr.next()).getStringField());
        assertFalse(itr.hasNext());
        q.closeAll();
        pm.close();
    }
    
    public void testCompiledQuery()
    throws Exception {
        OpenJPAEntityManager pm =(OpenJPAEntityManager)currentEntityManager();
        OpenJPAQuery q = pm.createQuery("javax.jdo.query.SQL",
                "select * from " + _fullTableName + " order by " + _intColName);
        q.setResultClass(RuntimeTest1.class);
        
        //FIXME jthomas
        //q = pm.createQuery(roundtrips(q, false));
        Iterator itr = ((Collection) q.getCandidateCollection()).iterator();
        assertTrue(itr.hasNext());
        assertEquals("1", ((RuntimeTest1) itr.next()).getStringField());
        assertTrue(itr.hasNext());
        assertEquals("2", ((RuntimeTest1) itr.next()).getStringField());
        assertFalse(itr.hasNext());
        q.closeAll();
        pm.close();
    }
    
    public void testCompiledLanguageQuery()
    throws Exception {
        OpenJPAEntityManager pm =(OpenJPAEntityManager)currentEntityManager();
        OpenJPAQuery q = pm.createQuery("javax.jdo.query.SQL",
                "select * from " + _fullTableName + " order by " + _intColName);
        q.setResultClass(RuntimeTest1.class);
        
        //FIXME jthomas
        //q = pm.createQuery("javax.jdo.query.SQL", roundtrips(q, false));
        Iterator itr = ((Collection) q.getCandidateCollection()).iterator();
        assertTrue(itr.hasNext());
        assertEquals("1", ((RuntimeTest1) itr.next()).getStringField());
        assertTrue(itr.hasNext());
        assertEquals("2", ((RuntimeTest1) itr.next()).getStringField());
        assertFalse(itr.hasNext());
        q.closeAll();
        pm.close();
    }
    
    public void testTableStarQuery() {
        OpenJPAEntityManager pm =(OpenJPAEntityManager)currentEntityManager();
        OpenJPAQuery q = pm.createQuery("javax.jdo.query.SQL",
                "select " + _tableName + ".* from " + _fullTableName + " order by "
                + _intColName);
        q.setResultClass(RuntimeTest1.class);
        Iterator itr = ((Collection) q.getCandidateCollection()).iterator();
        assertTrue(itr.hasNext());
        assertEquals("1", ((RuntimeTest1) itr.next()).getStringField());
        assertTrue(itr.hasNext());
        assertEquals("2", ((RuntimeTest1) itr.next()).getStringField());
        assertFalse(itr.hasNext());
        q.closeAll();
        pm.close();
    }
    
    public void testColumnQuery() {
        OpenJPAEntityManager pm =(OpenJPAEntityManager)currentEntityManager();
        OpenJPAQuery q = pm.createQuery("javax.jdo.query.SQL",
                "select " + _pkColName + ", " + _intColName + ", " + _stringColName
                + " from " + _fullTableName + " order by " + _intColName);
        q.setResultClass(RuntimeTest1.class);
        Iterator itr = ((Collection) q.getCandidateCollection()).iterator();
        assertTrue(itr.hasNext());
        assertEquals("1", ((RuntimeTest1) itr.next()).getStringField());
        assertTrue(itr.hasNext());
        assertEquals("2", ((RuntimeTest1) itr.next()).getStringField());
        assertFalse(itr.hasNext());
        q.closeAll();
        pm.close();
    }
    
    public void testJoinQuery() {
        OpenJPAEntityManager pm =(OpenJPAEntityManager)currentEntityManager();
        OpenJPAQuery q = pm.createQuery("javax.jdo.query.SQL",
                "select t0.* from " + _fullTableName + " t0, "
                + _fullTableName + " t1 where t0." + _relColName + " = t1."
                + _pkColName + " and t1." + _intColName + " = 2");
        q.setResultClass(RuntimeTest1.class);
        Iterator itr = ((Collection) q.getCandidateCollection()).iterator();
        assertTrue(itr.hasNext());
        assertEquals("1", ((RuntimeTest1) itr.next()).getStringField());
        assertFalse(itr.hasNext());
        q.closeAll();
        pm.close();
    }
    
    public void testParameters() {
        OpenJPAEntityManager pm =(OpenJPAEntityManager)currentEntityManager();
        OpenJPAQuery q = pm.createQuery("javax.jdo.query.SQL",
                "select * from " + _fullTableName + " where 'foo' = ? and "
                + _intColName + " = ?");
        q.setResultClass(RuntimeTest1.class);
        //FIXME jthomas
        /*Iterator itr = ((Collection) q.execute("foo", new Integer(2))).
                iterator();
        assertTrue(itr.hasNext());
        assertEquals("2", ((RuntimeTest1) itr.next()).getStringField());
        assertFalse(itr.hasNext());
         */
        q.closeAll();
        
        Map params = new HashMap();
        params.put(new Integer(1), "foo");
        params.put(new Integer(2), new Integer(2));
        //FIXME jthomas
        /*itr = ((Collection) q.executeWithMap(params)).iterator();
        assertTrue(itr.hasNext());
        assertEquals("2", ((RuntimeTest1) itr.next()).getStringField());
        assertFalse(itr.hasNext());
         */
        q.closeAll();
        pm.close();
    }
    
    public void testOnlySelectedFieldsLoaded() {
        OpenJPAEntityManager pm =(OpenJPAEntityManager)currentEntityManager();
        OpenJPAQuery q = pm.createQuery("javax.jdo.query.SQL",
                "select " + _pkColName + ", " + _intColName + ", " + _stringColName
                + " from " + _fullTableName + " order by " + _intColName);
        q.setResultClass(RuntimeTest1.class);
        Iterator itr = ((Collection) q.getCandidateCollection()).iterator();
        assertTrue(itr.hasNext());
        RuntimeTest1 pc = (RuntimeTest1) itr.next();
        OpenJPAStateManager sm = getStateManager(pc, pm);
        assertTrue(sm.getLoaded().get(sm.getMetaData().
                getField("intField").getIndex()));
        assertTrue(sm.getLoaded().get(sm.getMetaData().
                getField("stringField").getIndex()));
        assertFalse(sm.getLoaded().get(sm.getMetaData().
                getField("longField").getIndex()));
        assertEquals("1", pc.getStringField());
        assertFalse(sm.getLoaded().get(sm.getMetaData().
                getField("longField").getIndex()));
        q.closeAll();
        pm.close();
    }
    
    public void testSingleColumnClasslessQuery() {
        OpenJPAEntityManager pm =(OpenJPAEntityManager)currentEntityManager();
        OpenJPAQuery q = pm.createQuery("javax.jdo.query.SQL",
                "select " + _stringColName + " from " + _fullTableName
                + " order by " + _stringColName);
        Iterator itr = ((Collection) q.getCandidateCollection()).iterator();
        assertTrue(itr.hasNext());
        assertEquals("1", itr.next());
        assertTrue(itr.hasNext());
        assertEquals("2", itr.next());
        assertFalse(itr.hasNext());
        q.closeAll();
        
        q.setResultClass(Object[].class);
        itr = ((Collection) q.getCandidateCollection()).iterator();
        assertTrue(itr.hasNext());
        Object[] vals = (Object[]) itr.next();
        assertEquals(1, vals.length);
        assertEquals("1", vals[0]);
        assertTrue(itr.hasNext());
        vals = (Object[]) itr.next();
        assertEquals(1, vals.length);
        assertEquals("2", vals[0]);
        assertFalse(itr.hasNext());
        q.closeAll();
        
        pm.close();
    }
    
    public void testMultiColumnClasslessQuery() {
        OpenJPAEntityManager pm =(OpenJPAEntityManager)currentEntityManager();
        OpenJPAQuery q = pm.createQuery("javax.jdo.query.SQL",
                "select " + _intColName + ", " + _stringColName + " from "
                + _fullTableName + " order by " + _stringColName);
        Iterator itr = ((Collection) q.getCandidateCollection()).iterator();
        assertTrue(itr.hasNext());
        Object[] vals = (Object[]) itr.next();
        assertEquals(2, vals.length);
        assertEquals(1, ((Number) vals[0]).intValue());
        assertEquals("1", vals[1]);
        assertTrue(itr.hasNext());
        vals = (Object[]) itr.next();
        assertEquals(2, vals.length);
        assertEquals(2, ((Number) vals[0]).intValue());
        assertEquals("2", vals[1]);
        assertFalse(itr.hasNext());
        q.closeAll();
        pm.close();
    }
    
    public void testResultClass() {
        OpenJPAEntityManager pm =(OpenJPAEntityManager)currentEntityManager();
        OpenJPAQuery q = pm.createQuery("javax.jdo.query.SQL",
                "select * from " + _fullTableName + " order by " + _intColName);
        q.setResultClass(RuntimeTest1.class);
        q.setResultClass(Holder.class);
        Iterator itr = ((Collection) q.getCandidateCollection()).iterator();
        assertTrue(itr.hasNext());
        Holder holder = (Holder) itr.next();
        assertEquals(0, holder.I);
        assertNull(holder.S);
        assertNotNull(holder.pc);
        assertEquals("1", holder.pc.getStringField());
        assertTrue(itr.hasNext());
        holder = (Holder) itr.next();
        assertEquals(0, holder.I);
        assertNull(holder.S);
        assertNotNull(holder.pc);
        assertEquals("2", holder.pc.getStringField());
        assertFalse(itr.hasNext());
        q.closeAll();
        pm.close();
    }
    
    public void testClasslessProjection() {
        OpenJPAEntityManager pm =(OpenJPAEntityManager)currentEntityManager();
        OpenJPAQuery q = pm.createQuery("javax.jdo.query.SQL",
                "select " + _intColName + " as I, " + _stringColName + " as S from "
                + _fullTableName + " order by " + _intColName);
        q.setResultClass(Holder.class);
        Iterator itr = ((Collection) q.getCandidateCollection()).iterator();
        assertTrue(itr.hasNext());
        Holder holder = (Holder) itr.next();
        assertNull(holder.pc);
        assertEquals(1, holder.I);
        assertEquals("1", holder.S);
        assertTrue(itr.hasNext());
        holder = (Holder) itr.next();
        assertNull(holder.pc);
        assertEquals(2, holder.I);
        assertEquals("2", holder.S);
        assertFalse(itr.hasNext());
        q.closeAll();
        pm.close();
    }
    
    /**
     * Manual test to see if a relation will be eagerly loaded when SQL
     * containing enough information is run. This is not run as part of
     * the unit tests since we don't know if this behavior should be
     * really expected to work or not.
     */
    public void relationLoadedTest() {
       deleteAll(AttachD.class);
       deleteAll(AttachA.class);
        
        AttachD d = new AttachD();
        AttachA a = new AttachA();
        d.setA(a);
        
        OpenJPAEntityManager pm =(OpenJPAEntityManager)currentEntityManager();
        pm.getTransaction().begin();
        pm.persist(d);
        pm.getTransaction().commit();
        pm.close();
        
        JDBCConfiguration conf = (JDBCConfiguration) ((OpenJPAEntityManagerFactorySPI) pm).getConfiguration();
        DBDictionary dict = conf.getDBDictionaryInstance();
        MappingRepository repos = conf.getMappingRepositoryInstance();
        
        ClassMapping mappingA = repos.getMapping(AttachD.class,
                pm.getClassLoader(), true);
        String tableNameA = mappingA.getTable().getName();
        String fullTableNameA = dict.getFullName(mappingA.getTable(), false);
        String relColNameA = mappingA.getFieldMapping("a").
                getColumns()[0].getName();
        
        ClassMapping mappingD = repos.getMapping(AttachA.class,
                pm.getClassLoader(), true);
        String tableNameD = mappingD.getTable().getName();
        String fullTableNameD = dict.getFullName(mappingD.getTable(), false);
        String pkColNameD = mappingD.getTable().getPrimaryKey().
                getColumns()[0].getName();
        
        pm = (OpenJPAEntityManager)currentEntityManager();
        OpenJPAQuery q = pm.createQuery("javax.jdo.query.SQL",
                "select t0.*, t1.* from "
                + fullTableNameA + " t0, "
                + fullTableNameD + " t1 "
                + "where t0." + relColNameA + " = t1." + pkColNameD);
        
        // even the exact same SQL that Kodo generates will not
        // eagerly load the relation
        /*
          q = pm.newQuery ("javax.jdo.query.SQL",
              "SELECT t1.ID, t1.TYP, t1.VERSN, t1.ADBL, t1.AINT, "
              + "t1.ASTR, t1.BDBL, t1.BINT, t1.BSTR, t1.CDBL, t1.CINT, "
              + "t1.CSTR, t0.DDBL, t0.DINT, t0.DSTR "
              + "FROM ATTACHD t0 LEFT OUTER JOIN ATTACHA t1 ON t0.A = t1.ID");
         */
        
        q.setResultClass(AttachD.class);
        Iterator itr = ((Collection) q.getCandidateCollection()).iterator();
        assertTrue(itr.hasNext());
        
        d = (AttachD) itr.next();
        // d.getDstr ();
        
        OpenJPAStateManager sm = getStateManager(d, pm);
        assertTrue(sm.getLoaded().
                get(sm.getMetaData().getField("a").getIndex()));
        assertNotNull(d.getA());
        assertFalse(itr.hasNext());
        
        q.closeAll();
        pm.close();
    }
    
    public static class Holder {
        
        public RuntimeTest1 pc;
        public int I;
        public String S;
        
        public void setRuntimeTest1(RuntimeTest1 pc) {
            this.pc = pc;
        }
    }
    
    public static void main(String[] args)
    throws Exception {
        // main ();
        
        new TestSQLQueries().relationLoadedTest();
    }
    
    private static Object roundtrips(Object orig, boolean validateEquality)
    throws IOException, ClassNotFoundException {
        assertNotNull(orig);
        
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream(bout);
        out.writeObject(orig);
        ByteArrayInputStream bin = new ByteArrayInputStream(
                bout.toByteArray());
        ObjectInputStream in = new ObjectInputStream(bin);
        Object result = in.readObject();
        
        if (validateEquality) {
            assertEquals(orig.hashCode(), result.hashCode());
            assertEquals(orig, result);
        }
        
        return result;
    }
    
}
