gt:         q = QueryCloner.cloneQuery(q);
context: package org.intermine.objectstore.intermine;
  
  /*
   * Copyright (C) 2002-2014 FlyMine
   *
   * This code may be freely distributed and modified under the
   * terms of the GNU Lesser General Public Licence.  This should
   * be distributed with the code.  See the LICENSE file for more
   * information or http://www.gnu.org/copyleft/lesser.html.
   *
   */
  
  import java.lang.reflect.UndeclaredThrowableException;
  import java.sql.Connection;
  import java.sql.ResultSet;
  import java.sql.SQLException;
  import java.sql.Statement;
  import java.util.ArrayList;
  import java.util.Arrays;
  import java.util.Collections;
  import java.util.ConcurrentModificationException;
  import java.util.HashMap;
  import java.util.HashSet;
  import java.util.Iterator;
  import java.util.LinkedHashSet;
  import java.util.Map;
  import java.util.Set;
  
  import junit.framework.Test;
  
  import org.intermine.model.InterMineObject;
  import org.intermine.model.testmodel.Address;
  import org.intermine.model.testmodel.CEO;
  import org.intermine.model.testmodel.Company;
  import org.intermine.model.testmodel.Department;
  import org.intermine.model.testmodel.Employee;
  import org.intermine.model.testmodel.Manager;
  import org.intermine.model.testmodel.Types;
  import org.intermine.objectstore.ObjectStore;
  import org.intermine.objectstore.ObjectStoreAbstractImplTestCase;
  import org.intermine.objectstore.ObjectStoreException;
  import org.intermine.objectstore.ObjectStoreFactory;
  import org.intermine.objectstore.ObjectStoreQueriesTestCase;
  import org.intermine.objectstore.query.BagConstraint;
  import org.intermine.objectstore.query.ClassConstraint;
  import org.intermine.objectstore.query.ConstraintOp;
  import org.intermine.objectstore.query.ConstraintSet;
  import org.intermine.objectstore.query.ContainsConstraint;
  import org.intermine.objectstore.query.ObjectStoreBag;
  import org.intermine.objectstore.query.Query;
  import org.intermine.objectstore.query.QueryClass;
  import org.intermine.objectstore.query.QueryCloner;
  import org.intermine.objectstore.query.QueryCollectionReference;
  import org.intermine.objectstore.query.QueryField;
  import org.intermine.objectstore.query.QueryValue;
  import org.intermine.objectstore.query.Results;
  import org.intermine.objectstore.query.ResultsRow;
  import org.intermine.objectstore.query.SimpleConstraint;
  import org.intermine.objectstore.query.SingletonResults;
  import org.intermine.objectstore.query.iql.IqlQuery;
  import org.intermine.sql.query.Constraint;
  
  public class ObjectStoreInterMineImplTest extends ObjectStoreAbstractImplTestCase
  {
      public static void oneTimeSetUp() throws Exception {
          os = (ObjectStoreInterMineImpl) ObjectStoreFactory.getObjectStore("os.unittest");
          ObjectStoreAbstractImplTestCase.oneTimeSetUp();
      }
  
      public ObjectStoreInterMineImplTest(String arg) throws Exception {
          super(arg);
      }
  
      public static Test suite() {
          return buildSuite(ObjectStoreInterMineImplTest.class);
      }
  
      public void testLargeOffset() throws Exception {
          Query q = new Query();
          QueryClass qc = new QueryClass(Address.class);
          q.addFrom(qc);
          q.addToSelect(qc);
          Query q2 = QueryCloner.cloneQuery(q);
          SingletonResults r = os.executeSingleton(q, 2, true, true, true);
          InterMineObject o = (InterMineObject) r.get(5);
          SqlGenerator.registerOffset(q2, 6, ((ObjectStoreInterMineImpl) os).getSchema(), ((ObjectStoreInterMineImpl) os).db, o.getId(), new HashMap());
          SingletonResults r2 = os.executeSingleton(q2, 2, true, true, true);
  
          Query q3 = QueryCloner.cloneQuery(q);
          SqlGenerator.registerOffset(q3, 5, ((ObjectStoreInterMineImpl) os).getSchema(), ((ObjectStoreInterMineImpl) os).db, o.getId(), new HashMap());
          SingletonResults r3 = new SingletonResults(q3, os, ObjectStore.SEQUENCE_IGNORE);
          r3.setBatchSize(2);
  
          assertTrue(r == r2);
          assertTrue(r != r3);
          assertTrue(r2 != r3);
          assertEquals(r, r2);
          assertTrue(!r.equals(r3));
      }
  
      public void testLargeOffset2() throws Exception {
          Employee nullEmployee = new Employee();
          nullEmployee.setAge(26);
          nullEmployee.setName(null);
          try {
              storeDataWriter.store(nullEmployee);
              Query q = new Query();
              QueryClass qc = new QueryClass(Employee.class);
              q.addFrom(qc);
              q.addToSelect(qc);
              q.addToOrderBy(new QueryField(qc, "name"));
              Query q2 = QueryCloner.cloneQuery(q);
              SingletonResults r = os.executeSingleton(q, 2, true, true, true);
              Employee o = (Employee) r.get(2);
              SqlGenerator.registerOffset(q2, 3, ((ObjectStoreInterMineImpl) os).getSchema(), ((ObjectStoreInterMineImpl) os).db, o.getName(), new HashMap());
              SingletonResults r2 = os.executeSingleton(q2, 2, true, true, true);
  
              Query q3 = QueryCloner.cloneQuery(q);
              SqlGenerator.registerOffset(q3, 2, ((ObjectStoreInterMineImpl) os).getSchema(), ((ObjectStoreInterMineImpl) os).db, o.getName(), new HashMap());
              SingletonResults r3 = new SingletonResults(q3, os, ObjectStore.SEQUENCE_IGNORE);
              r3.setBatchSize(2);
  
              assertTrue(r == r2);
              assertTrue(r != r3);
              assertTrue(r2 != r3);
              assertEquals(r, r2);
              assertTrue(!r.equals(r3));
          } finally {
              storeDataWriter.delete(nullEmployee);
          }
      }
  
      /*public void testLargeOffset3() throws Exception {
          // This is to test the indexing of large offset queries, so it needs to do a performance test.
          Set toDelete = new HashSet();
          try {
              long start = System.currentTimeMillis();
              storeDataWriter.beginTransaction();
              for (int i = 0; i < 10105; i++) {
                  Employee e = new Employee();
                  String name = "Fred_";
                  if (i < 10000) {
                      name += "0";
                  }
                  if (i < 1000) {
                      name += "0";
                  }
                  if (i < 100) {
                      name += "0";
                  }
                  if (i < 10) {
                      name += "0";
                  }
                  e.setName(name + i);
                  e.setAge(i + 1000000);
                  storeDataWriter.store(e);
                  toDelete.add(e);
              }
              for (int i = 10105; i < 10205; i++) {
                  Employee e = new Employee();
                  e.setAge(i + 1000000);
                  storeDataWriter.store(e);
                  toDelete.add(e);
              }
              storeDataWriter.commitTransaction();
              Connection c = null;
              try {
                  c = ((ObjectStoreWriterInterMineImpl) storeDataWriter).getConnection();
                  c.createStatement().execute("ANALYSE");
              } finally {
                  if (c != null) {
                      ((ObjectStoreWriterInterMineImpl) storeDataWriter).releaseConnection(c);
                  }
              }
              long now = System.currentTimeMillis();
              System.out.println("Took " + (now - start) + "ms to insert data");
              start = now;
              Query q = new Query();
              QueryClass qc = new QueryClass(Employee.class);
              QueryField f = new QueryField(qc, "name");
              q.addFrom(qc);
              q.addToSelect(f);
              q.setDistinct(false);
              SingletonResults r = os.executeSingleton(q);
              r.setBatchSize(10);
              assertEquals("Fred_00000", r.get(6));
              now = System.currentTimeMillis();
              System.out.println("Took " + (now - start) + "ms to find first row");
              long timeA = now - start;
              start = now;
              assertEquals("Fred_10015", r.get(10021));
              now = System.currentTimeMillis();
              System.out.println("Took " + (now - start) + "ms to find row 10015");
              long timeB = now - start;
              start = now;
              assertEquals("Fred_10035", r.get(10041));
              now = System.currentTimeMillis();
              System.out.println("Took " + (now - start) + "ms to find row 10035");
              long timeC = now - start;
              start = now;
              assertNull(r.get(10141));
              now = System.currentTimeMillis();
              System.out.println("Took " + (now - start) + "ms to find row 10135");
              long timeD = now - start;
  
              q = QueryCloner.cloneQuery(q);
              ((ObjectStoreInterMineImpl) os).precompute(q);
              r = os.executeSingleton(q);
              r.setBatchSize(10);
              now = System.currentTimeMillis();
              System.out.println("Took " + (now - start) + "ms to precompute results");
              start = now;
              assertEquals("Fred_00000", r.get(6));
              now = System.currentTimeMillis();
              System.out.println("Took " + (now - start) + "ms to find first precomputed row");
              long timePA = now - start;
              start = now;
              assertEquals("Fred_10015", r.get(10021));
              now = System.currentTimeMillis();
              System.out.println("Took " + (now - start) + "ms to find precomputed row 10015");
              long timePB = now - start;
              start = now;
              assertEquals("Fred_10035", r.get(10041));
              now = System.currentTimeMillis();
              System.out.println("Took " + (now - start) + "ms to find precomputed row 10035");
              long timePC = now - start;
              start = now;
              assertNull(r.get(10141));
              now = System.currentTimeMillis();
              System.out.println("Took " + (now - start) + "ms to find precomputed row 10135");
              long timePD = now - start;
              assertTrue("Row 6 found in " + timeA + "ms", timeA < 30);
              assertTrue("Row 10015 found in " + timeB + "ms", timeB > 30);
              assertTrue("Row 10035 found in " + timeC + "ms", timeC < 22);
              assertTrue("Row 10135 found in " + timeD + "ms", timeD < 15);
              assertTrue("Precomputed row 6 found in " + timePA + "ms", timePA < 30);
              assertTrue("Precomputed row 10015 found in " + timePB + "ms", timePB > 30);
              //TODO: This should pass - it's Postgres being thick.
              //assertTrue("Precomputed row 10035 found in " + timePC + "ms", timePC < 15);
              assertTrue("Precomputed row 10135 found in " + timePD + "ms", timePD < 15);
          } finally {
              if (storeDataWriter.isInTransaction()) {
                  storeDataWriter.abortTransaction();
              }
              long start = System.currentTimeMillis();
              storeDataWriter.beginTransaction();
              Iterator iter = toDelete.iterator();
              while (iter.hasNext()) {
                  Employee e = (Employee) iter.next();
                  storeDataWriter.delete(e);
              }
              storeDataWriter.commitTransaction();
              long now = System.currentTimeMillis();
              System.out.println("Took " + (now - start) + "ms to remove data");
              start = now;
              Connection c = null;
              try {
                  c = ((ObjectStoreWriterInterMineImpl) storeDataWriter).getConnection();
                  c.createStatement().execute("VACUUM FULL ANALYSE");
              } finally {
                  if (c != null) {
                      ((ObjectStoreWriterInterMineImpl) storeDataWriter).releaseConnection(c);
                  }
              }
              now = System.currentTimeMillis();
              System.out.println("Took " + (now - start) + "ms to VACUUM FULL ANALYSE");
          }
      }*/
  
      public void testPrecompute() throws Exception {
          Query q = new Query();
          QueryClass qc1 = new QueryClass(Department.class);
          QueryClass qc2 = new QueryClass(Employee.class);
          q.addFrom(qc1);
          q.addFrom(qc2);
          q.addToSelect(qc1);
          q.addToSelect(qc2);
          QueryField f1 = new QueryField(qc1, "name");
          QueryField f2 = new QueryField(qc2, "name");
          q.addToSelect(f1);
          q.addToSelect(f2);
          q.setConstraint(new ContainsConstraint(new QueryCollectionReference(qc1, "employees"), ConstraintOp.CONTAINS, qc2));
          q.setDistinct(false);
          Set indexes = new LinkedHashSet();
          indexes.add(qc1);
          indexes.add(f1);
          indexes.add(f2);
          String tableName = ((ObjectStoreInterMineImpl) os).precompute(q, indexes, "test").get(0);
          Connection con = null;
          Map indexMap = new HashMap();
          try {
              con = ((ObjectStoreInterMineImpl) os).getConnection();
              Statement s = con.createStatement();
              ResultSet r = s.executeQuery("SELECT * FROM pg_indexes WHERE tablename = '" + tableName + "'");
              while (r.next()) {
                  indexMap.put(r.getString("indexname"), r.getString("indexdef"));
              }
          } finally {
              if (con != null) {
                  ((ObjectStoreInterMineImpl) os).releaseConnection(con);
              }
          }
          Map expectedIndexMap = new HashMap();
          expectedIndexMap.put(tableName + "_orderby_field", "CREATE INDEX " + tableName + "_orderby_field ON " + tableName + " USING btree (orderby_field)");
          expectedIndexMap.put(tableName + "_a1_id__lower_a3____lower_a4__", "CREATE INDEX " + tableName + "_a1_id__lower_a3____lower_a4__ ON " + tableName + " USING btree (a1_id, lower(a3_), lower(a4_))");
          expectedIndexMap.put(tableName + "_lower_a3__", "CREATE INDEX " + tableName + "_lower_a3__ ON " + tableName + " USING btree (lower(a3_))");
          expectedIndexMap.put(tableName + "_lower_a3___text_pattern_ops", "CREATE INDEX " + tableName + "_lower_a3___text_pattern_ops ON " + tableName + " USING btree (lower(a3_) text_pattern_ops)");
          expectedIndexMap.put(tableName + "_lower_a4__", "CREATE INDEX " + tableName + "_lower_a4__ ON " + tableName + " USING btree (lower(a4_))");
          expectedIndexMap.put(tableName + "_lower_a4___text_pattern_ops", "CREATE INDEX " + tableName + "_lower_a4___text_pattern_ops ON " + tableName + " USING btree (lower(a4_) text_pattern_ops)");
          assertEquals(expectedIndexMap, indexMap);
      }
  
      public void testGoFaster() throws Exception {
          Query q = new IqlQuery("SELECT Company, Department FROM Company, Department WHERE Department.company CONTAINS Company", "org.intermine.model.testmodel").toQuery();
          try {
              ((ObjectStoreInterMineImpl) os).goFaster(q);
              Results r = os.execute(q);
              r.get(0);
              assertEquals(3, r.size());
          } finally {
              ((ObjectStoreInterMineImpl) os).releaseGoFaster(q);
          }
      }
  
      public void testPrecomputeWithNullsInOrder() throws Exception {
          Types t1 = new Types();
          t1.setIntObjType(null);
          t1.setLongObjType(new Long(234212354));
          t1.setName("fred");
          storeDataWriter.store(t1);
          Types t2 = new Types();
          t2.setIntObjType(new Integer(278652));
          t2.setLongObjType(null);
          t2.setName("fred");
          storeDataWriter.store(t2);
  
          Query q = new Query();
          QueryClass qc = new QueryClass(Types.class);
          QueryField into = new QueryField(qc, "intObjType");
          QueryField longo = new QueryField(qc, "longObjType");
          q.addFrom(qc);
          q.addToSelect(into);
          q.addToSelect(longo);
          q.addToSelect(qc);
          q.setDistinct(false);
          ((ObjectStoreInterMineImpl) os).precompute(q, "test");
  
          Results r = os.execute(q, 1, true, true, true);
          SqlGenerator.registerOffset(q, 1, ((ObjectStoreInterMineImpl) os).getSchema(), ((ObjectStoreInterMineImpl) os).db, new Integer(100000), new HashMap());
  
          ResultsRow row = (ResultsRow) r.get(1);
          InterMineObject o = (InterMineObject) row.get(2);
          assertEquals("Expected " + t2.toString() + " but got " + o.toString(), t2.getId(), o.getId());
          row = (ResultsRow) r.get(2);
          o = (InterMineObject) row.get(2);
          assertEquals("Expected " + t1.toString() + " but got " + o.toString(), t1.getId(), o.getId());
  
          q.setConstraint(new SimpleConstraint(into, ConstraintOp.GREATER_THAN, new QueryValue(new Integer(100000))));
  