/tests/com/google/appengine/datanucleus/query/JPQLQueryTest.java

http://datanucleus-appengine.googlecode.com/ · Java · 3434 lines · 2943 code · 393 blank · 98 comment · 47 complexity · 3aab801a7e71a928c5a79dcec9a57053 MD5 · raw file

Large files are truncated click here to view the full file

  1. /**********************************************************************
  2. Copyright (c) 2009 Google Inc.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. **********************************************************************/
  13. package com.google.appengine.datanucleus.query;
  14. import com.google.appengine.api.datastore.DatastoreFailureException;
  15. import com.google.appengine.api.datastore.DatastoreTimeoutException;
  16. import com.google.appengine.api.datastore.Entity;
  17. import com.google.appengine.api.datastore.Key;
  18. import com.google.appengine.api.datastore.KeyFactory;
  19. import com.google.appengine.api.datastore.Query.FilterOperator;
  20. import com.google.appengine.api.datastore.Query.FilterPredicate;
  21. import com.google.appengine.api.datastore.Query.SortDirection;
  22. import com.google.appengine.api.datastore.Query.SortPredicate;
  23. import com.google.appengine.api.datastore.ShortBlob;
  24. import com.google.appengine.api.datastore.dev.LocalDatastoreService;
  25. import com.google.appengine.datanucleus.DatastoreManager;
  26. import com.google.appengine.datanucleus.DatastoreServiceFactoryInternal;
  27. import com.google.appengine.datanucleus.DatastoreServiceInterceptor;
  28. import com.google.appengine.datanucleus.ExceptionThrowingDatastoreDelegate;
  29. import com.google.appengine.datanucleus.PrimitiveArrays;
  30. import com.google.appengine.datanucleus.TestUtils;
  31. import com.google.appengine.datanucleus.Utils;
  32. import com.google.appengine.datanucleus.WriteBlocker;
  33. import com.google.appengine.datanucleus.jpa.JPATestCase;
  34. import com.google.appengine.datanucleus.test.jdo.Flight;
  35. import com.google.appengine.datanucleus.test.jdo.KitchenSink;
  36. import com.google.appengine.datanucleus.test.jdo.Person;
  37. import com.google.appengine.datanucleus.test.jpa.BidirectionalChildListJPA;
  38. import com.google.appengine.datanucleus.test.jpa.BidirectionalChildLongPkListJPA;
  39. import com.google.appengine.datanucleus.test.jpa.BidirectionalGrandchildListJPA;
  40. import com.google.appengine.datanucleus.test.jpa.Book;
  41. import com.google.appengine.datanucleus.test.jpa.DetachableJPA;
  42. import com.google.appengine.datanucleus.test.jpa.HasBytesJPA;
  43. import com.google.appengine.datanucleus.test.jpa.HasDoubleJPA;
  44. import com.google.appengine.datanucleus.test.jpa.HasEncodedStringPkJPA;
  45. import com.google.appengine.datanucleus.test.jpa.HasEncodedStringPkSeparateIdFieldJPA;
  46. import com.google.appengine.datanucleus.test.jpa.HasEncodedStringPkSeparateNameFieldJPA;
  47. import com.google.appengine.datanucleus.test.jpa.HasEnumJPA;
  48. import com.google.appengine.datanucleus.test.jpa.HasFloatJPA;
  49. import com.google.appengine.datanucleus.test.jpa.HasKeyAncestorStringPkJPA;
  50. import com.google.appengine.datanucleus.test.jpa.HasKeyPkJPA;
  51. import com.google.appengine.datanucleus.test.jpa.HasLongPkJPA;
  52. import com.google.appengine.datanucleus.test.jpa.HasMultiValuePropsJPA;
  53. import com.google.appengine.datanucleus.test.jpa.HasOneToManyKeyPkListJPA;
  54. import com.google.appengine.datanucleus.test.jpa.HasOneToManyKeyPkSetJPA;
  55. import com.google.appengine.datanucleus.test.jpa.HasOneToManyListJPA;
  56. import com.google.appengine.datanucleus.test.jpa.HasOneToManyLongPkListJPA;
  57. import com.google.appengine.datanucleus.test.jpa.HasOneToManyLongPkSetJPA;
  58. import com.google.appengine.datanucleus.test.jpa.HasOneToManyUnencodedStringPkListJPA;
  59. import com.google.appengine.datanucleus.test.jpa.HasOneToManyUnencodedStringPkSetJPA;
  60. import com.google.appengine.datanucleus.test.jpa.HasOneToOneJPA;
  61. import com.google.appengine.datanucleus.test.jpa.HasOneToOneParentJPA;
  62. import com.google.appengine.datanucleus.test.jpa.HasStringAncestorStringPkJPA;
  63. import com.google.appengine.datanucleus.test.jpa.HasUnencodedStringPkJPA;
  64. import com.google.appengine.datanucleus.test.jpa.InTheHouseJPA;
  65. import com.google.appengine.datanucleus.test.jpa.NullDataJPA;
  66. import com.google.appengine.datanucleus.test.jpa.AbstractBaseClassesJPA.Base1;
  67. import com.google.appengine.datanucleus.test.jpa.UnidirectionalSingeTableChildJPA.UnidirTop;
  68. import com.google.apphosting.api.ApiProxy;
  69. import com.google.apphosting.api.DatastorePb;
  70. import org.datanucleus.api.jpa.JPAQuery;
  71. import org.datanucleus.exceptions.NucleusFatalUserException;
  72. import org.datanucleus.exceptions.NucleusUserException;
  73. import org.datanucleus.query.expression.Expression;
  74. import org.easymock.EasyMock;
  75. import java.io.ByteArrayOutputStream;
  76. import java.io.IOException;
  77. import java.io.ObjectOutputStream;
  78. import java.math.BigDecimal;
  79. import java.util.Arrays;
  80. import java.util.Collections;
  81. import java.util.Date;
  82. import java.util.HashMap;
  83. import java.util.HashSet;
  84. import java.util.Iterator;
  85. import java.util.List;
  86. import java.util.Map;
  87. import java.util.Set;
  88. import java.util.concurrent.ExecutionException;
  89. import java.util.concurrent.Future;
  90. import javax.persistence.NoResultException;
  91. import javax.persistence.NonUniqueResultException;
  92. import javax.persistence.PersistenceException;
  93. import javax.persistence.Query;
  94. import javax.persistence.QueryTimeoutException;
  95. import javax.persistence.TypedQuery;
  96. import static com.google.appengine.datanucleus.test.jdo.Flight.newFlightEntity;
  97. /**
  98. * @author Max Ross <maxr@google.com>
  99. */
  100. public class JPQLQueryTest extends JPATestCase {
  101. private static final List<SortPredicate> NO_SORTS = Collections.emptyList();
  102. private static final List<FilterPredicate> NO_FILTERS = Collections.emptyList();
  103. private static final FilterPredicate TITLE_EQ_2 =
  104. new FilterPredicate("title", FilterOperator.EQUAL, 2L);
  105. private static final FilterPredicate TITLE_EQ_2STR =
  106. new FilterPredicate("title", FilterOperator.EQUAL, "2");
  107. private static final FilterPredicate ISBN_EQ_4 =
  108. new FilterPredicate("isbn", FilterOperator.EQUAL, 4L);
  109. private static final FilterPredicate TITLE_GT_2 =
  110. new FilterPredicate("title", FilterOperator.GREATER_THAN, 2L);
  111. private static final FilterPredicate TITLE_GTE_2 =
  112. new FilterPredicate("title", FilterOperator.GREATER_THAN_OR_EQUAL, 2L);
  113. private static final FilterPredicate ISBN_LT_4 =
  114. new FilterPredicate("isbn", FilterOperator.LESS_THAN, 4L);
  115. private static final FilterPredicate ISBN_LTE_4 =
  116. new FilterPredicate("isbn", FilterOperator.LESS_THAN_OR_EQUAL, 4L);
  117. private static final FilterPredicate TITLE_NEQ_NULL_LITERAL =
  118. new FilterPredicate("title", FilterOperator.NOT_EQUAL, null);
  119. private static final FilterPredicate TITLE_NEQ_2_LITERAL =
  120. new FilterPredicate("title", FilterOperator.NOT_EQUAL, 2L);
  121. private static final SortPredicate TITLE_ASC =
  122. new SortPredicate("title", SortDirection.ASCENDING);
  123. private static final SortPredicate ISBN_DESC =
  124. new SortPredicate("isbn", SortDirection.DESCENDING);
  125. private static final FilterPredicate TITLE_IN_2_ARGS =
  126. new FilterPredicate("title", FilterOperator.IN, Arrays.asList("2", 2L));
  127. private static final FilterPredicate TITLE_IN_3_ARGS =
  128. new FilterPredicate("title", FilterOperator.IN, Arrays.asList("2", 2L, false));
  129. @Override
  130. protected void setUp() throws Exception {
  131. super.setUp();
  132. DatastoreServiceInterceptor.install(getStoreManager(), new WriteBlocker());
  133. }
  134. @Override
  135. protected void tearDown() throws Exception {
  136. try {
  137. super.tearDown();
  138. } finally {
  139. DatastoreServiceInterceptor.uninstall();
  140. }
  141. }
  142. @Override
  143. protected EntityManagerFactoryName getEntityManagerFactoryName() {
  144. return EntityManagerFactoryName.nontransactional_ds_non_transactional_ops_allowed;
  145. }
  146. public void testUnsupportedFilters_NoResultExpr() {
  147. String baseQuery = "SELECT FROM " + Book.class.getName() + " b ";
  148. testUnsupportedFilters(baseQuery);
  149. }
  150. public void testUnsupportedFilters_PrimaryResultExpr() {
  151. String baseQuery = "SELECT b FROM " + Book.class.getName() + " b ";
  152. testUnsupportedFilters(baseQuery);
  153. }
  154. private void testUnsupportedFilters(String baseQuery) {
  155. Set<Expression.Operator> unsupportedOps =
  156. new HashSet<Expression.Operator>(DatastoreQuery.UNSUPPORTED_OPERATORS);
  157. baseQuery += "WHERE ";
  158. assertQueryUnsupportedByOrm(baseQuery + "NOT title = 'foo'", Expression.OP_NOT, unsupportedOps);
  159. assertQueryUnsupportedByOrm(baseQuery + "(title + author) = 'foo'", Expression.OP_ADD,
  160. unsupportedOps);
  161. assertQueryUnsupportedByOrm(baseQuery + "title + author = 'foo'", Expression.OP_ADD,
  162. unsupportedOps);
  163. assertQueryUnsupportedByOrm(baseQuery + "(title - author) = 'foo'", Expression.OP_SUB,
  164. unsupportedOps);
  165. assertQueryUnsupportedByOrm(baseQuery + "title - author = 'foo'", Expression.OP_SUB,
  166. unsupportedOps);
  167. assertQueryUnsupportedByOrm(baseQuery + "(title / author) = 'foo'", Expression.OP_DIV,
  168. unsupportedOps);
  169. assertQueryUnsupportedByOrm(baseQuery + "title / author = 'foo'", Expression.OP_DIV,
  170. unsupportedOps);
  171. assertQueryUnsupportedByOrm(baseQuery + "(title * author) = 'foo'", Expression.OP_MUL,
  172. unsupportedOps);
  173. assertQueryUnsupportedByOrm(baseQuery + "title * author = 'foo'", Expression.OP_MUL,
  174. unsupportedOps);
  175. assertQueryUnsupportedByOrm(baseQuery + "(title % author) = 'foo'", Expression.OP_MOD,
  176. unsupportedOps);
  177. assertQueryUnsupportedByOrm(baseQuery + "title % author = 'foo'", Expression.OP_MOD,
  178. unsupportedOps);
  179. assertQueryRequiresUnsupportedDatastoreFeature(baseQuery + "title LIKE '%foo'");
  180. // can't have 'or' on multiple properties
  181. assertQueryRequiresUnsupportedDatastoreFeature(baseQuery + "title = 'yar' or author = null");
  182. assertQueryRequiresUnsupportedDatastoreFeature(baseQuery + "isbn = 4 and (title = 'yar' or author = 'yam')");
  183. assertQueryRequiresUnsupportedDatastoreFeature(baseQuery + "title IN('yar') or author = 'yam'");
  184. // can only check equality
  185. assertQueryRequiresUnsupportedDatastoreFeature(baseQuery + "title > 5 or title < 2");
  186. // multiple inequality filters
  187. // TODO(maxr) Make this pass against the real datastore.
  188. // We need to have it return BadRequest instead of NeedIndex for that to happen.
  189. assertQueryUnsupportedByDatastore(baseQuery + "(title > 2 AND isbn < 4)", IllegalArgumentException.class);
  190. // inequality filter prop is not the same as the first order by prop
  191. assertQueryUnsupportedByDatastore(baseQuery + "(title > 2) order by isbn", IllegalArgumentException.class);
  192. // gets split into multiple inequality props
  193. assertQueryUnsupportedByDatastore(baseQuery + "title <> 2 AND isbn <> 4", IllegalArgumentException.class);
  194. assertEquals(
  195. new HashSet<Expression.Operator>(Arrays.asList(Expression.OP_CONCAT, Expression.OP_COM,
  196. Expression.OP_NEG, Expression.OP_IS,
  197. Expression.OP_LIKE,
  198. Expression.OP_ISNOT)), unsupportedOps);
  199. }
  200. public void testEvaluateInMemory() {
  201. ds.put(null, newFlightEntity("1", "yar", "bam", 1, 2));
  202. ds.put(null, newFlightEntity("1", "yam", null, 1, 2));
  203. // This is impossible in the datastore, so run totally in-memory
  204. String query = "SELECT f FROM " + Flight.class.getName() + " f WHERE origin = 'yar' OR dest IS null";
  205. Query q = em.createQuery(query);
  206. q.setHint("datanucleus.query.evaluateInMemory", "true");
  207. try {
  208. List<Flight> results = (List<Flight>) q.getResultList();
  209. assertEquals("Number of results was wrong", 2, results.size());
  210. } catch (RuntimeException e) {
  211. fail("Threw exception when evaluating query in-memory, but should have run");
  212. }
  213. }
  214. public void testSupportedFilters_NoResultExpr() {
  215. String baseQuery = "SELECT FROM " + Book.class.getName() + " b ";
  216. testSupportedFilters(baseQuery);
  217. }
  218. public void testSupportedFilters_PrimaryResultExpr() {
  219. String baseQuery = "SELECT b FROM " + Book.class.getName() + " b ";
  220. testSupportedFilters(baseQuery);
  221. }
  222. private void testSupportedFilters(String baseQuery) {
  223. assertQuerySupported(baseQuery, NO_FILTERS, NO_SORTS);
  224. baseQuery += "WHERE ";
  225. assertQuerySupported(baseQuery + "title = 2", Utils.newArrayList(TITLE_EQ_2), NO_SORTS);
  226. assertQuerySupported(baseQuery + "title = \"2\"", Utils.newArrayList(TITLE_EQ_2STR), NO_SORTS);
  227. assertQuerySupported(baseQuery + "(title = 2)", Utils.newArrayList(TITLE_EQ_2), NO_SORTS);
  228. assertQuerySupported(baseQuery + "title = 2 AND isbn = 4",
  229. Utils.newArrayList(TITLE_EQ_2,ISBN_EQ_4),
  230. NO_SORTS);
  231. assertQuerySupported(baseQuery + "(title = 2 AND isbn = 4)",
  232. Utils.newArrayList(TITLE_EQ_2, ISBN_EQ_4),
  233. NO_SORTS);
  234. assertQuerySupported(baseQuery + "(title = 2) AND (isbn = 4)", Utils.newArrayList(
  235. TITLE_EQ_2, ISBN_EQ_4), NO_SORTS);
  236. assertQuerySupported(baseQuery + "title > 2", Utils.newArrayList(TITLE_GT_2), NO_SORTS);
  237. assertQuerySupported(baseQuery + "title >= 2", Utils.newArrayList(TITLE_GTE_2), NO_SORTS);
  238. assertQuerySupported(baseQuery + "isbn < 4", Utils.newArrayList(ISBN_LT_4), NO_SORTS);
  239. assertQuerySupported(baseQuery + "isbn <= 4", Utils.newArrayList(ISBN_LTE_4), NO_SORTS);
  240. baseQuery = "SELECT FROM " + Book.class.getName() + " b ";
  241. assertQuerySupported(baseQuery + "ORDER BY title ASC", NO_FILTERS,
  242. Utils.newArrayList(TITLE_ASC));
  243. assertQuerySupported(baseQuery + "ORDER BY isbn DESC", NO_FILTERS,
  244. Utils.newArrayList(ISBN_DESC));
  245. assertQuerySupported(baseQuery + "ORDER BY title ASC, isbn DESC", NO_FILTERS,
  246. Utils.newArrayList(TITLE_ASC, ISBN_DESC));
  247. assertQuerySupported(baseQuery + "WHERE title = 2 AND isbn = 4 ORDER BY title ASC, isbn DESC",
  248. Utils.newArrayList(TITLE_EQ_2, ISBN_EQ_4),
  249. Utils.newArrayList(TITLE_ASC, ISBN_DESC));
  250. assertQuerySupported(baseQuery + "WHERE title <> null",
  251. Utils.newArrayList(TITLE_NEQ_NULL_LITERAL), NO_SORTS);
  252. assertQuerySupported(baseQuery + "WHERE title <> 2",
  253. Utils.newArrayList(TITLE_NEQ_2_LITERAL), NO_SORTS);
  254. assertQuerySupported(baseQuery + "WHERE title = '2' OR title = 2",
  255. Utils.newArrayList(TITLE_IN_2_ARGS), NO_SORTS);
  256. assertQuerySupported(baseQuery + "WHERE title = '2' OR title = 2 OR title = false",
  257. Utils.newArrayList(TITLE_IN_3_ARGS), NO_SORTS);
  258. assertQuerySupported(baseQuery + "WHERE title IN ('2', 2)",
  259. Utils.newArrayList(TITLE_IN_2_ARGS), NO_SORTS);
  260. assertQuerySupported(baseQuery + "WHERE title IN ('2', 2, false)",
  261. Utils.newArrayList(TITLE_IN_3_ARGS), NO_SORTS);
  262. assertQuerySupported(baseQuery + "WHERE (title = '2' OR title = 2) AND isbn = 4",
  263. Utils.newArrayList(ISBN_EQ_4, TITLE_IN_2_ARGS), NO_SORTS);
  264. assertQuerySupported(baseQuery + "WHERE title IN ('2', 2) AND isbn = 4",
  265. Utils.newArrayList(ISBN_EQ_4, TITLE_IN_2_ARGS), NO_SORTS);
  266. assertQuerySupported(baseQuery + "WHERE (title = '2' OR title = 2 OR title = false) AND isbn = 4",
  267. Utils.newArrayList(ISBN_EQ_4, TITLE_IN_3_ARGS), NO_SORTS);
  268. assertQuerySupported(baseQuery + "WHERE title IN ('2', 2, false) AND isbn = 4",
  269. Utils.newArrayList(ISBN_EQ_4, TITLE_IN_3_ARGS), NO_SORTS);
  270. }
  271. public void test2Equals2OrderBy() {
  272. ds.put(Book.newBookEntity("Joe Blow", "67890", "Bar Book"));
  273. ds.put(Book.newBookEntity("Joe Blow", "11111", "Bar Book"));
  274. ds.put(Book.newBookEntity("Joe Blow", "12345", "Foo Book"));
  275. ds.put(Book.newBookEntity("Joe Blow", "54321", "A Book"));
  276. ds.put(Book.newBookEntity("Jane Blow", "13579", "Baz Book"));
  277. Query q = em.createQuery("SELECT FROM " +
  278. Book.class.getName() + " b" +
  279. " WHERE author = 'Joe Blow'" +
  280. " ORDER BY title DESC, isbn ASC");
  281. @SuppressWarnings("unchecked")
  282. List<Book> result = (List<Book>) q.getResultList();
  283. assertEquals(4, result.size());
  284. assertEquals("12345", result.get(0).getIsbn());
  285. assertEquals("11111", result.get(1).getIsbn());
  286. assertEquals("67890", result.get(2).getIsbn());
  287. assertEquals("54321", result.get(3).getIsbn());
  288. }
  289. public void testDefaultOrderingIsAsc() {
  290. ds.put(Book.newBookEntity("Joe Blow", "67890", "Bar Book"));
  291. ds.put(Book.newBookEntity("Joe Blow", "11111", "Bar Book"));
  292. ds.put(Book.newBookEntity("Joe Blow", "12345", "Foo Book"));
  293. ds.put(Book.newBookEntity("Joe Blow", "54321", "A Book"));
  294. ds.put(Book.newBookEntity("Jane Blow", "13579", "Baz Book"));
  295. Query q = em.createQuery("SELECT FROM " +
  296. Book.class.getName() + " b" +
  297. " WHERE author = 'Joe Blow'" +
  298. " ORDER BY title");
  299. @SuppressWarnings("unchecked")
  300. List<Book> result = (List<Book>) q.getResultList();
  301. assertEquals(4, result.size());
  302. assertEquals("54321", result.get(0).getIsbn());
  303. assertEquals("67890", result.get(1).getIsbn());
  304. assertEquals("11111", result.get(2).getIsbn());
  305. assertEquals("12345", result.get(3).getIsbn());
  306. }
  307. public void testLimitQuery() {
  308. ds.put(Book.newBookEntity("Joe Blow", "67890", "Bar Book"));
  309. ds.put(Book.newBookEntity("Joe Blow", "11111", "Bar Book"));
  310. ds.put(Book.newBookEntity("Joe Blow", "12345", "Foo Book"));
  311. ds.put(Book.newBookEntity("Joe Blow", "54321", "A Book"));
  312. ds.put(Book.newBookEntity("Jane Blow", "13579", "Baz Book"));
  313. Query q = em.createQuery("SELECT FROM " +
  314. Book.class.getName() + " b" +
  315. " WHERE author = 'Joe Blow'" +
  316. " ORDER BY title DESC, isbn ASC");
  317. q.setMaxResults(1);
  318. @SuppressWarnings("unchecked")
  319. List<Book> result1 = (List<Book>) q.getResultList();
  320. assertEquals(1, result1.size());
  321. assertEquals("12345", result1.get(0).getIsbn());
  322. q.setMaxResults(0);
  323. @SuppressWarnings("unchecked")
  324. List<Book> result2 = (List<Book>) q.getResultList();
  325. assertEquals(0, result2.size());
  326. try {
  327. q.setMaxResults(-1);
  328. fail("expected iae");
  329. } catch (IllegalArgumentException iae) {
  330. // good
  331. }
  332. }
  333. public void testOffsetQuery() {
  334. ds.put(Book.newBookEntity("Joe Blow", "67890", "Bar Book"));
  335. ds.put(Book.newBookEntity("Joe Blow", "11111", "Bar Book"));
  336. ds.put(Book.newBookEntity("Joe Blow", "12345", "Foo Book"));
  337. ds.put(Book.newBookEntity("Joe Blow", "54321", "A Book"));
  338. ds.put(Book.newBookEntity("Jane Blow", "13579", "Baz Book"));
  339. Query q = em.createQuery("SELECT FROM " +
  340. Book.class.getName() + " b" +
  341. " WHERE author = 'Joe Blow'" +
  342. " ORDER BY title DESC, isbn ASC");
  343. q.setFirstResult(0);
  344. @SuppressWarnings("unchecked")
  345. List<Book> result1 = (List<Book>) q.getResultList();
  346. assertEquals(4, result1.size());
  347. assertEquals("12345", result1.get(0).getIsbn());
  348. q.setFirstResult(1);
  349. @SuppressWarnings("unchecked")
  350. List<Book> result2 = (List<Book>) q.getResultList();
  351. assertEquals(3, result2.size());
  352. assertEquals("11111", result2.get(0).getIsbn());
  353. try {
  354. q.setFirstResult(-1);
  355. fail("expected iae");
  356. } catch (IllegalArgumentException iae) {
  357. // good
  358. }
  359. }
  360. public void testOffsetLimitQuery() {
  361. ds.put(Book.newBookEntity("Joe Blow", "67890", "Bar Book"));
  362. ds.put(Book.newBookEntity("Joe Blow", "11111", "Bar Book"));
  363. ds.put(Book.newBookEntity("Joe Blow", "12345", "Foo Book"));
  364. ds.put(Book.newBookEntity("Joe Blow", "54321", "A Book"));
  365. ds.put(Book.newBookEntity("Jane Blow", "13579", "Baz Book"));
  366. Query q = em.createQuery("SELECT FROM " +
  367. Book.class.getName() + " b" +
  368. " WHERE author = 'Joe Blow'" +
  369. " ORDER BY title DESC, isbn ASC");
  370. q.setFirstResult(0);
  371. q.setMaxResults(0);
  372. @SuppressWarnings("unchecked")
  373. List<Book> result1 = (List<Book>) q.getResultList();
  374. assertEquals(0, result1.size());
  375. q.setFirstResult(1);
  376. q.setMaxResults(0);
  377. @SuppressWarnings("unchecked")
  378. List<Book> result2 = (List<Book>) q.getResultList();
  379. assertEquals(0, result2.size());
  380. q.setFirstResult(0);
  381. q.setMaxResults(1);
  382. @SuppressWarnings("unchecked")
  383. List<Book> result3 = (List<Book>) q.getResultList();
  384. assertEquals(1, result3.size());
  385. q.setFirstResult(0);
  386. q.setMaxResults(2);
  387. @SuppressWarnings("unchecked")
  388. List<Book> result4 = (List<Book>) q.getResultList();
  389. assertEquals(2, result4.size());
  390. assertEquals("12345", result4.get(0).getIsbn());
  391. q.setFirstResult(1);
  392. q.setMaxResults(1);
  393. @SuppressWarnings("unchecked")
  394. List<Book> result5 = (List<Book>) q.getResultList();
  395. assertEquals(1, result5.size());
  396. assertEquals("11111", result5.get(0).getIsbn());
  397. q.setFirstResult(2);
  398. q.setMaxResults(5);
  399. @SuppressWarnings("unchecked")
  400. List<Book> result6 = (List<Book>) q.getResultList();
  401. assertEquals(2, result6.size());
  402. assertEquals("67890", result6.get(0).getIsbn());
  403. }
  404. public void testSerialization() throws IOException {
  405. Query q = em.createQuery("select from " + Book.class.getName() + " b ");
  406. q.getResultList();
  407. JPQLQuery innerQuery = (JPQLQuery) ((JPAQuery) q).getInternalQuery();
  408. ByteArrayOutputStream baos = new ByteArrayOutputStream();
  409. ObjectOutputStream oos = new ObjectOutputStream(baos);
  410. // the fact that this doesn't blow up is the test
  411. oos.writeObject(innerQuery);
  412. }
  413. public void testBindVariables() {
  414. assertQuerySupported("select from " + Book.class.getName() + " b where title = :titleParam",
  415. Utils.newArrayList(TITLE_EQ_2), NO_SORTS, "titleParam", 2L);
  416. assertQuerySupported("select from " + Book.class.getName() + " b" +
  417. " where title = :titleParam AND isbn = :isbnParam",
  418. Utils.newArrayList(TITLE_EQ_2, ISBN_EQ_4), NO_SORTS, "titleParam", 2L, "isbnParam", 4L);
  419. assertQuerySupported("select from " + Book.class.getName() + " b" +
  420. " where title = :titleParam AND isbn = :isbnParam order by title asc, isbn desc",
  421. Utils.newArrayList(TITLE_EQ_2, ISBN_EQ_4),
  422. Utils.newArrayList(TITLE_ASC, ISBN_DESC), "titleParam", 2L, "isbnParam", 4L);
  423. }
  424. public void testKeyQuery() {
  425. Entity bookEntity = Book.newBookEntity("Joe Blow", "67890", "Bar Book");
  426. ds.put(bookEntity);
  427. javax.persistence.Query q = em.createQuery(
  428. "select from " + Book.class.getName() + " b where id = :key");
  429. q.setParameter("key", KeyFactory.keyToString(bookEntity.getKey()));
  430. @SuppressWarnings("unchecked")
  431. List<Book> books = (List<Book>) q.getResultList();
  432. assertEquals(1, books.size());
  433. assertEquals(bookEntity.getKey(), KeyFactory.stringToKey(books.get(0).getId()));
  434. // now issue the same query, but instead of providing a String version of
  435. // the key, provide the Key itself.
  436. q.setParameter("key", bookEntity.getKey());
  437. @SuppressWarnings("unchecked")
  438. List<Book> books2 = (List<Book>) q.getResultList();
  439. assertEquals(1, books2.size());
  440. assertEquals(bookEntity.getKey(), KeyFactory.stringToKey(books2.get(0).getId()));
  441. }
  442. public void testKeyQuery_KeyPk() {
  443. Entity entityWithName = new Entity(HasKeyPkJPA.class.getSimpleName(), "blarg");
  444. Entity entityWithId = new Entity(HasKeyPkJPA.class.getSimpleName());
  445. ds.put(entityWithName);
  446. ds.put(entityWithId);
  447. Query q = em.createQuery(
  448. "select from " + HasKeyPkJPA.class.getName() + " b where id = :key");
  449. q.setParameter("key", entityWithName.getKey());
  450. HasKeyPkJPA result = (HasKeyPkJPA) q.getSingleResult();
  451. assertEquals(entityWithName.getKey(), result.getId());
  452. q = em.createQuery("select from " + HasKeyPkJPA.class.getName() + " b where id = :mykey");
  453. q.setParameter("mykey", entityWithId.getKey());
  454. result = (HasKeyPkJPA) q.getSingleResult();
  455. assertEquals(entityWithId.getKey(), result.getId());
  456. q = em.createQuery("select from " + HasKeyPkJPA.class.getName() + " b where id = :mykeyname");
  457. q.setParameter("mykeyname", entityWithName.getKey().getName());
  458. result = (HasKeyPkJPA) q.getSingleResult();
  459. assertEquals(entityWithName.getKey(), result.getId());
  460. q = em.createQuery("select from " + HasKeyPkJPA.class.getName() + " b where id = :mykeyid");
  461. q.setParameter("mykeyid", entityWithId.getKey().getId());
  462. result = (HasKeyPkJPA) q.getSingleResult();
  463. assertEquals(entityWithId.getKey(), result.getId());
  464. }
  465. public void testKeyQueryWithSorts() {
  466. Entity bookEntity = Book.newBookEntity("Joe Blow", "67890", "Bar Book");
  467. ds.put(bookEntity);
  468. javax.persistence.Query q = em.createQuery(
  469. "select from " + Book.class.getName() + " c where id = :key order by isbn ASC");
  470. q.setParameter("key", KeyFactory.keyToString(bookEntity.getKey()));
  471. @SuppressWarnings("unchecked")
  472. List<Book> books = (List<Book>) q.getResultList();
  473. assertEquals(1, books.size());
  474. assertEquals(bookEntity.getKey(), KeyFactory.stringToKey(books.get(0).getId()));
  475. }
  476. public void testKeyQuery_MultipleFilters() {
  477. Entity bookEntity = Book.newBookEntity("Joe Blow", "67890", "Bar Book");
  478. ds.put(bookEntity);
  479. javax.persistence.Query q = em.createQuery(
  480. "select from " + Book.class.getName() + " c where id = :key and isbn = \"67890\"");
  481. q.setParameter("key", KeyFactory.keyToString(bookEntity.getKey()));
  482. @SuppressWarnings("unchecked")
  483. List<Book> books = (List<Book>) q.getResultList();
  484. assertEquals(1, books.size());
  485. assertEquals(bookEntity.getKey(), KeyFactory.stringToKey(books.get(0).getId()));
  486. }
  487. public void testKeyQuery_NonEqualityFilter() {
  488. Entity bookEntity1 = Book.newBookEntity("Joe Blow", "67890", "Bar Book");
  489. ds.put(bookEntity1);
  490. Entity bookEntity2 = Book.newBookEntity("Joe Blow", "67890", "Bar Book");
  491. ds.put(bookEntity2);
  492. javax.persistence.Query q = em.createQuery(
  493. "select from " + Book.class.getName()
  494. + " b where id > :key");
  495. q.setParameter("key", KeyFactory.keyToString(bookEntity1.getKey()));
  496. @SuppressWarnings("unchecked")
  497. List<Book> books = (List<Book>) q.getResultList();
  498. assertEquals(1, books.size());
  499. assertEquals(bookEntity2.getKey(), KeyFactory.stringToKey(books.get(0).getId()));
  500. }
  501. public void testKeyQuery_SortByKey() {
  502. Entity bookEntity1 = Book.newBookEntity("Joe Blow", "67890", "Bar Book");
  503. ds.put(bookEntity1);
  504. Entity bookEntity2 = Book.newBookEntity("Joe Blow", "67890", "Bar Book");
  505. ds.put(bookEntity2);
  506. javax.persistence.Query q = em.createQuery(
  507. "select from " + Book.class.getName()
  508. + " b order by id DESC");
  509. @SuppressWarnings("unchecked")
  510. List<Book> books = (List<Book>) q.getResultList();
  511. assertEquals(2, books.size());
  512. assertEquals(bookEntity2.getKey(), KeyFactory.stringToKey(books.get(0).getId()));
  513. }
  514. public void testKeyQuery_FilterAndSortByKeyComponent() {
  515. // filter by pk-id
  516. assertQueryUnsupportedByDatastore(
  517. "select from " + HasEncodedStringPkSeparateIdFieldJPA.class.getName() + " b where id = 4",
  518. NucleusFatalUserException.class);
  519. // sort by pk-id
  520. assertQueryUnsupportedByDatastore(
  521. "select from " + HasEncodedStringPkSeparateIdFieldJPA.class.getName() + " b order by id",
  522. NucleusFatalUserException.class);
  523. // filter by pk-id
  524. assertQueryUnsupportedByDatastore(
  525. "select from " + HasEncodedStringPkSeparateNameFieldJPA.class.getName() + " b where name = 4",
  526. NucleusFatalUserException.class);
  527. // sort by pk-id
  528. assertQueryUnsupportedByDatastore(
  529. "select from " + HasEncodedStringPkSeparateNameFieldJPA.class.getName() + " b order by name",
  530. NucleusFatalUserException.class);
  531. }
  532. public void testAncestorQuery() {
  533. Entity bookEntity = Book.newBookEntity("Joe Blow", "67890", "Bar Book");
  534. ds.put(bookEntity);
  535. Entity
  536. hasAncestorEntity =
  537. new Entity(HasStringAncestorStringPkJPA.class.getSimpleName(), bookEntity.getKey());
  538. ds.put(hasAncestorEntity);
  539. javax.persistence.Query q = em.createQuery(
  540. "select from " + HasStringAncestorStringPkJPA.class.getName()
  541. + " b where ancestorId = :ancId");
  542. q.setParameter("ancId", KeyFactory.keyToString(bookEntity.getKey()));
  543. @SuppressWarnings("unchecked")
  544. List<HasStringAncestorStringPkJPA>
  545. haList =
  546. (List<HasStringAncestorStringPkJPA>) q.getResultList();
  547. assertEquals(1, haList.size());
  548. assertEquals(bookEntity.getKey(), KeyFactory.stringToKey(haList.get(0).getAncestorId()));
  549. assertEquals(
  550. bookEntity.getKey(), getDatastoreQuery(q).getLatestDatastoreQuery().getAncestor());
  551. assertEquals(NO_FILTERS, getFilterPredicates(q));
  552. assertEquals(NO_SORTS, getSortPredicates(q));
  553. }
  554. public void testIllegalAncestorQuery() {
  555. Entity bookEntity = Book.newBookEntity("Joe Blow", "67890", "Bar Book");
  556. ds.put(bookEntity);
  557. Entity
  558. hasAncestorEntity =
  559. new Entity(HasStringAncestorStringPkJPA.class.getName(), bookEntity.getKey());
  560. ds.put(hasAncestorEntity);
  561. javax.persistence.Query q = em.createQuery(
  562. "select from " + HasStringAncestorStringPkJPA.class.getName() + " b"
  563. + " where ancestorId > :ancId");
  564. q.setParameter("ancId", KeyFactory.keyToString(bookEntity.getKey()));
  565. q.setHint(DatastoreManager.QUERYEXT_INMEMORY_WHEN_UNSUPPORTED, "false");
  566. try {
  567. q.getResultList();
  568. fail("expected udfe");
  569. } catch (PersistenceException pe) {
  570. if (pe.getCause() instanceof DatastoreQuery.UnsupportedDatastoreFeatureException) {
  571. // good
  572. }
  573. else {
  574. throw pe;
  575. }
  576. }
  577. }
  578. public void testSortByFieldWithCustomColumn() {
  579. ds.put(Book.newBookEntity("Joe Blow", "67890", "Bar Book", 2003));
  580. ds.put(Book.newBookEntity("Joe Blow", "11111", "Bar Book", 2002));
  581. ds.put(Book.newBookEntity("Joe Blow", "12345", "Foo Book", 2001));
  582. Query q = em.createQuery("SELECT FROM " +
  583. Book.class.getName() + " b" +
  584. " WHERE b.author = 'Joe Blow'" +
  585. " ORDER BY firstPublished ASC");
  586. @SuppressWarnings("unchecked")
  587. List<Book> result = (List<Book>) q.getResultList();
  588. assertEquals(3, result.size());
  589. assertEquals("12345", result.get(0).getIsbn());
  590. assertEquals("11111", result.get(1).getIsbn());
  591. assertEquals("67890", result.get(2).getIsbn());
  592. }
  593. private interface BookProvider {
  594. Book getBook(Key key);
  595. }
  596. private class AttachedBookProvider implements BookProvider {
  597. public Book getBook(Key key) {
  598. return em.find(Book.class, key);
  599. }
  600. }
  601. private class TransientBookProvider implements BookProvider {
  602. public Book getBook(Key key) {
  603. Book b = new Book();
  604. b.setId(KeyFactory.keyToString(key));
  605. return b;
  606. }
  607. }
  608. private void testFilterByChildObject(BookProvider bp) {
  609. Entity parentEntity = new Entity(HasOneToOneJPA.class.getSimpleName());
  610. ds.put(parentEntity);
  611. Entity bookEntity = Book.newBookEntity(parentEntity.getKey(), "Joe Blow", "11111", "Bar Book", 1929);
  612. ds.put(bookEntity);
  613. Book book = bp.getBook(bookEntity.getKey());
  614. Query q = em.createQuery(
  615. "select from " + HasOneToOneJPA.class.getName() + " c where book = :b");
  616. q.setParameter("b", book);
  617. List<HasOneToOneJPA> result = (List<HasOneToOneJPA>) q.getResultList();
  618. assertEquals(1, result.size());
  619. assertEquals(parentEntity.getKey(), KeyFactory.stringToKey(result.get(0).getId()));
  620. }
  621. public void testFilterByChildObject() {
  622. testFilterByChildObject(new AttachedBookProvider());
  623. testFilterByChildObject(new TransientBookProvider());
  624. }
  625. private void testFilterByChildObject_AdditionalFilterOnParent(BookProvider bp) {
  626. Entity parentEntity = new Entity(HasOneToOneJPA.class.getSimpleName());
  627. ds.put(parentEntity);
  628. Entity bookEntity = Book.newBookEntity(parentEntity.getKey(), "Joe Blow", "11111", "Bar Book", 1929);
  629. ds.put(bookEntity);
  630. Book book = bp.getBook(bookEntity.getKey());
  631. Query q = em.createQuery(
  632. "select from " + HasOneToOneJPA.class.getName() + " c where id = :parentId and book = :b");
  633. q.setParameter("parentId", KeyFactory.keyToString(bookEntity.getKey()));
  634. q.setParameter("b", book);
  635. List<HasOneToOneJPA> result = (List<HasOneToOneJPA>) q.getResultList();
  636. assertTrue(result.isEmpty());
  637. q.setParameter("parentId", KeyFactory.keyToString(parentEntity.getKey()));
  638. q.setParameter("b", book);
  639. result = (List<HasOneToOneJPA>) q.getResultList();
  640. assertEquals(1, result.size());
  641. assertEquals(parentEntity.getKey(), KeyFactory.stringToKey(result.get(0).getId()));
  642. }
  643. public void testFilterByChildObject_AdditionalFilterOnParent() {
  644. testFilterByChildObject_AdditionalFilterOnParent(new AttachedBookProvider());
  645. testFilterByChildObject_AdditionalFilterOnParent(new TransientBookProvider());
  646. }
  647. private void testFilterByChildObject_UnsupportedOperator(BookProvider bp) {
  648. Entity parentEntity = new Entity(HasOneToOneJPA.class.getSimpleName());
  649. ds.put(parentEntity);
  650. Entity bookEntity = Book.newBookEntity(parentEntity.getKey(), "Joe Blow", "11111", "Bar Book", 1929);
  651. ds.put(bookEntity);
  652. Book book = bp.getBook(bookEntity.getKey());
  653. Query q = em.createQuery(
  654. "select from " + HasOneToOneJPA.class.getName() + " c where book > :b");
  655. q.setHint(DatastoreManager.QUERYEXT_INMEMORY_WHEN_UNSUPPORTED, "false");
  656. q.setParameter("b", book);
  657. try {
  658. q.getResultList();
  659. fail("expected udfe");
  660. } catch (PersistenceException pe) {
  661. if (pe.getCause() instanceof DatastoreQuery.UnsupportedDatastoreFeatureException) {
  662. // good
  663. }
  664. else {
  665. throw pe;
  666. }
  667. }
  668. }
  669. public void testFilterByChildObject_UnsupportedOperator() {
  670. testFilterByChildObject_UnsupportedOperator(new AttachedBookProvider());
  671. testFilterByChildObject_UnsupportedOperator(new TransientBookProvider());
  672. }
  673. private void testFilterByChildObject_ValueWithoutAncestor(BookProvider bp) {
  674. Entity parentEntity = new Entity(HasOneToOneJPA.class.getSimpleName());
  675. ds.put(parentEntity);
  676. Entity bookEntity = Book.newBookEntity("Joe Blow", "11111", "Bar Book", 1929);
  677. ds.put(bookEntity);
  678. Book book = bp.getBook(bookEntity.getKey());
  679. Query q = em.createQuery(
  680. "select from " + HasOneToOneJPA.class.getName() + " c where book = :b");
  681. q.setParameter("b", book);
  682. q.setHint(DatastoreManager.QUERYEXT_INMEMORY_WHEN_UNSUPPORTED, "false");
  683. try {
  684. q.getResultList();
  685. fail("expected JPAException");
  686. } catch (PersistenceException e) {
  687. // good
  688. }
  689. }
  690. public void testFilterByChildObject_ValueWithoutAncestor() {
  691. testFilterByChildObject_ValueWithoutAncestor(new AttachedBookProvider());
  692. testFilterByChildObject_ValueWithoutAncestor(new TransientBookProvider());
  693. }
  694. public void testFilterByChildObject_KeyIsWrongType() {
  695. Entity parentEntity = new Entity(HasOneToOneJPA.class.getSimpleName());
  696. ds.put(parentEntity);
  697. Query q = em.createQuery(
  698. "select from " + HasOneToOneJPA.class.getName() + " c where book = :b");
  699. q.setParameter("b", parentEntity.getKey());
  700. q.setHint(DatastoreManager.QUERYEXT_INMEMORY_WHEN_UNSUPPORTED, "false");
  701. try {
  702. q.getResultList();
  703. fail("expected JPAException");
  704. } catch (PersistenceException e) {
  705. // good
  706. }
  707. }
  708. public void testFilterByChildObject_KeyParentIsWrongType() {
  709. Key parent = KeyFactory.createKey("yar", 44);
  710. Entity bookEntity = new Entity(Book.class.getSimpleName(), parent);
  711. Query q = em.createQuery(
  712. "select from " + HasOneToOneJPA.class.getName() + " c where book = :b");
  713. q.setParameter("b", bookEntity.getKey());
  714. assertTrue(q.getResultList().isEmpty());
  715. }
  716. public void testFilterByChildObject_ValueWithoutId() {
  717. Entity parentEntity = new Entity(HasOneToOneJPA.class.getSimpleName());
  718. ds.put(parentEntity);
  719. Entity bookEntity = Book.newBookEntity("Joe Blow", "11111", "Bar Book", 1929);
  720. ds.put(bookEntity);
  721. Book book = new Book();
  722. Query q = em.createQuery(
  723. "select from " + HasOneToOneJPA.class.getName() + " c where book = :b");
  724. q.setParameter("b", book);
  725. q.setHint(DatastoreManager.QUERYEXT_INMEMORY_WHEN_UNSUPPORTED, "false");
  726. try {
  727. q.getResultList();
  728. fail("expected JPAException");
  729. } catch (PersistenceException e) {
  730. // good
  731. }
  732. }
  733. public void testFilterByParentObject() {
  734. Entity parentEntity = new Entity(HasOneToManyListJPA.class.getSimpleName());
  735. ds.put(parentEntity);
  736. Entity bidirEntity =
  737. new Entity(BidirectionalChildListJPA.class.getSimpleName(), parentEntity.getKey());
  738. ds.put(bidirEntity);
  739. Entity bidirEntity2 =
  740. new Entity(BidirectionalChildListJPA.class.getSimpleName(), parentEntity.getKey());
  741. ds.put(bidirEntity2);
  742. HasOneToManyListJPA parent =
  743. em.find(HasOneToManyListJPA.class, KeyFactory.keyToString(parentEntity.getKey()));
  744. Query q = em.createQuery("SELECT FROM " +
  745. BidirectionalChildListJPA.class.getName() +
  746. " c WHERE parent = :p");
  747. q.setParameter("p", parent);
  748. @SuppressWarnings("unchecked")
  749. List<BidirectionalChildListJPA> result = (List<BidirectionalChildListJPA>) q.getResultList();
  750. assertEquals(2, result.size());
  751. assertEquals(bidirEntity.getKey(), KeyFactory.stringToKey(result.get(0).getId()));
  752. assertEquals(bidirEntity2.getKey(), KeyFactory.stringToKey(result.get(1).getId()));
  753. }
  754. public void testFilterByParentLongObjectId() {
  755. Entity parentEntity = new Entity(HasOneToManyLongPkListJPA.class.getSimpleName());
  756. ds.put(parentEntity);
  757. Entity bidirEntity =
  758. new Entity(BidirectionalChildLongPkListJPA.class.getSimpleName(), parentEntity.getKey());
  759. ds.put(bidirEntity);
  760. Entity bidirEntity2 =
  761. new Entity(BidirectionalChildLongPkListJPA.class.getSimpleName(), parentEntity.getKey());
  762. ds.put(bidirEntity2);
  763. HasOneToManyLongPkListJPA parent =
  764. em.find(HasOneToManyLongPkListJPA.class, KeyFactory.keyToString(parentEntity.getKey()));
  765. Query q = em.createQuery("SELECT FROM " +
  766. BidirectionalChildLongPkListJPA.class.getName() + " c WHERE parent = :p");
  767. q.setParameter("p", parent.getId());
  768. @SuppressWarnings("unchecked")
  769. List<BidirectionalChildLongPkListJPA> result = (List<BidirectionalChildLongPkListJPA>) q.getResultList();
  770. assertEquals(2, result.size());
  771. assertEquals(bidirEntity.getKey(), KeyFactory.stringToKey(result.get(0).getId()));
  772. assertEquals(bidirEntity2.getKey(), KeyFactory.stringToKey(result.get(1).getId()));
  773. }
  774. public void testFilterByParentIntObjectId() {
  775. Entity parentEntity = new Entity(HasOneToManyLongPkListJPA.class.getSimpleName());
  776. ds.put(parentEntity);
  777. Entity bidirEntity =
  778. new Entity(BidirectionalChildLongPkListJPA.class.getSimpleName(), parentEntity.getKey());
  779. ds.put(bidirEntity);
  780. Entity bidirEntity2 =
  781. new Entity(BidirectionalChildLongPkListJPA.class.getSimpleName(), parentEntity.getKey());
  782. ds.put(bidirEntity2);
  783. HasOneToManyLongPkListJPA parent =
  784. em.find(HasOneToManyLongPkListJPA.class, KeyFactory.keyToString(parentEntity.getKey()));
  785. Query q = em.createQuery("SELECT FROM " +
  786. BidirectionalChildLongPkListJPA.class.getName() + " c WHERE parent = :p");
  787. q.setParameter("p", parent.getId().intValue());
  788. @SuppressWarnings("unchecked")
  789. List<BidirectionalChildLongPkListJPA> result = (List<BidirectionalChildLongPkListJPA>) q.getResultList();
  790. assertEquals(2, result.size());
  791. assertEquals(bidirEntity.getKey(), KeyFactory.stringToKey(result.get(0).getId()));
  792. assertEquals(bidirEntity2.getKey(), KeyFactory.stringToKey(result.get(1).getId()));
  793. }
  794. public void testFilterByParentObjectWhereParentIsAChild() {
  795. Entity parentEntity = new Entity(HasOneToManyListJPA.class.getSimpleName());
  796. ds.put(parentEntity);
  797. Entity childEntity = new Entity(BidirectionalChildListJPA.class.getSimpleName(), parentEntity.getKey());
  798. ds.put(childEntity);
  799. Entity grandChildEntity1 =
  800. new Entity(BidirectionalGrandchildListJPA.class.getSimpleName(), childEntity.getKey());
  801. ds.put(grandChildEntity1);
  802. Entity grandChildEntity2 =
  803. new Entity(BidirectionalGrandchildListJPA.class.getSimpleName(), childEntity.getKey());
  804. ds.put(grandChildEntity2);
  805. BidirectionalChildListJPA child =
  806. em.find(BidirectionalChildListJPA.class, KeyFactory.keyToString(childEntity.getKey()));
  807. Query q = em.createQuery(
  808. "select from " + BidirectionalGrandchildListJPA.class.getName() + " c where parent = :p");
  809. q.setParameter("p", child);
  810. @SuppressWarnings("unchecked")
  811. List<BidirectionalGrandchildListJPA> result = (List<BidirectionalGrandchildListJPA>) q.getResultList();
  812. assertEquals(2, result.size());
  813. assertEquals(grandChildEntity1.getKey(), KeyFactory.stringToKey(result.get(0).getId()));
  814. assertEquals(grandChildEntity2.getKey(), KeyFactory.stringToKey(result.get(1).getId()));
  815. }
  816. public void testFilterByParentId() {
  817. Entity parentEntity = new Entity(HasOneToManyListJPA.class.getSimpleName());
  818. ds.put(parentEntity);
  819. Entity
  820. bidirEntity =
  821. new Entity(BidirectionalChildListJPA.class.getSimpleName(), parentEntity.getKey());
  822. ds.put(bidirEntity);
  823. Entity
  824. bidirEntity2 =
  825. new Entity(BidirectionalChildListJPA.class.getSimpleName(), parentEntity.getKey());
  826. ds.put(bidirEntity2);
  827. HasOneToManyListJPA parent =
  828. em.find(HasOneToManyListJPA.class, KeyFactory.keyToString(parentEntity.getKey()));
  829. Query q = em.createQuery("SELECT FROM " +
  830. BidirectionalChildListJPA.class.getName() +
  831. " c WHERE parent = :p");
  832. q.setParameter("p", parent.getId());
  833. @SuppressWarnings("unchecked")
  834. List<BidirectionalChildListJPA> result = (List<BidirectionalChildListJPA>) q.getResultList();
  835. assertEquals(2, result.size());
  836. assertEquals(bidirEntity.getKey(), KeyFactory.stringToKey(result.get(0).getId()));
  837. assertEquals(bidirEntity2.getKey(), KeyFactory.stringToKey(result.get(1).getId()));
  838. }
  839. public void testFilterByParentKey() {
  840. Entity parentEntity = new Entity(HasOneToManyListJPA.class.getSimpleName());
  841. ds.put(parentEntity);
  842. Entity
  843. bidirEntity =
  844. new Entity(BidirectionalChildListJPA.class.getSimpleName(), parentEntity.getKey());
  845. ds.put(bidirEntity);
  846. Entity
  847. bidirEntity2 =
  848. new Entity(BidirectionalChildListJPA.class.getSimpleName(), parentEntity.getKey());
  849. ds.put(bidirEntity2);
  850. Query q = em.createQuery("SELECT FROM " +
  851. BidirectionalChildListJPA.class.getName() +
  852. " c WHERE parent = :p");
  853. q.setParameter("p", parentEntity.getKey());
  854. @SuppressWarnings("unchecked")
  855. List<BidirectionalChildListJPA> result = (List<BidirectionalChildListJPA>) q.getResultList();
  856. assertEquals(2, result.size());
  857. assertEquals(bidirEntity.getKey(), KeyFactory.stringToKey(result.get(0).getId()));
  858. assertEquals(bidirEntity2.getKey(), KeyFactory.stringToKey(result.get(1).getId()));
  859. }
  860. public void testFilterByMultiValueProperty() {
  861. Entity entity = new Entity(HasMultiValuePropsJPA.class.getSimpleName());
  862. entity.setProperty("strList", Utils.newArrayList("1", "2", "3"));
  863. entity.setProperty("keyList",
  864. Utils.newArrayList(KeyFactory.createKey("be", "bo"),
  865. KeyFactory.createKey("bo", "be")));
  866. ds.put(entity);
  867. Query q = em.createQuery(
  868. "select from " + HasMultiValuePropsJPA.class.getName()
  869. + " c where strList = :p1 AND strList = :p2");
  870. q.setParameter("p1", "1");
  871. q.setParameter("p2", "3");
  872. @SuppressWarnings("unchecked")
  873. List<HasMultiValuePropsJPA> result = (List<HasMultiValuePropsJPA>) q.getResultList();
  874. assertEquals(1, result.size());
  875. q.setParameter("p1", "1");
  876. q.setParameter("p2", "4");
  877. @SuppressWarnings("unchecked")
  878. List<HasMultiValuePropsJPA> result2 = (List<HasMultiValuePropsJPA>) q.getResultList();
  879. assertEquals(0, result2.size());
  880. q = em.createQuery(
  881. "select from " + HasMultiValuePropsJPA.class.getName() + " c where keyList = :p1 AND keyList = :p2");
  882. q.setParameter("p1", KeyFactory.createKey("be", "bo"));
  883. q.setParameter("p2", KeyFactory.createKey("bo", "be"));
  884. assertEquals(1, result.size());
  885. q.setParameter("p1", KeyFactory.createKey("be", "bo"));
  886. q.setParameter("p2", KeyFactory.createKey("bo", "be2"));
  887. @SuppressWarnings("unchecked")
  888. List<HasMultiValuePropsJPA> result3 = (List<HasMultiValuePropsJPA>) q.getResultList();
  889. assertEquals(0, result3.size());
  890. }
  891. public void testNoPutsAfterLoadingMultiValueProperty() throws NoSuchMethodException {
  892. switchDatasource(EntityManagerFactoryName.nontransactional_ds_non_transactional_ops_allowed);
  893. testFilterByMultiValueProperty();
  894. em.close();
  895. }
  896. public void testFilterByMultiValueProperty_MemberOf_ArgsWrongOrder() {
  897. Entity entity = new Entity(HasMultiValuePropsJPA.class.getSimpleName());
  898. entity.setProperty("strList", Utils.newArrayList("1", "2", "3"));
  899. entity.setProperty("keyList",
  900. Utils.newArrayList(KeyFactory.createKey("be", "bo"),
  901. KeyFactory.createKey("bo", "be")));
  902. ds.put(entity);
  903. Query q = em.createQuery(
  904. "select from " + HasMultiValuePropsJPA.class.getName()
  905. + " c where strList MEMBER OF :p1 AND strList MEMBER OF :p2");
  906. q.setParameter("p1", "1");
  907. q.setParameter("p2", "3");
  908. @SuppressWarnings("unchecked")
  909. List<HasMultiValuePropsJPA> result = (List<HasMultiValuePropsJPA>) q.getResultList();
  910. assertEquals(1, result.size());
  911. q.setParameter("p1", "1");
  912. q.setParameter("p2", "4");
  913. @SuppressWarnings("unchecked")
  914. List<HasMultiValuePropsJPA> result2 = (List<HasMultiValuePropsJPA>) q.getResultList();
  915. assertEquals(0, result2.size());
  916. q = em.createQuery(
  917. "select from " + HasMultiValuePropsJPA.class.getName()
  918. + " c where keyList MEMBER OF :p1 AND keyList MEMBER OF :p2");
  919. q.setParameter("p1", KeyFactory.createKey("be", "bo"));
  920. q.setParameter("p2", KeyFactory.createKey("bo", "be"));
  921. result = q.getResultList();
  922. assertEquals(1, result.size());
  923. q.setParameter("p1", KeyFactory.createKey("be", "bo"));
  924. q.setParameter("p2", KeyFactory.createKey("bo", "be2"));
  925. @SuppressWarnings("unchecked")
  926. List<HasMultiValuePropsJPA> result3 = (List<HasMultiValuePropsJPA>) q.getResultList();
  927. assertEquals(0, result3.size());
  928. }
  929. public void testFilterByMultiValueProperty_MemberOf_ArgsCorrectOrder() {
  930. Entity entity = new Entity(HasMultiValuePropsJPA.class.getSimpleName());
  931. entity.setProperty("strList", Utils.newArrayList("1", "2", "3"));
  932. entity.setProperty("keyList",
  933. Utils.newArrayList(KeyFactory.createKey("be", "bo"),
  934. KeyFactory.createKey("bo", "be")));
  935. ds.put(entity);
  936. Query q = em.createQuery(
  937. "select from " + HasMultiValuePropsJPA.class.getName()
  938. + " c where :p1 MEMBER OF strList AND :p2 MEMBER OF strList");
  939. q.setParameter("p1", "1");
  940. q.setParameter("p2", "3");
  941. @SuppressWarnings("unchecked")
  942. List<HasMultiValuePropsJPA> result = (List<HasMultiValuePropsJPA>) q.getResultList();
  943. assertEquals(1, result.size());
  944. q.setParameter("p1", "1");
  945. q.setParameter("p2", "4");
  946. @SuppressWarnings("unchecked")
  947. List<HasMultiValuePropsJPA> result2 = (List<HasMultiValuePropsJPA>) q.getResultList();
  948. assertEquals(0, result2.size());
  949. q = em.createQuery(
  950. "select from " + HasMultiValuePropsJPA.class.getName()
  951. + " c where :p1 MEMBER OF keyList AND :p2 MEMBER OF keyList");
  952. q.setParameter("p1", KeyFactory.createKey("be", "bo"));
  953. q.setParameter("p2", KeyFactory.createKey("bo", "be"));
  954. result = q.getResultList();
  955. assertEquals(1, result.size());
  956. q.setParameter("p1", KeyFactory.createKey("be", "bo"));
  957. q.setParameter("p2", KeyFactory.createKey("bo", "be2"));
  958. @SuppressWarnings("unchecked")
  959. List<HasMultiValuePropsJPA> result3 = (List<HasMultiValuePropsJPA>) q.getResultList();
  960. assertEquals(0, result3.size());
  961. // try one with a literal value
  962. q = em.createQuery(
  963. "select from " + HasMultiValuePropsJPA.class.getName()
  964. + " c where '1' MEMBER OF strList");
  965. result = q.getResultList();
  966. assertEquals(1, result.size());
  967. }
  968. public void testFilterByEmbeddedField() {
  969. Entity entity = new Entity(Person.class.getSimpleName());
  970. e