You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by aa...@apache.org on 2014/11/02 08:09:52 UTC

[04/48] Installing Maven Failsafe Plugin

http://git-wip-us.apache.org/repos/asf/cayenne/blob/e42c376c/cayenne-server/src/test/java/org/apache/cayenne/query/SQLTemplateTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/query/SQLTemplateTest.java b/cayenne-server/src/test/java/org/apache/cayenne/query/SQLTemplateTest.java
deleted file mode 100644
index 31a8fcf..0000000
--- a/cayenne-server/src/test/java/org/apache/cayenne/query/SQLTemplateTest.java
+++ /dev/null
@@ -1,211 +0,0 @@
-/*****************************************************************
- *   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.cayenne.query;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.cayenne.CayenneRuntimeException;
-import org.apache.cayenne.DataRow;
-import org.apache.cayenne.access.DataContext;
-import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.map.DataMap;
-import org.apache.cayenne.test.jdbc.DBHelper;
-import org.apache.cayenne.unit.di.server.ServerCase;
-import org.apache.cayenne.unit.di.server.UseServerRuntime;
-import org.apache.cayenne.util.Util;
-
-@UseServerRuntime(ServerCase.TESTMAP_PROJECT)
-public class SQLTemplateTest extends ServerCase {
-
-    @Inject
-    private DataContext context;
-
-    @Inject
-    private DBHelper dbHelper;
-
-    @Override
-    protected void setUpAfterInjection() throws Exception {
-        dbHelper.deleteAll("PAINTING_INFO");
-        dbHelper.deleteAll("PAINTING");
-        dbHelper.deleteAll("ARTIST_EXHIBIT");
-        dbHelper.deleteAll("ARTIST_GROUP");
-        dbHelper.deleteAll("ARTIST");
-    }
-
-    public void testSQLTemplateForDataMap() {
-        DataMap testDataMap = context.getEntityResolver().getDataMap("tstmap");
-        SQLTemplate q1 = new SQLTemplate(testDataMap, "SELECT * FROM ARTIST", true);
-        List<DataRow> result = context.performQuery(q1);
-        assertEquals(0, result.size());
-    }
-
-    public void testSQLTemplateForDataMapWithInsert() {
-        DataMap testDataMap = context.getEntityResolver().getDataMap("tstmap");
-        String sql = "INSERT INTO ARTIST VALUES (15, 'Surikov', null)";
-        SQLTemplate q1 = new SQLTemplate(testDataMap, sql, true);
-        context.performNonSelectingQuery(q1);
-
-        SQLTemplate q2 = new SQLTemplate(testDataMap, "SELECT * FROM ARTIST", true);
-        List<DataRow> result = context.performQuery(q2);
-        assertEquals(1, result.size());
-    }
-
-    public void testSQLTemplateForDataMapWithInsertException() {
-        DataMap testDataMap = context.getEntityResolver().getDataMap("tstmap");
-        String sql = "INSERT INTO ARTIST VALUES (15, 'Surikov', null)";
-        SQLTemplate q1 = new SQLTemplate(testDataMap, sql, true);
-        context.performNonSelectingQuery(q1);
-
-        SQLTemplate q2 = new SQLTemplate(testDataMap, "SELECT * FROM ARTIST", false);
-        boolean gotRuntimeException = false;
-        try {
-            context.performQuery(q2);
-        } catch (CayenneRuntimeException e) {
-            gotRuntimeException = true;
-        }
-        assertTrue("If fetchingDataRows is false and ObjectEntity not set, shoulb be thrown exception",
-                gotRuntimeException);
-    }
-
-    public void testColumnNameCapitalization() {
-        SQLTemplate q1 = new SQLTemplate("E1", "SELECT");
-        assertSame(CapsStrategy.DEFAULT, q1.getColumnNamesCapitalization());
-        q1.setColumnNamesCapitalization(CapsStrategy.UPPER);
-        assertEquals(CapsStrategy.UPPER, q1.getColumnNamesCapitalization());
-    }
-
-    public void testQueryWithParameters() {
-        SQLTemplate q1 = new SQLTemplate("E1", "SELECT");
-        q1.setName("QName");
-
-        Query q2 = q1.queryWithParameters(Collections.EMPTY_MAP);
-        assertNotNull(q2);
-        assertNotSame(q1, q2);
-        assertTrue(q2 instanceof SQLTemplate);
-
-        assertNull(q2.getName());
-
-        Query q3 = q1.queryWithParameters(Collections.singletonMap("a", "b"));
-        assertNotNull(q3);
-        assertNotSame(q1, q3);
-        assertNull(q3.getName());
-        assertFalse(q1.getName().equals(q3.getName()));
-
-        Query q4 = q1.queryWithParameters(Collections.singletonMap("a", "b"));
-        assertNotNull(q4);
-        assertNotSame(q3, q4);
-        assertEquals(q3.getName(), q4.getName());
-    }
-
-    public void testSerializability() throws Exception {
-        SQLTemplate o = new SQLTemplate("Test", "DO SQL");
-        Object clone = Util.cloneViaSerialization(o);
-
-        assertTrue(clone instanceof SQLTemplate);
-        SQLTemplate c1 = (SQLTemplate) clone;
-
-        assertNotSame(o, c1);
-        assertEquals(o.getRoot(), c1.getRoot());
-        assertEquals(o.getDefaultTemplate(), c1.getDefaultTemplate());
-    }
-
-    public void testGetDefaultTemplate() {
-        SQLTemplate query = new SQLTemplate();
-        query.setDefaultTemplate("AAA # BBB");
-        assertEquals("AAA # BBB", query.getDefaultTemplate());
-    }
-
-    public void testGetTemplate() {
-        SQLTemplate query = new SQLTemplate();
-
-        // no template for key, no default template... must be null
-        assertNull(query.getTemplate("key1"));
-
-        // no template for key, must return default
-        query.setDefaultTemplate("AAA # BBB");
-        assertEquals("AAA # BBB", query.getTemplate("key1"));
-
-        // must find template
-        query.setTemplate("key1", "XYZ");
-        assertEquals("XYZ", query.getTemplate("key1"));
-
-        // add another template.. still must find
-        query.setTemplate("key2", "123");
-        assertEquals("XYZ", query.getTemplate("key1"));
-        assertEquals("123", query.getTemplate("key2"));
-    }
-
-    public void testSingleParameterSet() throws Exception {
-        SQLTemplate query = new SQLTemplate();
-
-        assertNotNull(query.getParameters());
-        assertTrue(query.getParameters().isEmpty());
-
-        Map<String, Object> params = new HashMap<String, Object>();
-        params.put("a", "b");
-
-        query.setParameters(params);
-        assertEquals(params, query.getParameters());
-        Iterator<?> it = query.parametersIterator();
-        assertTrue(it.hasNext());
-        assertEquals(params, it.next());
-        assertFalse(it.hasNext());
-
-        query.setParameters(null);
-        assertNotNull(query.getParameters());
-        assertTrue(query.getParameters().isEmpty());
-        it = query.parametersIterator();
-        assertFalse(it.hasNext());
-    }
-
-    public void testBatchParameterSet() throws Exception {
-        SQLTemplate query = new SQLTemplate();
-
-        assertNotNull(query.getParameters());
-        assertTrue(query.getParameters().isEmpty());
-
-        Map<String, Object> params1 = new HashMap<String, Object>();
-        params1.put("a", "b");
-
-        Map<String, Object> params2 = new HashMap<String, Object>();
-        params2.put("1", "2");
-
-        query.setParameters(new Map[] { params1, params2, null });
-        assertEquals(params1, query.getParameters());
-        Iterator<?> it = query.parametersIterator();
-        assertTrue(it.hasNext());
-        assertEquals(params1, it.next());
-        assertTrue(it.hasNext());
-        assertEquals(params2, it.next());
-        assertTrue(it.hasNext());
-        assertTrue(((Map<String, Object>) it.next()).isEmpty());
-        assertFalse(it.hasNext());
-
-        query.setParameters((Map[]) null);
-        assertNotNull(query.getParameters());
-        assertTrue(query.getParameters().isEmpty());
-        it = query.parametersIterator();
-        assertFalse(it.hasNext());
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/e42c376c/cayenne-server/src/test/java/org/apache/cayenne/query/SelectByIdIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/query/SelectByIdIT.java b/cayenne-server/src/test/java/org/apache/cayenne/query/SelectByIdIT.java
new file mode 100644
index 0000000..e81a513
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/query/SelectByIdIT.java
@@ -0,0 +1,193 @@
+/*****************************************************************
+ *   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.cayenne.query;
+
+import static java.util.Collections.singletonMap;
+import static org.junit.Assert.assertNotEquals;
+
+import org.apache.cayenne.DataRow;
+import org.apache.cayenne.ObjectContext;
+import org.apache.cayenne.ObjectId;
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.test.jdbc.DBHelper;
+import org.apache.cayenne.test.jdbc.TableHelper;
+import org.apache.cayenne.testdo.testmap.Artist;
+import org.apache.cayenne.testdo.testmap.Painting;
+import org.apache.cayenne.unit.di.DataChannelInterceptor;
+import org.apache.cayenne.unit.di.UnitTestClosure;
+import org.apache.cayenne.unit.di.server.ServerCase;
+import org.apache.cayenne.unit.di.server.UseServerRuntime;
+
+@UseServerRuntime(ServerCase.TESTMAP_PROJECT)
+public class SelectByIdIT extends ServerCase {
+
+	@Inject
+	private DataChannelInterceptor interceptor;
+
+	@Inject
+	private DBHelper dbHelper;
+
+	private TableHelper tArtist;
+
+	@Inject
+	private ObjectContext context;
+
+	@Override
+	protected void setUpAfterInjection() throws Exception {
+		dbHelper.deleteAll("PAINTING_INFO");
+		dbHelper.deleteAll("PAINTING");
+		dbHelper.deleteAll("ARTIST_EXHIBIT");
+		dbHelper.deleteAll("ARTIST_GROUP");
+		dbHelper.deleteAll("ARTIST");
+		dbHelper.deleteAll("COMPOUND_FK_TEST");
+		dbHelper.deleteAll("COMPOUND_PK_TEST");
+		dbHelper.deleteAll("CHAR_PK_TEST");
+
+		tArtist = new TableHelper(dbHelper, "ARTIST");
+		tArtist.setColumns("ARTIST_ID", "ARTIST_NAME");
+	}
+
+	private void createTwoArtists() throws Exception {
+		tArtist.insert(2, "artist2");
+		tArtist.insert(3, "artist3");
+	}
+
+	public void testIntPk() throws Exception {
+		createTwoArtists();
+
+		Artist a3 = SelectById.query(Artist.class, 3).selectOne(context);
+		assertNotNull(a3);
+		assertEquals("artist3", a3.getArtistName());
+
+		Artist a2 = SelectById.query(Artist.class, 2).selectOne(context);
+		assertNotNull(a2);
+		assertEquals("artist2", a2.getArtistName());
+	}
+
+	public void testMapPk() throws Exception {
+		createTwoArtists();
+
+		Artist a3 = SelectById.query(Artist.class, singletonMap(Artist.ARTIST_ID_PK_COLUMN, 3)).selectOne(context);
+		assertNotNull(a3);
+		assertEquals("artist3", a3.getArtistName());
+
+		Artist a2 = SelectById.query(Artist.class, singletonMap(Artist.ARTIST_ID_PK_COLUMN, 2)).selectOne(context);
+		assertNotNull(a2);
+		assertEquals("artist2", a2.getArtistName());
+	}
+
+	public void testObjectIdPk() throws Exception {
+		createTwoArtists();
+
+		ObjectId oid3 = new ObjectId("Artist", Artist.ARTIST_ID_PK_COLUMN, 3);
+		Artist a3 = SelectById.query(Artist.class, oid3).selectOne(context);
+		assertNotNull(a3);
+		assertEquals("artist3", a3.getArtistName());
+
+		ObjectId oid2 = new ObjectId("Artist", Artist.ARTIST_ID_PK_COLUMN, 2);
+		Artist a2 = SelectById.query(Artist.class, oid2).selectOne(context);
+		assertNotNull(a2);
+		assertEquals("artist2", a2.getArtistName());
+	}
+
+	public void testDataRowIntPk() throws Exception {
+		createTwoArtists();
+
+		DataRow a3 = SelectById.dataRowQuery(Artist.class, 3).selectOne(context);
+		assertNotNull(a3);
+		assertEquals("artist3", a3.get("ARTIST_NAME"));
+
+		DataRow a2 = SelectById.dataRowQuery(Artist.class, 2).selectOne(context);
+		assertNotNull(a2);
+		assertEquals("artist2", a2.get("ARTIST_NAME"));
+	}
+
+	public void testMetadataCacheKey() throws Exception {
+		SelectById<Painting> q1 = SelectById.query(Painting.class, 4);
+		QueryMetadata md1 = q1.getMetaData(context.getEntityResolver());
+		assertNotNull(md1);
+		assertNotNull(md1.getCacheKey());
+
+		SelectById<Painting> q2 = SelectById.query(Painting.class, singletonMap(Painting.PAINTING_ID_PK_COLUMN, 4));
+		QueryMetadata md2 = q2.getMetaData(context.getEntityResolver());
+		assertNotNull(md2);
+		assertNotNull(md2.getCacheKey());
+
+		// this query is just a different form of q1, so should hit the same
+		// cache entry
+		assertEquals(md1.getCacheKey(), md2.getCacheKey());
+
+		SelectById<Painting> q3 = SelectById.query(Painting.class, 5);
+		QueryMetadata md3 = q3.getMetaData(context.getEntityResolver());
+		assertNotNull(md3);
+		assertNotNull(md3.getCacheKey());
+		assertNotEquals(md1.getCacheKey(), md3.getCacheKey());
+
+		SelectById<Artist> q4 = SelectById.query(Artist.class, 4);
+		QueryMetadata md4 = q4.getMetaData(context.getEntityResolver());
+		assertNotNull(md4);
+		assertNotNull(md4.getCacheKey());
+		assertNotEquals(md1.getCacheKey(), md4.getCacheKey());
+
+		SelectById<Painting> q5 = SelectById.query(Painting.class, new ObjectId("Painting",
+				Painting.PAINTING_ID_PK_COLUMN, 4));
+		QueryMetadata md5 = q5.getMetaData(context.getEntityResolver());
+		assertNotNull(md5);
+		assertNotNull(md5.getCacheKey());
+
+		// this query is just a different form of q1, so should hit the same
+		// cache entry
+		assertEquals(md1.getCacheKey(), md5.getCacheKey());
+	}
+
+	public void testLocalCache() throws Exception {
+		createTwoArtists();
+
+		final Artist[] a3 = new Artist[1];
+
+		assertEquals(1, interceptor.runWithQueryCounter(new UnitTestClosure() {
+
+			@Override
+			public void execute() {
+				a3[0] = SelectById.query(Artist.class, 3).useLocalCache("g1").selectOne(context);
+				assertNotNull(a3[0]);
+				assertEquals("artist3", a3[0].getArtistName());
+			}
+		}));
+
+		interceptor.runWithQueriesBlocked(new UnitTestClosure() {
+
+			@Override
+			public void execute() {
+				Artist a3cached = SelectById.query(Artist.class, 3).useLocalCache("g1").selectOne(context);
+				assertSame(a3[0], a3cached);
+			}
+		});
+
+		context.performGenericQuery(new RefreshQuery("g1"));
+
+		assertEquals(1, interceptor.runWithQueryCounter(new UnitTestClosure() {
+
+			@Override
+			public void execute() {
+				SelectById.query(Artist.class, 3).useLocalCache("g1").selectOne(context);
+			}
+		}));
+	}
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/e42c376c/cayenne-server/src/test/java/org/apache/cayenne/query/SelectByIdTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/query/SelectByIdTest.java b/cayenne-server/src/test/java/org/apache/cayenne/query/SelectByIdTest.java
deleted file mode 100644
index 790cb27..0000000
--- a/cayenne-server/src/test/java/org/apache/cayenne/query/SelectByIdTest.java
+++ /dev/null
@@ -1,193 +0,0 @@
-/*****************************************************************
- *   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.cayenne.query;
-
-import static java.util.Collections.singletonMap;
-import static org.junit.Assert.assertNotEquals;
-
-import org.apache.cayenne.DataRow;
-import org.apache.cayenne.ObjectContext;
-import org.apache.cayenne.ObjectId;
-import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.test.jdbc.DBHelper;
-import org.apache.cayenne.test.jdbc.TableHelper;
-import org.apache.cayenne.testdo.testmap.Artist;
-import org.apache.cayenne.testdo.testmap.Painting;
-import org.apache.cayenne.unit.di.DataChannelInterceptor;
-import org.apache.cayenne.unit.di.UnitTestClosure;
-import org.apache.cayenne.unit.di.server.ServerCase;
-import org.apache.cayenne.unit.di.server.UseServerRuntime;
-
-@UseServerRuntime(ServerCase.TESTMAP_PROJECT)
-public class SelectByIdTest extends ServerCase {
-
-	@Inject
-	private DataChannelInterceptor interceptor;
-
-	@Inject
-	private DBHelper dbHelper;
-
-	private TableHelper tArtist;
-
-	@Inject
-	private ObjectContext context;
-
-	@Override
-	protected void setUpAfterInjection() throws Exception {
-		dbHelper.deleteAll("PAINTING_INFO");
-		dbHelper.deleteAll("PAINTING");
-		dbHelper.deleteAll("ARTIST_EXHIBIT");
-		dbHelper.deleteAll("ARTIST_GROUP");
-		dbHelper.deleteAll("ARTIST");
-		dbHelper.deleteAll("COMPOUND_FK_TEST");
-		dbHelper.deleteAll("COMPOUND_PK_TEST");
-		dbHelper.deleteAll("CHAR_PK_TEST");
-
-		tArtist = new TableHelper(dbHelper, "ARTIST");
-		tArtist.setColumns("ARTIST_ID", "ARTIST_NAME");
-	}
-
-	private void createTwoArtists() throws Exception {
-		tArtist.insert(2, "artist2");
-		tArtist.insert(3, "artist3");
-	}
-
-	public void testIntPk() throws Exception {
-		createTwoArtists();
-
-		Artist a3 = SelectById.query(Artist.class, 3).selectOne(context);
-		assertNotNull(a3);
-		assertEquals("artist3", a3.getArtistName());
-
-		Artist a2 = SelectById.query(Artist.class, 2).selectOne(context);
-		assertNotNull(a2);
-		assertEquals("artist2", a2.getArtistName());
-	}
-
-	public void testMapPk() throws Exception {
-		createTwoArtists();
-
-		Artist a3 = SelectById.query(Artist.class, singletonMap(Artist.ARTIST_ID_PK_COLUMN, 3)).selectOne(context);
-		assertNotNull(a3);
-		assertEquals("artist3", a3.getArtistName());
-
-		Artist a2 = SelectById.query(Artist.class, singletonMap(Artist.ARTIST_ID_PK_COLUMN, 2)).selectOne(context);
-		assertNotNull(a2);
-		assertEquals("artist2", a2.getArtistName());
-	}
-
-	public void testObjectIdPk() throws Exception {
-		createTwoArtists();
-
-		ObjectId oid3 = new ObjectId("Artist", Artist.ARTIST_ID_PK_COLUMN, 3);
-		Artist a3 = SelectById.query(Artist.class, oid3).selectOne(context);
-		assertNotNull(a3);
-		assertEquals("artist3", a3.getArtistName());
-
-		ObjectId oid2 = new ObjectId("Artist", Artist.ARTIST_ID_PK_COLUMN, 2);
-		Artist a2 = SelectById.query(Artist.class, oid2).selectOne(context);
-		assertNotNull(a2);
-		assertEquals("artist2", a2.getArtistName());
-	}
-
-	public void testDataRowIntPk() throws Exception {
-		createTwoArtists();
-
-		DataRow a3 = SelectById.dataRowQuery(Artist.class, 3).selectOne(context);
-		assertNotNull(a3);
-		assertEquals("artist3", a3.get("ARTIST_NAME"));
-
-		DataRow a2 = SelectById.dataRowQuery(Artist.class, 2).selectOne(context);
-		assertNotNull(a2);
-		assertEquals("artist2", a2.get("ARTIST_NAME"));
-	}
-
-	public void testMetadataCacheKey() throws Exception {
-		SelectById<Painting> q1 = SelectById.query(Painting.class, 4);
-		QueryMetadata md1 = q1.getMetaData(context.getEntityResolver());
-		assertNotNull(md1);
-		assertNotNull(md1.getCacheKey());
-
-		SelectById<Painting> q2 = SelectById.query(Painting.class, singletonMap(Painting.PAINTING_ID_PK_COLUMN, 4));
-		QueryMetadata md2 = q2.getMetaData(context.getEntityResolver());
-		assertNotNull(md2);
-		assertNotNull(md2.getCacheKey());
-
-		// this query is just a different form of q1, so should hit the same
-		// cache entry
-		assertEquals(md1.getCacheKey(), md2.getCacheKey());
-
-		SelectById<Painting> q3 = SelectById.query(Painting.class, 5);
-		QueryMetadata md3 = q3.getMetaData(context.getEntityResolver());
-		assertNotNull(md3);
-		assertNotNull(md3.getCacheKey());
-		assertNotEquals(md1.getCacheKey(), md3.getCacheKey());
-
-		SelectById<Artist> q4 = SelectById.query(Artist.class, 4);
-		QueryMetadata md4 = q4.getMetaData(context.getEntityResolver());
-		assertNotNull(md4);
-		assertNotNull(md4.getCacheKey());
-		assertNotEquals(md1.getCacheKey(), md4.getCacheKey());
-
-		SelectById<Painting> q5 = SelectById.query(Painting.class, new ObjectId("Painting",
-				Painting.PAINTING_ID_PK_COLUMN, 4));
-		QueryMetadata md5 = q5.getMetaData(context.getEntityResolver());
-		assertNotNull(md5);
-		assertNotNull(md5.getCacheKey());
-
-		// this query is just a different form of q1, so should hit the same
-		// cache entry
-		assertEquals(md1.getCacheKey(), md5.getCacheKey());
-	}
-
-	public void testLocalCache() throws Exception {
-		createTwoArtists();
-
-		final Artist[] a3 = new Artist[1];
-
-		assertEquals(1, interceptor.runWithQueryCounter(new UnitTestClosure() {
-
-			@Override
-			public void execute() {
-				a3[0] = SelectById.query(Artist.class, 3).useLocalCache("g1").selectOne(context);
-				assertNotNull(a3[0]);
-				assertEquals("artist3", a3[0].getArtistName());
-			}
-		}));
-
-		interceptor.runWithQueriesBlocked(new UnitTestClosure() {
-
-			@Override
-			public void execute() {
-				Artist a3cached = SelectById.query(Artist.class, 3).useLocalCache("g1").selectOne(context);
-				assertSame(a3[0], a3cached);
-			}
-		});
-
-		context.performGenericQuery(new RefreshQuery("g1"));
-
-		assertEquals(1, interceptor.runWithQueryCounter(new UnitTestClosure() {
-
-			@Override
-			public void execute() {
-				SelectById.query(Artist.class, 3).useLocalCache("g1").selectOne(context);
-			}
-		}));
-	}
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/e42c376c/cayenne-server/src/test/java/org/apache/cayenne/query/SelectQueryCacheKeyIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/query/SelectQueryCacheKeyIT.java b/cayenne-server/src/test/java/org/apache/cayenne/query/SelectQueryCacheKeyIT.java
new file mode 100644
index 0000000..8cbf07b
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/query/SelectQueryCacheKeyIT.java
@@ -0,0 +1,181 @@
+/*****************************************************************
+ *   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.cayenne.query;
+
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.exp.ExpressionFactory;
+import org.apache.cayenne.map.EntityResolver;
+import org.apache.cayenne.testdo.testmap.Artist;
+import org.apache.cayenne.testdo.testmap.Painting;
+import org.apache.cayenne.unit.di.server.ServerCase;
+import org.apache.cayenne.unit.di.server.UseServerRuntime;
+
+@UseServerRuntime(ServerCase.TESTMAP_PROJECT)
+public class SelectQueryCacheKeyIT extends ServerCase {
+
+    @Inject
+    private EntityResolver resolver;
+
+    public void testNoCache() {
+
+        SelectQuery query = new SelectQuery(Artist.class);
+
+        QueryMetadata md1 = query.getMetaData(resolver);
+        assertEquals(QueryCacheStrategy.NO_CACHE, md1.getCacheStrategy());
+        assertNull(md1.getCacheKey());
+
+        query.setName("XYZ");
+        QueryMetadata md2 = query.getMetaData(resolver);
+        assertEquals(QueryCacheStrategy.NO_CACHE, md2.getCacheStrategy());
+        assertNull(md2.getCacheKey());
+    }
+
+    public void testLocalCache() {
+
+        SelectQuery<Artist> query = new SelectQuery<Artist>(Artist.class);
+
+        query.setCacheStrategy(QueryCacheStrategy.LOCAL_CACHE);
+
+        QueryMetadata md1 = query.getMetaData(resolver);
+        assertEquals(QueryCacheStrategy.LOCAL_CACHE, md1.getCacheStrategy());
+        assertNotNull(md1.getCacheKey());
+    }
+
+    public void testUseLocalCache() {
+
+        SelectQuery<Artist> q1 = new SelectQuery<Artist>(Artist.class);
+        q1.useLocalCache();
+
+        QueryMetadata md1 = q1.getMetaData(resolver);
+        assertEquals(QueryCacheStrategy.LOCAL_CACHE, md1.getCacheStrategy());
+        assertNotNull(md1.getCacheKey());
+        assertEquals(0, md1.getCacheGroups().length);
+        
+        SelectQuery<Artist> q2 = new SelectQuery<Artist>(Artist.class);
+        q2.useLocalCache("g1", "g2");
+
+        QueryMetadata md2 = q2.getMetaData(resolver);
+        assertEquals(QueryCacheStrategy.LOCAL_CACHE, md2.getCacheStrategy());
+        assertNotNull(md2.getCacheKey());
+        assertEquals(2, md2.getCacheGroups().length);
+    }
+
+    public void testSharedCache() {
+
+        SelectQuery<Artist> query = new SelectQuery<Artist>(Artist.class);
+
+        query.setCacheStrategy(QueryCacheStrategy.SHARED_CACHE);
+
+        QueryMetadata md1 = query.getMetaData(resolver);
+        assertEquals(QueryCacheStrategy.SHARED_CACHE, md1.getCacheStrategy());
+        assertNotNull(md1.getCacheKey());
+    }
+    
+    public void testUseSharedCache() {
+
+        SelectQuery<Artist> q1 = new SelectQuery<Artist>(Artist.class);
+        q1.useSharedCache();
+
+        QueryMetadata md1 = q1.getMetaData(resolver);
+        assertEquals(QueryCacheStrategy.SHARED_CACHE, md1.getCacheStrategy());
+        assertNotNull(md1.getCacheKey());
+        assertEquals(0, md1.getCacheGroups().length);
+        
+        SelectQuery<Artist> q2 = new SelectQuery<Artist>(Artist.class);
+        q2.useSharedCache("g1", "g2");
+
+        QueryMetadata md2 = q2.getMetaData(resolver);
+        assertEquals(QueryCacheStrategy.SHARED_CACHE, md2.getCacheStrategy());
+        assertNotNull(md2.getCacheKey());
+        assertEquals(2, md2.getCacheGroups().length);
+    }
+
+    public void testNamedQuery() {
+
+        SelectQuery query = new SelectQuery(Artist.class);
+
+        query.setCacheStrategy(QueryCacheStrategy.SHARED_CACHE);
+        query.setName("XYZ");
+
+        QueryMetadata md1 = query.getMetaData(resolver);
+        assertEquals(QueryCacheStrategy.SHARED_CACHE, md1.getCacheStrategy());
+        assertFalse("XYZ".equals(md1.getCacheKey()));
+    }
+
+    public void testUniqueKeyEntity() {
+
+        SelectQuery q1 = new SelectQuery(Artist.class);
+        q1.setCacheStrategy(QueryCacheStrategy.LOCAL_CACHE);
+
+        SelectQuery q2 = new SelectQuery(Artist.class);
+        q2.setCacheStrategy(QueryCacheStrategy.LOCAL_CACHE);
+
+        SelectQuery q3 = new SelectQuery(Painting.class);
+        q3.setCacheStrategy(QueryCacheStrategy.LOCAL_CACHE);
+
+        assertNotNull(q1.getMetaData(resolver).getCacheKey());
+        assertEquals(q1.getMetaData(resolver).getCacheKey(), q2.getMetaData(resolver).getCacheKey());
+
+        assertFalse(q1.getMetaData(resolver).getCacheKey().equals(q3.getMetaData(resolver).getCacheKey()));
+    }
+
+    public void testUniqueKeyEntityQualifier() {
+
+        SelectQuery q1 = new SelectQuery(Artist.class);
+        q1.setCacheStrategy(QueryCacheStrategy.LOCAL_CACHE);
+        q1.setQualifier(ExpressionFactory.matchExp("a", "b"));
+
+        SelectQuery q2 = new SelectQuery(Artist.class);
+        q2.setCacheStrategy(QueryCacheStrategy.LOCAL_CACHE);
+        q2.setQualifier(ExpressionFactory.matchExp("a", "b"));
+
+        SelectQuery q3 = new SelectQuery(Artist.class);
+        q3.setCacheStrategy(QueryCacheStrategy.LOCAL_CACHE);
+        q3.setQualifier(ExpressionFactory.matchExp("a", "c"));
+
+        assertNotNull(q1.getMetaData(resolver).getCacheKey());
+        assertEquals(q1.getMetaData(resolver).getCacheKey(), q2.getMetaData(resolver).getCacheKey());
+
+        assertFalse(q1.getMetaData(resolver).getCacheKey().equals(q3.getMetaData(resolver).getCacheKey()));
+    }
+
+    public void testUniqueKeyEntityFetchLimit() {
+
+        SelectQuery q1 = new SelectQuery(Artist.class);
+        q1.setCacheStrategy(QueryCacheStrategy.LOCAL_CACHE);
+        q1.setFetchLimit(5);
+
+        SelectQuery q2 = new SelectQuery(Artist.class);
+        q2.setCacheStrategy(QueryCacheStrategy.LOCAL_CACHE);
+        q2.setFetchLimit(5);
+
+        SelectQuery q3 = new SelectQuery(Artist.class);
+        q3.setCacheStrategy(QueryCacheStrategy.LOCAL_CACHE);
+        q3.setFetchLimit(6);
+
+        SelectQuery q4 = new SelectQuery(Artist.class);
+        q4.setCacheStrategy(QueryCacheStrategy.LOCAL_CACHE);
+
+        assertNotNull(q1.getMetaData(resolver).getCacheKey());
+        assertEquals(q1.getMetaData(resolver).getCacheKey(), q2.getMetaData(resolver).getCacheKey());
+
+        assertFalse(q1.getMetaData(resolver).getCacheKey().equals(q3.getMetaData(resolver).getCacheKey()));
+        assertFalse(q1.getMetaData(resolver).getCacheKey().equals(q4.getMetaData(resolver).getCacheKey()));
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/e42c376c/cayenne-server/src/test/java/org/apache/cayenne/query/SelectQueryCacheKeyTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/query/SelectQueryCacheKeyTest.java b/cayenne-server/src/test/java/org/apache/cayenne/query/SelectQueryCacheKeyTest.java
deleted file mode 100644
index e37f680..0000000
--- a/cayenne-server/src/test/java/org/apache/cayenne/query/SelectQueryCacheKeyTest.java
+++ /dev/null
@@ -1,181 +0,0 @@
-/*****************************************************************
- *   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.cayenne.query;
-
-import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.exp.ExpressionFactory;
-import org.apache.cayenne.map.EntityResolver;
-import org.apache.cayenne.testdo.testmap.Artist;
-import org.apache.cayenne.testdo.testmap.Painting;
-import org.apache.cayenne.unit.di.server.ServerCase;
-import org.apache.cayenne.unit.di.server.UseServerRuntime;
-
-@UseServerRuntime(ServerCase.TESTMAP_PROJECT)
-public class SelectQueryCacheKeyTest extends ServerCase {
-
-    @Inject
-    private EntityResolver resolver;
-
-    public void testNoCache() {
-
-        SelectQuery query = new SelectQuery(Artist.class);
-
-        QueryMetadata md1 = query.getMetaData(resolver);
-        assertEquals(QueryCacheStrategy.NO_CACHE, md1.getCacheStrategy());
-        assertNull(md1.getCacheKey());
-
-        query.setName("XYZ");
-        QueryMetadata md2 = query.getMetaData(resolver);
-        assertEquals(QueryCacheStrategy.NO_CACHE, md2.getCacheStrategy());
-        assertNull(md2.getCacheKey());
-    }
-
-    public void testLocalCache() {
-
-        SelectQuery<Artist> query = new SelectQuery<Artist>(Artist.class);
-
-        query.setCacheStrategy(QueryCacheStrategy.LOCAL_CACHE);
-
-        QueryMetadata md1 = query.getMetaData(resolver);
-        assertEquals(QueryCacheStrategy.LOCAL_CACHE, md1.getCacheStrategy());
-        assertNotNull(md1.getCacheKey());
-    }
-
-    public void testUseLocalCache() {
-
-        SelectQuery<Artist> q1 = new SelectQuery<Artist>(Artist.class);
-        q1.useLocalCache();
-
-        QueryMetadata md1 = q1.getMetaData(resolver);
-        assertEquals(QueryCacheStrategy.LOCAL_CACHE, md1.getCacheStrategy());
-        assertNotNull(md1.getCacheKey());
-        assertEquals(0, md1.getCacheGroups().length);
-        
-        SelectQuery<Artist> q2 = new SelectQuery<Artist>(Artist.class);
-        q2.useLocalCache("g1", "g2");
-
-        QueryMetadata md2 = q2.getMetaData(resolver);
-        assertEquals(QueryCacheStrategy.LOCAL_CACHE, md2.getCacheStrategy());
-        assertNotNull(md2.getCacheKey());
-        assertEquals(2, md2.getCacheGroups().length);
-    }
-
-    public void testSharedCache() {
-
-        SelectQuery<Artist> query = new SelectQuery<Artist>(Artist.class);
-
-        query.setCacheStrategy(QueryCacheStrategy.SHARED_CACHE);
-
-        QueryMetadata md1 = query.getMetaData(resolver);
-        assertEquals(QueryCacheStrategy.SHARED_CACHE, md1.getCacheStrategy());
-        assertNotNull(md1.getCacheKey());
-    }
-    
-    public void testUseSharedCache() {
-
-        SelectQuery<Artist> q1 = new SelectQuery<Artist>(Artist.class);
-        q1.useSharedCache();
-
-        QueryMetadata md1 = q1.getMetaData(resolver);
-        assertEquals(QueryCacheStrategy.SHARED_CACHE, md1.getCacheStrategy());
-        assertNotNull(md1.getCacheKey());
-        assertEquals(0, md1.getCacheGroups().length);
-        
-        SelectQuery<Artist> q2 = new SelectQuery<Artist>(Artist.class);
-        q2.useSharedCache("g1", "g2");
-
-        QueryMetadata md2 = q2.getMetaData(resolver);
-        assertEquals(QueryCacheStrategy.SHARED_CACHE, md2.getCacheStrategy());
-        assertNotNull(md2.getCacheKey());
-        assertEquals(2, md2.getCacheGroups().length);
-    }
-
-    public void testNamedQuery() {
-
-        SelectQuery query = new SelectQuery(Artist.class);
-
-        query.setCacheStrategy(QueryCacheStrategy.SHARED_CACHE);
-        query.setName("XYZ");
-
-        QueryMetadata md1 = query.getMetaData(resolver);
-        assertEquals(QueryCacheStrategy.SHARED_CACHE, md1.getCacheStrategy());
-        assertFalse("XYZ".equals(md1.getCacheKey()));
-    }
-
-    public void testUniqueKeyEntity() {
-
-        SelectQuery q1 = new SelectQuery(Artist.class);
-        q1.setCacheStrategy(QueryCacheStrategy.LOCAL_CACHE);
-
-        SelectQuery q2 = new SelectQuery(Artist.class);
-        q2.setCacheStrategy(QueryCacheStrategy.LOCAL_CACHE);
-
-        SelectQuery q3 = new SelectQuery(Painting.class);
-        q3.setCacheStrategy(QueryCacheStrategy.LOCAL_CACHE);
-
-        assertNotNull(q1.getMetaData(resolver).getCacheKey());
-        assertEquals(q1.getMetaData(resolver).getCacheKey(), q2.getMetaData(resolver).getCacheKey());
-
-        assertFalse(q1.getMetaData(resolver).getCacheKey().equals(q3.getMetaData(resolver).getCacheKey()));
-    }
-
-    public void testUniqueKeyEntityQualifier() {
-
-        SelectQuery q1 = new SelectQuery(Artist.class);
-        q1.setCacheStrategy(QueryCacheStrategy.LOCAL_CACHE);
-        q1.setQualifier(ExpressionFactory.matchExp("a", "b"));
-
-        SelectQuery q2 = new SelectQuery(Artist.class);
-        q2.setCacheStrategy(QueryCacheStrategy.LOCAL_CACHE);
-        q2.setQualifier(ExpressionFactory.matchExp("a", "b"));
-
-        SelectQuery q3 = new SelectQuery(Artist.class);
-        q3.setCacheStrategy(QueryCacheStrategy.LOCAL_CACHE);
-        q3.setQualifier(ExpressionFactory.matchExp("a", "c"));
-
-        assertNotNull(q1.getMetaData(resolver).getCacheKey());
-        assertEquals(q1.getMetaData(resolver).getCacheKey(), q2.getMetaData(resolver).getCacheKey());
-
-        assertFalse(q1.getMetaData(resolver).getCacheKey().equals(q3.getMetaData(resolver).getCacheKey()));
-    }
-
-    public void testUniqueKeyEntityFetchLimit() {
-
-        SelectQuery q1 = new SelectQuery(Artist.class);
-        q1.setCacheStrategy(QueryCacheStrategy.LOCAL_CACHE);
-        q1.setFetchLimit(5);
-
-        SelectQuery q2 = new SelectQuery(Artist.class);
-        q2.setCacheStrategy(QueryCacheStrategy.LOCAL_CACHE);
-        q2.setFetchLimit(5);
-
-        SelectQuery q3 = new SelectQuery(Artist.class);
-        q3.setCacheStrategy(QueryCacheStrategy.LOCAL_CACHE);
-        q3.setFetchLimit(6);
-
-        SelectQuery q4 = new SelectQuery(Artist.class);
-        q4.setCacheStrategy(QueryCacheStrategy.LOCAL_CACHE);
-
-        assertNotNull(q1.getMetaData(resolver).getCacheKey());
-        assertEquals(q1.getMetaData(resolver).getCacheKey(), q2.getMetaData(resolver).getCacheKey());
-
-        assertFalse(q1.getMetaData(resolver).getCacheKey().equals(q3.getMetaData(resolver).getCacheKey()));
-        assertFalse(q1.getMetaData(resolver).getCacheKey().equals(q4.getMetaData(resolver).getCacheKey()));
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/e42c376c/cayenne-server/src/test/java/org/apache/cayenne/query/SelectQueryFetchLimitOrderingIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/query/SelectQueryFetchLimitOrderingIT.java b/cayenne-server/src/test/java/org/apache/cayenne/query/SelectQueryFetchLimitOrderingIT.java
new file mode 100644
index 0000000..a251137
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/query/SelectQueryFetchLimitOrderingIT.java
@@ -0,0 +1,81 @@
+/*****************************************************************
+ *   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.cayenne.query;
+
+import org.apache.cayenne.ObjectContext;
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.test.jdbc.DBHelper;
+import org.apache.cayenne.test.jdbc.TableHelper;
+import org.apache.cayenne.testdo.testmap.Artist;
+import org.apache.cayenne.unit.di.server.ServerCase;
+import org.apache.cayenne.unit.di.server.UseServerRuntime;
+
+import java.util.List;
+
+@UseServerRuntime(ServerCase.TESTMAP_PROJECT)
+public class SelectQueryFetchLimitOrderingIT extends ServerCase {
+
+    @Inject
+    protected ObjectContext context;
+
+    @Inject
+    protected DBHelper dbHelper;
+
+    protected TableHelper tArtist;
+
+    @Override
+    protected void setUpAfterInjection() throws Exception {
+        dbHelper.deleteAll("PAINTING_INFO");
+        dbHelper.deleteAll("PAINTING");
+        dbHelper.deleteAll("ARTIST_EXHIBIT");
+        dbHelper.deleteAll("ARTIST_GROUP");
+        dbHelper.deleteAll("ARTIST");
+
+        tArtist = new TableHelper(dbHelper, "ARTIST");
+        tArtist.setColumns("ARTIST_ID", "ARTIST_NAME");
+    }
+
+    protected void creatArtistsDataSet() throws Exception {
+        tArtist.insert(33001, "c");
+        tArtist.insert(33002, "b");
+        tArtist.insert(33003, "f");
+        tArtist.insert(33004, "d");
+        tArtist.insert(33005, "a");
+        tArtist.insert(33006, "e");
+    }
+
+    public void testOrdering() throws Exception {
+
+        creatArtistsDataSet();
+
+        SelectQuery query = new SelectQuery("Artist");
+        query.addOrdering(Artist.ARTIST_NAME_PROPERTY, SortOrder.ASCENDING);
+
+        query.setFetchLimit(4);
+
+        List<?> results = context.performQuery(query);
+        assertEquals(4, results.size());
+
+        assertEquals("a", ((Artist) results.get(0)).getArtistName());
+        assertEquals("b", ((Artist) results.get(1)).getArtistName());
+        assertEquals("c", ((Artist) results.get(2)).getArtistName());
+        assertEquals("d", ((Artist) results.get(3)).getArtistName());
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/e42c376c/cayenne-server/src/test/java/org/apache/cayenne/query/SelectQueryFetchLimitOrderingTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/query/SelectQueryFetchLimitOrderingTest.java b/cayenne-server/src/test/java/org/apache/cayenne/query/SelectQueryFetchLimitOrderingTest.java
deleted file mode 100644
index a613d20..0000000
--- a/cayenne-server/src/test/java/org/apache/cayenne/query/SelectQueryFetchLimitOrderingTest.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*****************************************************************
- *   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.cayenne.query;
-
-import java.util.List;
-
-import org.apache.cayenne.ObjectContext;
-import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.test.jdbc.DBHelper;
-import org.apache.cayenne.test.jdbc.TableHelper;
-import org.apache.cayenne.testdo.testmap.Artist;
-import org.apache.cayenne.unit.di.server.ServerCase;
-import org.apache.cayenne.unit.di.server.UseServerRuntime;
-
-@UseServerRuntime(ServerCase.TESTMAP_PROJECT)
-public class SelectQueryFetchLimitOrderingTest extends ServerCase {
-
-    @Inject
-    protected ObjectContext context;
-
-    @Inject
-    protected DBHelper dbHelper;
-
-    protected TableHelper tArtist;
-
-    @Override
-    protected void setUpAfterInjection() throws Exception {
-        dbHelper.deleteAll("PAINTING_INFO");
-        dbHelper.deleteAll("PAINTING");
-        dbHelper.deleteAll("ARTIST_EXHIBIT");
-        dbHelper.deleteAll("ARTIST_GROUP");
-        dbHelper.deleteAll("ARTIST");
-
-        tArtist = new TableHelper(dbHelper, "ARTIST");
-        tArtist.setColumns("ARTIST_ID", "ARTIST_NAME");
-    }
-
-    protected void creatArtistsDataSet() throws Exception {
-        tArtist.insert(33001, "c");
-        tArtist.insert(33002, "b");
-        tArtist.insert(33003, "f");
-        tArtist.insert(33004, "d");
-        tArtist.insert(33005, "a");
-        tArtist.insert(33006, "e");
-    }
-
-    public void testOrdering() throws Exception {
-
-        creatArtistsDataSet();
-
-        SelectQuery query = new SelectQuery("Artist");
-        query.addOrdering(Artist.ARTIST_NAME_PROPERTY, SortOrder.ASCENDING);
-
-        query.setFetchLimit(4);
-
-        List<?> results = context.performQuery(query);
-        assertEquals(4, results.size());
-
-        assertEquals("a", ((Artist) results.get(0)).getArtistName());
-        assertEquals("b", ((Artist) results.get(1)).getArtistName());
-        assertEquals("c", ((Artist) results.get(2)).getArtistName());
-        assertEquals("d", ((Artist) results.get(3)).getArtistName());
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/e42c376c/cayenne-server/src/test/java/org/apache/cayenne/query/SelectQueryIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/query/SelectQueryIT.java b/cayenne-server/src/test/java/org/apache/cayenne/query/SelectQueryIT.java
new file mode 100644
index 0000000..6f5527f
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/query/SelectQueryIT.java
@@ -0,0 +1,796 @@
+/*****************************************************************
+ *   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.cayenne.query;
+
+import org.apache.cayenne.Cayenne;
+import org.apache.cayenne.DataRow;
+import org.apache.cayenne.ObjectContext;
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.exp.Expression;
+import org.apache.cayenne.exp.ExpressionFactory;
+import org.apache.cayenne.exp.parser.ASTBitwiseAnd;
+import org.apache.cayenne.exp.parser.ASTBitwiseNot;
+import org.apache.cayenne.exp.parser.ASTBitwiseOr;
+import org.apache.cayenne.exp.parser.ASTBitwiseXor;
+import org.apache.cayenne.exp.parser.ASTEqual;
+import org.apache.cayenne.exp.parser.ASTGreater;
+import org.apache.cayenne.exp.parser.ASTObjPath;
+import org.apache.cayenne.exp.parser.ASTScalar;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.EntityResolver;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.map.ObjRelationship;
+import org.apache.cayenne.test.jdbc.DBHelper;
+import org.apache.cayenne.test.jdbc.TableHelper;
+import org.apache.cayenne.testdo.testmap.Artist;
+import org.apache.cayenne.testdo.testmap.ArtistExhibit;
+import org.apache.cayenne.testdo.testmap.ClobTestEntity;
+import org.apache.cayenne.testdo.testmap.Exhibit;
+import org.apache.cayenne.testdo.testmap.Gallery;
+import org.apache.cayenne.testdo.testmap.Painting;
+import org.apache.cayenne.testdo.testmap.ReturnTypesMap1;
+import org.apache.cayenne.unit.UnitDbAdapter;
+import org.apache.cayenne.unit.di.server.ServerCase;
+import org.apache.cayenne.unit.di.server.UseServerRuntime;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+@UseServerRuntime(ServerCase.TESTMAP_PROJECT)
+public class SelectQueryIT extends ServerCase {
+
+    @Inject
+    private ObjectContext context;
+
+    @Inject
+    private DBHelper dbHelper;
+
+    @Inject
+    private UnitDbAdapter accessStackAdapter;
+
+    @Override
+    protected void setUpAfterInjection() throws Exception {
+        dbHelper.deleteAll("PAINTING_INFO");
+        dbHelper.deleteAll("PAINTING");
+        dbHelper.deleteAll("ARTIST_EXHIBIT");
+        dbHelper.deleteAll("ARTIST_GROUP");
+        dbHelper.deleteAll("ARTIST");
+        dbHelper.deleteAll("CLOB_TEST_RELATION");
+        dbHelper.deleteAll("TYPES_MAPPING_TEST1");
+
+        if (accessStackAdapter.supportsLobs()) {
+            dbHelper.deleteAll("CLOB_TEST");
+        }
+    }
+
+    protected void createClobDataSet() throws Exception {
+        TableHelper tClobTest = new TableHelper(dbHelper, "CLOB_TEST");
+        tClobTest.setColumns("CLOB_TEST_ID", "CLOB_COL");
+
+        tClobTest.deleteAll();
+
+        tClobTest.insert(1, "clob1");
+        tClobTest.insert(2, "clob2");
+    }
+
+    protected void createArtistsDataSet() throws Exception {
+        TableHelper tArtist = new TableHelper(dbHelper, "ARTIST");
+        tArtist.setColumns("ARTIST_ID", "ARTIST_NAME", "DATE_OF_BIRTH");
+
+        long dateBase = System.currentTimeMillis();
+
+        for (int i = 1; i <= 20; i++) {
+            tArtist.insert(i, "artist" + i, new java.sql.Date(dateBase + 10000 * i));
+        }
+    }
+
+    protected void createArtistsWildcardDataSet() throws Exception {
+        TableHelper tArtist = new TableHelper(dbHelper, "ARTIST");
+        tArtist.setColumns("ARTIST_ID", "ARTIST_NAME");
+
+        tArtist.insert(1, "_X");
+        tArtist.insert(2, "Y_");
+    }
+
+    protected void createNumericsDataSet() throws Exception {
+        TableHelper tNumerics = new TableHelper(dbHelper, "TYPES_MAPPING_TEST1");
+        tNumerics.setColumns("AAAID", "INTEGER_COLUMN");
+
+        tNumerics.insert(1, 0);
+        tNumerics.insert(2, 1);
+        tNumerics.insert(3, 2);
+        tNumerics.insert(4, 3);
+        tNumerics.insert(5, 4);
+    }
+    
+    public void testSetQualifier() {
+        SelectQuery<Artist> query = new SelectQuery<Artist>(Artist.class);
+        assertNull(query.getQualifier());
+
+        Expression qual = ExpressionFactory.expressionOfType(Expression.AND);
+        query.setQualifier(qual);
+        assertNotNull(query.getQualifier());
+        assertSame(qual, query.getQualifier());
+    }
+
+    public void testAndQualifier() {
+    	SelectQuery<Artist> query = new SelectQuery<Artist>(Artist.class);
+        assertNull(query.getQualifier());
+
+        Expression e1 = ExpressionFactory.expressionOfType(Expression.EQUAL_TO);
+        query.andQualifier(e1);
+        assertSame(e1, query.getQualifier());
+
+        Expression e2 = ExpressionFactory.expressionOfType(Expression.NOT_EQUAL_TO);
+        query.andQualifier(e2);
+        assertEquals(Expression.AND, query.getQualifier().getType());
+    }
+
+    public void testOrQualifier() {
+    	SelectQuery<Artist> query = new SelectQuery<Artist>(Artist.class);
+        assertNull(query.getQualifier());
+
+        Expression e1 = ExpressionFactory.expressionOfType(Expression.EQUAL_TO);
+        query.orQualifier(e1);
+        assertSame(e1, query.getQualifier());
+
+        Expression e2 = ExpressionFactory.expressionOfType(Expression.NOT_EQUAL_TO);
+        query.orQualifier(e2);
+        assertEquals(Expression.OR, query.getQualifier().getType());
+    }
+
+    public void testFetchLimit() throws Exception {
+        createArtistsDataSet();
+
+        SelectQuery<Artist> query = new SelectQuery<Artist>(Artist.class);
+        query.setFetchLimit(7);
+
+        List<?> objects = context.performQuery(query);
+        assertNotNull(objects);
+        assertEquals(7, objects.size());
+    }
+
+    public void testFetchOffset() throws Exception {
+
+        createArtistsDataSet();
+
+        int totalRows = context.select(new SelectQuery<Artist>(Artist.class)).size();
+
+        SelectQuery<Artist> query = new SelectQuery<Artist>(Artist.class);
+        query.addOrdering("db:" + Artist.ARTIST_ID_PK_COLUMN, SortOrder.ASCENDING);
+        query.setFetchOffset(5);
+        List<Artist> results = context.select(query);
+
+        assertEquals(totalRows - 5, results.size());
+        assertEquals("artist6", results.get(0).getArtistName());
+    }
+
+    public void testDbEntityRoot() throws Exception {
+
+        createArtistsDataSet();
+        DbEntity artistDbEntity = context.getEntityResolver().getDbEntity("ARTIST");
+
+        SelectQuery query = new SelectQuery(artistDbEntity);
+        List<?> results = context.performQuery(query);
+
+        assertEquals(20, results.size());
+        assertTrue(results.get(0) instanceof DataRow);
+    }
+
+    public void testFetchLimitWithOffset() throws Exception {
+        createArtistsDataSet();
+        SelectQuery<Artist> query = new SelectQuery<Artist>(Artist.class);
+        query.addOrdering("db:" + Artist.ARTIST_ID_PK_COLUMN, SortOrder.ASCENDING);
+        query.setFetchOffset(15);
+        query.setFetchLimit(4);
+        List<Artist> results = context.select(query);
+
+        assertEquals(4, results.size());
+        assertEquals("artist16", results.get(0).getArtistName());
+    }
+
+    public void testFetchOffsetWithQualifier() throws Exception {
+        createArtistsDataSet();
+        SelectQuery<Artist> query = new SelectQuery<Artist>(Artist.class);
+        query.setQualifier(Expression.fromString("db:ARTIST_ID > 3"));
+        query.setFetchOffset(5);
+
+        List<?> objects = context.performQuery(query);
+        int size = objects.size();
+
+        SelectQuery<Artist> sizeQ = new SelectQuery<Artist>(Artist.class);
+        sizeQ.setQualifier(Expression.fromString("db:ARTIST_ID > 3"));
+        List<?> objects1 = context.performQuery(sizeQ);
+        int sizeAll = objects1.size();
+        assertEquals(size, sizeAll - 5);
+    }
+
+    public void testFetchLimitWithQualifier() throws Exception {
+        createArtistsDataSet();
+        SelectQuery<Artist> query = new SelectQuery<Artist>(Artist.class);
+        query.setQualifier(Expression.fromString("db:ARTIST_ID > 3"));
+        query.setFetchLimit(7);
+        List<?> objects = context.performQuery(query);
+        assertEquals(7, objects.size());
+    }
+
+    public void testSelectAllObjectsRootEntityName() throws Exception {
+        createArtistsDataSet();
+        SelectQuery<Artist> query = new SelectQuery<Artist>("Artist");
+        List<?> objects = context.performQuery(query);
+        assertEquals(20, objects.size());
+    }
+
+    public void testSelectAllObjectsRootClass() throws Exception {
+        createArtistsDataSet();
+        SelectQuery<Artist> query = new SelectQuery<Artist>(Artist.class);
+        List<?> objects = context.performQuery(query);
+        assertEquals(20, objects.size());
+    }
+
+    public void testSelectAllObjectsRootObjEntity() throws Exception {
+        createArtistsDataSet();
+        ObjEntity artistEntity = context.getEntityResolver().getObjEntity(Artist.class);
+        SelectQuery<Artist> query = new SelectQuery<Artist>(artistEntity);
+
+        List<?> objects = context.performQuery(query);
+        assertEquals(20, objects.size());
+    }
+
+    public void testSelectLikeExactMatch() throws Exception {
+        createArtistsDataSet();
+        SelectQuery<Artist> query = new SelectQuery<Artist>(Artist.class);
+        Expression qual = ExpressionFactory.likeExp("artistName", "artist1");
+        query.setQualifier(qual);
+        List<?> objects = context.performQuery(query);
+        assertEquals(1, objects.size());
+    }
+
+    public void testSelectNotLikeSingleWildcardMatch() throws Exception {
+        createArtistsDataSet();
+        SelectQuery<Artist> query = new SelectQuery<Artist>(Artist.class);
+        Expression qual = ExpressionFactory.notLikeExp("artistName", "artist11%");
+        query.setQualifier(qual);
+        List<?> objects = context.performQuery(query);
+        assertEquals(19, objects.size());
+    }
+
+    public void testSelectNotLikeIgnoreCaseSingleWildcardMatch() throws Exception {
+        createArtistsDataSet();
+        SelectQuery<Artist> query = new SelectQuery<Artist>(Artist.class);
+        Expression qual = ExpressionFactory.notLikeIgnoreCaseExp("artistName", "aRtIsT11%");
+        query.setQualifier(qual);
+        List<?> objects = context.performQuery(query);
+        assertEquals(19, objects.size());
+    }
+
+    public void testSelectLikeCaseSensitive() throws Exception {
+        if (!accessStackAdapter.supportsCaseSensitiveLike()) {
+            return;
+        }
+
+        createArtistsDataSet();
+        SelectQuery<Artist> query = new SelectQuery<Artist>(Artist.class);
+        Expression qual = ExpressionFactory.likeExp("artistName", "aRtIsT%");
+        query.setQualifier(qual);
+        List<?> objects = context.performQuery(query);
+        assertEquals(0, objects.size());
+    }
+
+    public void testSelectLikeSingleWildcardMatch() throws Exception {
+        createArtistsDataSet();
+        SelectQuery<Artist> query = new SelectQuery<Artist>(Artist.class);
+        Expression qual = ExpressionFactory.likeExp("artistName", "artist11%");
+        query.setQualifier(qual);
+        List<?> objects = context.performQuery(query);
+        assertEquals(1, objects.size());
+    }
+
+    public void testSelectLikeSingleWildcardMatchAndEscape() throws Exception {
+
+        createArtistsWildcardDataSet();
+
+        SelectQuery<Artist> query = new SelectQuery<Artist>(Artist.class);
+        query.andQualifier(ExpressionFactory.likeExp("artistName", "=_%", '='));
+
+        List<?> objects = context.performQuery(query);
+        assertEquals(1, objects.size());
+    }
+
+    public void testSelectLikeMultipleWildcardMatch() throws Exception {
+        createArtistsDataSet();
+        SelectQuery<Artist> query = new SelectQuery<Artist>(Artist.class);
+        Expression qual = ExpressionFactory.likeExp("artistName", "artist1%");
+        query.setQualifier(qual);
+        List<?> objects = context.performQuery(query);
+        assertEquals(11, objects.size());
+    }
+
+    /**
+     * Test how "like ignore case" works when using uppercase parameter.
+     */
+    public void testSelectLikeIgnoreCaseObjects1() throws Exception {
+        createArtistsDataSet();
+        SelectQuery<Artist> query = new SelectQuery<Artist>(Artist.class);
+        Expression qual = ExpressionFactory.likeIgnoreCaseExp("artistName", "ARTIST%");
+        query.setQualifier(qual);
+        List<?> objects = context.performQuery(query);
+        assertEquals(20, objects.size());
+    }
+
+    /** Test how "like ignore case" works when using lowercase parameter. */
+    public void testSelectLikeIgnoreCaseObjects2() throws Exception {
+        createArtistsDataSet();
+        SelectQuery<Artist> query = new SelectQuery<Artist>(Artist.class);
+        Expression qual = ExpressionFactory.likeIgnoreCaseExp("artistName", "artist%");
+        query.setQualifier(qual);
+        List<?> objects = context.performQuery(query);
+        assertEquals(20, objects.size());
+    }
+
+    /** Test how "like ignore case" works when using uppercase parameter. */
+    public void testSelectLikeIgnoreCaseClob() throws Exception {
+        if (accessStackAdapter.supportsLobs()) {
+            createClobDataSet();
+            SelectQuery<ClobTestEntity> query = new SelectQuery<ClobTestEntity>(ClobTestEntity.class);
+            Expression qual = ExpressionFactory.likeIgnoreCaseExp("clobCol", "clob%");
+            query.setQualifier(qual);
+            List<?> objects = context.performQuery(query);
+            assertEquals(2, objects.size());
+        }
+    }
+
+    public void testSelectFetchLimit_Offset_DistinctClob() throws Exception {
+        if (accessStackAdapter.supportsLobs()) {
+            createClobDataSet();
+
+            // see CAY-1539... CLOB column causes suppression of DISTINCT in
+            // SQL, and hence the offset processing is done in memory
+            SelectQuery<ClobTestEntity> query = new SelectQuery<ClobTestEntity>(ClobTestEntity.class);
+            query.addOrdering("db:" + ClobTestEntity.CLOB_TEST_ID_PK_COLUMN, SortOrder.ASCENDING);
+            query.setFetchLimit(1);
+            query.setFetchOffset(1);
+            query.setDistinct(true);
+
+            List<ClobTestEntity> objects = context.performQuery(query);
+            assertEquals(1, objects.size());
+            assertEquals(2, Cayenne.intPKForObject(objects.get(0)));
+        }
+    }
+
+    public void testSelectEqualsClob() throws Exception {
+        if (accessStackAdapter.supportsLobComparisons()) {
+            createClobDataSet();
+            SelectQuery<ClobTestEntity> query = new SelectQuery<ClobTestEntity>(ClobTestEntity.class);
+            Expression qual = ExpressionFactory.matchExp("clobCol", "clob1");
+            query.setQualifier(qual);
+            List<?> objects = context.performQuery(query);
+            assertEquals(1, objects.size());
+        }
+    }
+
+    public void testSelectNotEqualsClob() throws Exception {
+        if (accessStackAdapter.supportsLobComparisons()) {
+            createClobDataSet();
+            SelectQuery query = new SelectQuery(ClobTestEntity.class);
+            Expression qual = ExpressionFactory.noMatchExp("clobCol", "clob1");
+            query.setQualifier(qual);
+            List<?> objects = context.performQuery(query);
+            assertEquals(1, objects.size());
+        }
+    }
+
+    public void testSelectIn() throws Exception {
+        createArtistsDataSet();
+        SelectQuery query = new SelectQuery(Artist.class);
+        Expression qual = Expression.fromString("artistName in ('artist1', 'artist2')");
+        query.setQualifier(qual);
+        List<?> objects = context.performQuery(query);
+        assertEquals(2, objects.size());
+    }
+
+    public void testSelectParameterizedIn() throws Exception {
+        createArtistsDataSet();
+        SelectQuery query = new SelectQuery(Artist.class);
+        Expression qual = Expression.fromString("artistName in $list");
+        query.setQualifier(qual);
+        query = query.queryWithParameters(Collections.singletonMap("list", new Object[] { "artist1", "artist2" }));
+        List<?> objects = context.performQuery(query);
+        assertEquals(2, objects.size());
+    }
+
+    public void testSelectParameterizedEmptyIn() throws Exception {
+        createArtistsDataSet();
+        SelectQuery query = new SelectQuery(Artist.class);
+        Expression qual = Expression.fromString("artistName in $list");
+        query.setQualifier(qual);
+        query = query.queryWithParameters(Collections.singletonMap("list", new Object[] {}));
+        List<?> objects = context.performQuery(query);
+        assertEquals(0, objects.size());
+    }
+
+    public void testSelectParameterizedEmptyNotIn() throws Exception {
+        createArtistsDataSet();
+        SelectQuery query = new SelectQuery(Artist.class);
+        Expression qual = Expression.fromString("artistName not in $list");
+        query.setQualifier(qual);
+        query = query.queryWithParameters(Collections.singletonMap("list", new Object[] {}));
+        List<?> objects = context.performQuery(query);
+        assertEquals(20, objects.size());
+    }
+
+    public void testSelectEmptyIn() throws Exception {
+        createArtistsDataSet();
+        SelectQuery query = new SelectQuery(Artist.class);
+        Expression qual = ExpressionFactory.inExp("artistName");
+        query.setQualifier(qual);
+        List<?> objects = context.performQuery(query);
+        assertEquals(0, objects.size());
+    }
+
+    public void testSelectEmptyNotIn() throws Exception {
+        createArtistsDataSet();
+        SelectQuery query = new SelectQuery(Artist.class);
+        Expression qual = ExpressionFactory.notInExp("artistName");
+        query.setQualifier(qual);
+        List<?> objects = context.performQuery(query);
+        assertEquals(20, objects.size());
+    }
+
+    public void testSelectBooleanTrue() throws Exception {
+        createArtistsDataSet();
+        SelectQuery query = new SelectQuery(Artist.class);
+        Expression qual = ExpressionFactory.expTrue();
+        qual = qual.andExp(ExpressionFactory.matchExp("artistName", "artist1"));
+        query.setQualifier(qual);
+        List<?> objects = context.performQuery(query);
+        assertEquals(1, objects.size());
+    }
+
+    public void testSelectBitwiseNot() throws Exception {
+
+        if (!accessStackAdapter.supportsBitwiseOps()) {
+            return;
+        }
+
+        createNumericsDataSet();
+
+        // to simplify result checking, do double NOT
+        Expression left = new ASTBitwiseNot(new ASTBitwiseNot(new ASTObjPath(ReturnTypesMap1.INTEGER_COLUMN_PROPERTY)));
+        Expression right = new ASTScalar(2);
+        Expression greater = new ASTGreater();
+        greater.setOperand(0, left);
+        greater.setOperand(1, right);
+
+        SelectQuery query = new SelectQuery(ReturnTypesMap1.class);
+        query.setQualifier(greater);
+
+        List<ReturnTypesMap1> objects = context.performQuery(query);
+        assertEquals(2, objects.size());
+    }
+
+    public void testSelectBitwiseOr() throws Exception {
+
+        if (!accessStackAdapter.supportsBitwiseOps()) {
+            return;
+        }
+
+        createNumericsDataSet();
+
+        // to simplify result checking, do double NOT
+        Expression left = new ASTBitwiseOr(new Object[] { new ASTObjPath(ReturnTypesMap1.INTEGER_COLUMN_PROPERTY),
+                new ASTScalar(1) });
+        Expression right = new ASTScalar(1);
+        Expression equal = new ASTEqual();
+        equal.setOperand(0, left);
+        equal.setOperand(1, right);
+
+        SelectQuery query = new SelectQuery(ReturnTypesMap1.class);
+        query.setQualifier(equal);
+
+        List<ReturnTypesMap1> objects = context.performQuery(query);
+        assertEquals(2, objects.size());
+    }
+
+    public void testSelectBitwiseAnd() throws Exception {
+
+        if (!accessStackAdapter.supportsBitwiseOps()) {
+            return;
+        }
+
+        createNumericsDataSet();
+
+        // to simplify result checking, do double NOT
+        Expression left = new ASTBitwiseAnd(new Object[] { new ASTObjPath(ReturnTypesMap1.INTEGER_COLUMN_PROPERTY),
+                new ASTScalar(1) });
+        Expression right = new ASTScalar(0);
+        Expression equal = new ASTEqual();
+        equal.setOperand(0, left);
+        equal.setOperand(1, right);
+
+        SelectQuery query = new SelectQuery(ReturnTypesMap1.class);
+        query.setQualifier(equal);
+
+        List<ReturnTypesMap1> objects = context.performQuery(query);
+        assertEquals(3, objects.size());
+    }
+
+    public void testSelectBitwiseXor() throws Exception {
+
+        if (!accessStackAdapter.supportsBitwiseOps()) {
+            return;
+        }
+
+        createNumericsDataSet();
+
+        // to simplify result checking, do double NOT
+        Expression left = new ASTBitwiseXor(new Object[] { new ASTObjPath(ReturnTypesMap1.INTEGER_COLUMN_PROPERTY),
+                new ASTScalar(1) });
+        Expression right = new ASTScalar(5);
+        Expression equal = new ASTEqual();
+        equal.setOperand(0, left);
+        equal.setOperand(1, right);
+
+        SelectQuery query = new SelectQuery(ReturnTypesMap1.class);
+        query.setQualifier(equal);
+
+        List<ReturnTypesMap1> objects = context.performQuery(query);
+        assertEquals(1, objects.size());
+        assertEquals(4, objects.get(0).getIntegerColumn().intValue());
+    }
+
+    public void testSelectBooleanNotTrueOr() throws Exception {
+        createArtistsDataSet();
+        SelectQuery query = new SelectQuery(Artist.class);
+        Expression qual = ExpressionFactory.expTrue();
+        qual = qual.notExp();
+        qual = qual.orExp(ExpressionFactory.matchExp("artistName", "artist1"));
+        query.setQualifier(qual);
+        List<?> objects = context.performQuery(query);
+        assertEquals(1, objects.size());
+    }
+
+    public void testSelectBooleanFalse() throws Exception {
+        createArtistsDataSet();
+        SelectQuery query = new SelectQuery(Artist.class);
+        Expression qual = ExpressionFactory.expFalse();
+        qual = qual.andExp(ExpressionFactory.matchExp("artistName", "artist1"));
+        query.setQualifier(qual);
+        List<?> objects = context.performQuery(query);
+        assertEquals(0, objects.size());
+    }
+
+    public void testSelectBooleanFalseOr() throws Exception {
+        createArtistsDataSet();
+        SelectQuery query = new SelectQuery(Artist.class);
+        Expression qual = ExpressionFactory.expFalse();
+        qual = qual.orExp(ExpressionFactory.matchExp("artistName", "artist1"));
+        query.setQualifier(qual);
+        List<?> objects = context.performQuery(query);
+        assertEquals(1, objects.size());
+    }
+
+    /**
+     * Tests that all queries specified in prefetch are executed in a more
+     * complex prefetch scenario.
+     */
+    public void testRouteWithPrefetches() {
+        EntityResolver resolver = context.getEntityResolver();
+        MockQueryRouter router = new MockQueryRouter();
+
+        SelectQuery<Artist> q = new SelectQuery<Artist>(Artist.class, ExpressionFactory.matchExp("artistName", "a"));
+
+        q.route(router, resolver, null);
+        assertEquals(1, router.getQueryCount());
+
+        q.addPrefetch("paintingArray");
+        router.reset();
+        q.route(router, resolver, null);
+        assertEquals(2, router.getQueryCount());
+
+        q.addPrefetch("paintingArray.toGallery");
+        router.reset();
+        q.route(router, resolver, null);
+        assertEquals(3, router.getQueryCount());
+
+        q.addPrefetch("artistExhibitArray.toExhibit");
+        router.reset();
+        q.route(router, resolver, null);
+        assertEquals(4, router.getQueryCount());
+
+        q.removePrefetch("paintingArray");
+        router.reset();
+        q.route(router, resolver, null);
+        assertEquals(3, router.getQueryCount());
+    }
+
+    /**
+     * Tests that all queries specified in prefetch are executed in a more
+     * complex prefetch scenario with no reverse obj relationships.
+     */
+    public void testRouteQueryWithPrefetchesNoReverse() {
+
+        EntityResolver resolver = context.getEntityResolver();
+        ObjEntity paintingEntity = resolver.getObjEntity(Painting.class);
+        ObjEntity galleryEntity = resolver.getObjEntity(Gallery.class);
+        ObjEntity artistExhibitEntity = resolver.getObjEntity(ArtistExhibit.class);
+        ObjEntity exhibitEntity = resolver.getObjEntity(Exhibit.class);
+        ObjRelationship paintingToArtistRel = paintingEntity.getRelationship("toArtist");
+        paintingEntity.removeRelationship("toArtist");
+
+        ObjRelationship galleryToPaintingRel = galleryEntity.getRelationship("paintingArray");
+        galleryEntity.removeRelationship("paintingArray");
+
+        ObjRelationship artistExhibitToArtistRel = artistExhibitEntity.getRelationship("toArtist");
+        artistExhibitEntity.removeRelationship("toArtist");
+
+        ObjRelationship exhibitToArtistExhibitRel = exhibitEntity.getRelationship("artistExhibitArray");
+        exhibitEntity.removeRelationship("artistExhibitArray");
+
+        Expression e = ExpressionFactory.matchExp("artistName", "artist1");
+        SelectQuery<Artist> q = new SelectQuery<Artist>(Artist.class, e);
+        q.addPrefetch("paintingArray");
+        q.addPrefetch("paintingArray.toGallery");
+        q.addPrefetch("artistExhibitArray.toExhibit");
+
+        try {
+            MockQueryRouter router = new MockQueryRouter();
+            q.route(router, resolver, null);
+            assertEquals(4, router.getQueryCount());
+        } finally {
+            paintingEntity.addRelationship(paintingToArtistRel);
+            galleryEntity.addRelationship(galleryToPaintingRel);
+            artistExhibitEntity.addRelationship(artistExhibitToArtistRel);
+            exhibitEntity.addRelationship(exhibitToArtistExhibitRel);
+        }
+    }
+
+    /**
+     * Test prefetching with qualifier on the root query being the path to the
+     * prefetch.
+     */
+    public void testRouteQueryWithPrefetchesPrefetchExpressionPath() {
+
+        // find the painting not matching the artist (this is the case where
+        // such prefetch
+        // at least makes sense)
+        Expression exp = ExpressionFactory.noMatchExp("toArtist", new Object());
+
+        SelectQuery q = new SelectQuery(Painting.class, exp);
+        q.addPrefetch("toArtist");
+
+        // test how prefetches are resolved in this case - this was a stumbling
+        // block for
+        // a while
+        EntityResolver resolver = context.getEntityResolver();
+        MockQueryRouter router = new MockQueryRouter();
+        q.route(router, resolver, null);
+        assertEquals(2, router.getQueryCount());
+    }
+
+    public void testLeftJoinAndPrefetchToMany() throws Exception {
+        createArtistsDataSet();
+        SelectQuery<Artist> query = new SelectQuery<Artist>(Artist.class, ExpressionFactory.matchExp(
+                "paintingArray+.toGallery", null));
+        query.addPrefetch("artistExhibitArray");
+        context.performQuery(query);
+    }
+
+    public void testLeftJoinAndPrefetchToOne() throws Exception {
+        createArtistsDataSet();
+        SelectQuery<Painting> query = new SelectQuery<Painting>(Painting.class, ExpressionFactory.matchExp(
+                "toArtist+.artistName", null));
+        query.addPrefetch("toGallery");
+        context.select(query);
+    }
+
+    public void testSelect_MatchObject() {
+
+        Artist a1 = context.newObject(Artist.class);
+        a1.setArtistName("a1");
+        Artist a2 = context.newObject(Artist.class);
+        a2.setArtistName("a2");
+        Artist a3 = context.newObject(Artist.class);
+        a3.setArtistName("a3");
+        context.commitChanges();
+
+        SelectQuery<Artist> query = new SelectQuery<Artist>(Artist.class);
+
+        query.setQualifier(ExpressionFactory.matchExp(a2));
+        Object res = Cayenne.objectForQuery(context, query);// exception if >1
+                                                            // result
+        assertSame(res, a2);
+        assertTrue(query.getQualifier().match(res));
+
+        query.setQualifier(ExpressionFactory.matchAnyExp(a1, a3));
+        query.addOrdering("artistName", SortOrder.ASCENDING);
+        List<Artist> list = context.select(query);
+        assertEquals(list.size(), 2);
+        assertSame(list.get(0), a1);
+        assertSame(list.get(1), a3);
+        assertTrue(query.getQualifier().match(a1));
+        assertTrue(query.getQualifier().match(a3));
+
+        assertEquals(query.getQualifier(), ExpressionFactory.matchAnyExp(Arrays.asList(a1, a3)));
+    }
+
+    public void testSelect_WithOrdering() {
+
+        Artist a1 = context.newObject(Artist.class);
+        a1.setArtistName("a1");
+        Artist a2 = context.newObject(Artist.class);
+        a2.setArtistName("a2");
+        Artist a3 = context.newObject(Artist.class);
+        a3.setArtistName("a3");
+        context.commitChanges();
+
+        List<Ordering> orderings = Arrays.asList(new Ordering("artistName", SortOrder.ASCENDING));
+        SelectQuery<Artist> query = new SelectQuery<Artist>(Artist.class, null, orderings);
+
+        List<Artist> list = context.select(query);
+        assertEquals(list.size(), 3);
+        assertSame(list.get(0), a1);
+        assertSame(list.get(1), a2);
+        assertSame(list.get(2), a3);
+    }
+
+    /**
+     * Tests INs with more than 1000 elements
+     */
+    public void testSelectLongIn() {
+        // not all adapters strip INs, so we just make sure query with such
+        // qualifier
+        // fires OK
+        Object[] numbers = new String[2009];
+        for (int i = 0; i < numbers.length; i++) {
+            numbers[i] = "" + i;
+        }
+
+        SelectQuery<Artist> query = new SelectQuery<Artist>(Artist.class,
+                ExpressionFactory.inExp("artistName", numbers));
+        context.performQuery(query);
+    }
+
+    public void testCacheOffsetAndLimit() throws Exception {
+        createArtistsDataSet();
+
+        SelectQuery<Artist> query1 = new SelectQuery<Artist>(Artist.class);
+        query1.setCacheStrategy(QueryCacheStrategy.SHARED_CACHE);
+        query1.setFetchOffset(0);
+        query1.setFetchLimit(10);
+        context.performQuery(query1);
+
+        SelectQuery<Artist> query2 = new SelectQuery<Artist>(Artist.class);
+        query2.setCacheStrategy(QueryCacheStrategy.SHARED_CACHE);
+        query2.setFetchOffset(10);
+        query2.setFetchLimit(10);
+        context.performQuery(query2);
+
+        SelectQuery<Artist> query3 = new SelectQuery<Artist>(Artist.class);
+        query3.setCacheStrategy(QueryCacheStrategy.SHARED_CACHE);
+        query3.setFetchOffset(10);
+        query3.setFetchLimit(10);
+        context.performQuery(query3);
+
+        assertFalse(query1.metaData.getCacheKey().equals(query2.metaData.cacheKey));
+        assertEquals(query2.metaData.getCacheKey(), query3.metaData.getCacheKey());
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/e42c376c/cayenne-server/src/test/java/org/apache/cayenne/query/SelectQueryPrefetchRouterActionIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/query/SelectQueryPrefetchRouterActionIT.java b/cayenne-server/src/test/java/org/apache/cayenne/query/SelectQueryPrefetchRouterActionIT.java
new file mode 100644
index 0000000..df2b2f1
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/query/SelectQueryPrefetchRouterActionIT.java
@@ -0,0 +1,90 @@
+/*****************************************************************
+ *   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.cayenne.query;
+
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.exp.Expression;
+import org.apache.cayenne.exp.ExpressionFactory;
+import org.apache.cayenne.map.EntityResolver;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.testdo.testmap.Artist;
+import org.apache.cayenne.testdo.testmap.Gallery;
+import org.apache.cayenne.testdo.testmap.Painting;
+import org.apache.cayenne.unit.di.server.ServerCase;
+import org.apache.cayenne.unit.di.server.UseServerRuntime;
+
+@UseServerRuntime(ServerCase.TESTMAP_PROJECT)
+public class SelectQueryPrefetchRouterActionIT extends ServerCase {
+
+    @Inject
+    private EntityResolver resolver;
+
+    public void testPaintings1() {
+        ObjEntity paintingEntity = resolver.getObjEntity(Painting.class);
+        SelectQuery q = new SelectQuery(Artist.class, ExpressionFactory.matchExp("artistName", "abc"));
+        q.addPrefetch(Artist.PAINTING_ARRAY_PROPERTY);
+
+        SelectQueryPrefetchRouterAction action = new SelectQueryPrefetchRouterAction();
+
+        MockQueryRouter router = new MockQueryRouter();
+        action.route(q, router, resolver);
+        assertEquals(1, router.getQueryCount());
+
+        PrefetchSelectQuery prefetch = (PrefetchSelectQuery) router.getQueries().get(0);
+
+        assertSame(paintingEntity, prefetch.getRoot());
+        assertEquals(Expression.fromString("db:toArtist.ARTIST_NAME = 'abc'"), prefetch.getQualifier());
+    }
+
+    public void testPrefetchPaintings2() {
+        ObjEntity paintingEntity = resolver.getObjEntity(Painting.class);
+
+        SelectQuery q = new SelectQuery(Artist.class, Expression.fromString("artistName = 'abc' or artistName = 'xyz'"));
+        q.addPrefetch(Artist.PAINTING_ARRAY_PROPERTY);
+
+        SelectQueryPrefetchRouterAction action = new SelectQueryPrefetchRouterAction();
+
+        MockQueryRouter router = new MockQueryRouter();
+        action.route(q, router, resolver);
+        assertEquals(1, router.getQueryCount());
+
+        PrefetchSelectQuery prefetch = (PrefetchSelectQuery) router.getQueries().get(0);
+        assertSame(paintingEntity, prefetch.getRoot());
+        assertEquals(Expression.fromString("db:toArtist.ARTIST_NAME = 'abc' or db:toArtist.ARTIST_NAME = 'xyz'"),
+                prefetch.getQualifier());
+    }
+
+    public void testGalleries() {
+        ObjEntity galleryEntity = resolver.getObjEntity(Gallery.class);
+        SelectQuery q = new SelectQuery(Artist.class, ExpressionFactory.matchExp("artistName", "abc"));
+        q.addPrefetch("paintingArray.toGallery");
+
+        SelectQueryPrefetchRouterAction action = new SelectQueryPrefetchRouterAction();
+
+        MockQueryRouter router = new MockQueryRouter();
+        action.route(q, router, resolver);
+        assertEquals(1, router.getQueryCount());
+
+        PrefetchSelectQuery prefetch = (PrefetchSelectQuery) router.getQueries().get(0);
+
+        assertSame(galleryEntity, prefetch.getRoot());
+        assertEquals(Expression.fromString("db:paintingArray.toArtist.ARTIST_NAME = 'abc'"), prefetch.getQualifier());
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/e42c376c/cayenne-server/src/test/java/org/apache/cayenne/query/SelectQueryPrefetchRouterActionQualifiedEntityIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/query/SelectQueryPrefetchRouterActionQualifiedEntityIT.java b/cayenne-server/src/test/java/org/apache/cayenne/query/SelectQueryPrefetchRouterActionQualifiedEntityIT.java
new file mode 100644
index 0000000..60361ca
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/query/SelectQueryPrefetchRouterActionQualifiedEntityIT.java
@@ -0,0 +1,75 @@
+/*****************************************************************
+ *   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.cayenne.query;
+
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.exp.Expression;
+import org.apache.cayenne.exp.ExpressionFactory;
+import org.apache.cayenne.map.EntityResolver;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.testdo.inherit.Department;
+import org.apache.cayenne.testdo.inherit.Employee;
+import org.apache.cayenne.testdo.inherit.Manager;
+import org.apache.cayenne.unit.di.server.ServerCase;
+import org.apache.cayenne.unit.di.server.UseServerRuntime;
+
+@UseServerRuntime(ServerCase.PEOPLE_PROJECT)
+public class SelectQueryPrefetchRouterActionQualifiedEntityIT extends ServerCase {
+
+    @Inject
+    private EntityResolver resolver;
+
+    public void testPrefetchEmployee() throws Exception {
+        ObjEntity departmentEntity = resolver.getObjEntity(Department.class);
+        SelectQuery q = new SelectQuery(Employee.class, ExpressionFactory.matchExp("name", "abc"));
+
+        q.addPrefetch(Employee.TO_DEPARTMENT_PROPERTY);
+
+        SelectQueryPrefetchRouterAction action = new SelectQueryPrefetchRouterAction();
+
+        MockQueryRouter router = new MockQueryRouter();
+        action.route(q, router, resolver);
+        assertEquals(1, router.getQueryCount());
+
+        PrefetchSelectQuery prefetch = (PrefetchSelectQuery) router.getQueries().get(0);
+
+        assertSame(departmentEntity, prefetch.getRoot());
+        assertEquals(Expression.fromString("db:employees.NAME = 'abc' " + "and (db:employees.PERSON_TYPE = 'EE' "
+                + "or db:employees.PERSON_TYPE = 'EM')"), prefetch.getQualifier());
+    }
+
+    public void testPrefetchManager() throws Exception {
+        ObjEntity departmentEntity = resolver.getObjEntity(Department.class);
+        SelectQuery q = new SelectQuery(Manager.class, ExpressionFactory.matchExp("name", "abc"));
+
+        q.addPrefetch(Employee.TO_DEPARTMENT_PROPERTY);
+
+        SelectQueryPrefetchRouterAction action = new SelectQueryPrefetchRouterAction();
+
+        MockQueryRouter router = new MockQueryRouter();
+        action.route(q, router, resolver);
+        assertEquals(1, router.getQueryCount());
+
+        PrefetchSelectQuery prefetch = (PrefetchSelectQuery) router.getQueries().get(0);
+        assertSame(departmentEntity, prefetch.getRoot());
+        assertEquals(Expression.fromString("db:employees.NAME = 'abc' and db:employees.PERSON_TYPE = 'EM'"),
+                prefetch.getQualifier());
+    }
+}