PageRenderTime 73ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/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
Possible License(s): Apache-2.0
  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. entity.setProperty("first", "max");
  971. entity.setProperty("last", "ross");
  972. entity.setProperty("anotherFirst", "notmax");
  973. entity.setProperty("anotherLast", "notross");
  974. ds.put(entity);
  975. Query q = em.createQuery(
  976. "select from " + Person.class.getName() + " c where name.first = \"max\"");
  977. @SuppressWarnings("unchecked")
  978. List<Person> result = (List<Person>) q.getResultList();
  979. assertEquals(1, result.size());
  980. }
  981. public void testFilterByEmbeddedField_OverriddenColumn() {
  982. Entity entity = new Entity(Person.class.getSimpleName());
  983. entity.setProperty("first", "max");
  984. entity.setProperty("last", "ross");
  985. entity.setProperty("anotherFirst", "notmax");
  986. entity.setProperty("anotherLast", "notross");
  987. ds.put(entity);
  988. Query q = em.createQuery(
  989. "select from " + Person.class.getName()
  990. + " c where anotherName.last = \"notross\"");
  991. @SuppressWarnings("unchecked")
  992. List<Person> result = (List<Person>) q.getResultList();
  993. assertEquals(1, result.size());
  994. }
  995. public void testFilterByEmbeddedField_MultipleFields() {
  996. Entity entity = new Entity(Person.class.getSimpleName());
  997. entity.setProperty("first", "max");
  998. entity.setProperty("last", "ross");
  999. entity.setProperty("anotherFirst", "max");
  1000. entity.setProperty("anotherLast", "notross");
  1001. ds.put(entity);
  1002. Query q = em.createQuery(
  1003. "select from " + Person.class.getName()
  1004. + " c where name.first = \"max\" AND anotherName.last = \"notross\"");
  1005. @SuppressWarnings("unchecked")
  1006. List<Person> result = (List<Person>) q.getResultList();
  1007. assertEquals(1, result.size());
  1008. }
  1009. public void testFilterBySubObject_UnknownField() {
  1010. try {
  1011. em.createQuery(
  1012. "select from " + Flight.class.getName() + " c where origin.first = \"max\"")
  1013. .getResultList();
  1014. fail("expected exception");
  1015. } catch (PersistenceException e) {
  1016. // good
  1017. }
  1018. }
  1019. public void testFilterBySubObject_NotEmbeddable() {
  1020. try {
  1021. em.createQuery(
  1022. "select from " + HasOneToOneJPA.class.getName() + " c where flight.origin = \"max\"")
  1023. .getResultList();
  1024. fail("expected exception");
  1025. } catch (PersistenceException e) {
  1026. // good
  1027. }
  1028. }
  1029. public void testSortByEmbeddedField() {
  1030. Entity entity = new Entity(Person.class.getSimpleName());
  1031. entity.setProperty("first", "max");
  1032. entity.setProperty("last", "ross");
  1033. entity.setProperty("anotherFirst", "notmax");
  1034. entity.setProperty("anotherLast", "notross");
  1035. ds.put(entity);
  1036. entity = new Entity(Person.class.getSimpleName());
  1037. entity.setProperty("first", "max2");
  1038. entity.setProperty("last", "ross2");
  1039. entity.setProperty("anotherFirst", "notmax2");
  1040. entity.setProperty("anotherLast", "notross2");
  1041. ds.put(entity);
  1042. Query q = em.createQuery("select from " + Person.class.getName() + " c order by name.first desc");
  1043. @SuppressWarnings("unchecked")
  1044. List<Person> result = (List<Person>) q.getResultList();
  1045. assertEquals(2, result.size());
  1046. assertEquals("max2", result.get(0).getName().getFirst());
  1047. assertEquals("max", result.get(1).getName().getFirst());
  1048. }
  1049. public void testSortByEmbeddedField_OverriddenColumn() {
  1050. Entity entity = new Entity(Person.class.getSimpleName());
  1051. entity.setProperty("first", "max");
  1052. entity.setProperty("last", "ross");
  1053. entity.setProperty("anotherFirst", "notmax");
  1054. entity.setProperty("anotherLast", "notross");
  1055. ds.put(entity);
  1056. entity = new Entity(Person.class.getSimpleName());
  1057. entity.setProperty("first", "max2");
  1058. entity.setProperty("last", "ross2");
  1059. entity.setProperty("anotherFirst", "notmax2");
  1060. entity.setProperty("anotherLast", "notross2");
  1061. ds.put(entity);
  1062. Query q =
  1063. em.createQuery("select from " + Person.class.getName() + " c order by anotherName.last desc");
  1064. @SuppressWarnings("unchecked")
  1065. List<Person> result = (List<Person>) q.getResultList();
  1066. assertEquals(2, result.size());
  1067. assertEquals("notross2", result.get(0).getAnotherName().getLast());
  1068. assertEquals("notross", result.get(1).getAnotherName().getLast());
  1069. }
  1070. public void testSortByEmbeddedField_MultipleFields() {
  1071. Entity entity0 = new Entity(Person.class.getSimpleName());
  1072. entity0.setProperty("first", "max");
  1073. entity0.setProperty("last", "ross");
  1074. entity0.setProperty("anotherFirst", "notmax");
  1075. entity0.setProperty("anotherLast", "z");
  1076. ds.put(entity0);
  1077. Entity entity1 = new Entity(Person.class.getSimpleName());
  1078. entity1.setProperty("first", "max");
  1079. entity1.setProperty("last", "ross2");
  1080. entity1.setProperty("anotherFirst", "notmax2");
  1081. entity1.setProperty("anotherLast", "notross2");
  1082. ds.put(entity1);
  1083. Entity entity2 = new Entity(Person.class.getSimpleName());
  1084. entity2.setProperty("first", "a");
  1085. entity2.setProperty("last", "b");
  1086. entity2.setProperty("anotherFirst", "c");
  1087. entity2.setProperty("anotherLast", "d");
  1088. ds.put(entity2);
  1089. Query q = em.createQuery(
  1090. "select from " + Person.class.getName()
  1091. + " c order by name.first asc, anotherName.last desc");
  1092. @SuppressWarnings("unchecked")
  1093. List<Person> result = (List<Person>) q.getResultList();
  1094. assertEquals(3, result.size());
  1095. assertEquals(Long.valueOf(entity2.getKey().getId()), result.get(0).getId());
  1096. assertEquals(Long.valueOf(entity0.getKey().getId()), result.get(1).getId());
  1097. assertEquals(Long.valueOf(entity1.getKey().getId()), result.get(2).getId());
  1098. }
  1099. public void testSortBySubObject_UnknownField() {
  1100. try {
  1101. Query q = em.createQuery("select from " + Book.class.getName() + " c order by author.first");
  1102. q.setHint(DatastoreManager.QUERYEXT_INMEMORY_WHEN_UNSUPPORTED, "false");
  1103. q.getResultList();
  1104. fail("expected exception");
  1105. } catch (PersistenceException e) {
  1106. // good
  1107. }
  1108. }
  1109. public void testSortBySubObject_NotEmbeddable() {
  1110. try {
  1111. Query q = em.createQuery(
  1112. "select from " + HasOneToOneJPA.class.getName() + " c order by book.author");
  1113. q.setHint(DatastoreManager.QUERYEXT_INMEMORY_WHEN_UNSUPPORTED, "false");
  1114. q.getResultList();
  1115. fail("expected exception");
  1116. } catch (PersistenceException e) {
  1117. // good
  1118. }
  1119. }
  1120. public void testBigDecimalQuery() {
  1121. Map<String, String> props = new HashMap<String, String>();
  1122. props.put("datanucleus.appengine.BigDecimalsEncoding", "String");
  1123. switchDatasource(EntityManagerFactoryName.originalStorageVersion, props);
  1124. Entity e = KitchenSink.newKitchenSinkEntity("blarg", null);
  1125. ds.put(e);
  1126. Query q = em.createQuery(
  1127. "select from " + KitchenSink.class.getName() + " c where bigDecimal = :bd");
  1128. q.setParameter("bd", new BigDecimal("2.444"));
  1129. @SuppressWarnings("unchecked")
  1130. List<KitchenSink> results = (List<KitchenSink>) q.getResultList();
  1131. assertEquals(1, results.size());
  1132. }
  1133. public void testBigDecimalInequalityQuery() {
  1134. Map<String, String> props = new HashMap<String, String>();
  1135. props.put("datanucleus.appengine.BigDecimalsEncoding", "String");
  1136. switchDatasource(EntityManagerFactoryName.originalStorageVersion, props);
  1137. Entity e = KitchenSink.newKitchenSinkEntity("blarg", null);
  1138. ds.put(e);
  1139. Query q = em.createQuery(
  1140. "select from " + KitchenSink.class.getName() + " c where bigDecimal < :bd1 and bigDecimal > :bd2");
  1141. q.setParameter("bd1", new BigDecimal("3"));
  1142. q.setParameter("bd2", new BigDecimal("2"));
  1143. @SuppressWarnings("unchecked")
  1144. List<KitchenSink> results = (List<KitchenSink>) q.getResultList();
  1145. assertEquals(1, results.size());
  1146. }
  1147. public void testQueryWithLiteralFloat() {
  1148. Entity e = new Entity(HasFloatJPA.class.getSimpleName());
  1149. e.setProperty("aFloat", -2.23f);
  1150. ds.put(e);
  1151. Query q = em.createQuery(
  1152. "select from " + HasFloatJPA.class.getName() + " c where aFloat > -2.25");
  1153. @SuppressWarnings("unchecked")
  1154. List<KitchenSink> results = (List<KitchenSink>) q.getResultList();
  1155. assertEquals(1, results.size());
  1156. }
  1157. public void testQueryWithNegativeLiteralLong() {
  1158. ds.put(Book.newBookEntity("auth", "123432", "title", -40));
  1159. Query q = em.createQuery(
  1160. "select from " + Book.class.getName() + " c where firstPublished = -40");
  1161. @SuppressWarnings("unchecked")
  1162. List<Book> results = (List<Book>) q.getResultList();
  1163. assertEquals(1, results.size());
  1164. q = em.createQuery(
  1165. "select from " + Book.class.getName() + " c where firstPublished > -41");
  1166. @SuppressWarnings("unchecked")
  1167. List<Book> results2 = (List<Book>) q.getResultList();
  1168. assertEquals(1, results2.size());
  1169. }
  1170. public void testQueryWithNegativeLiteralDouble() {
  1171. Entity e = new Entity(HasDoubleJPA.class.getSimpleName());
  1172. e.setProperty("aDouble", -2.23d);
  1173. ds.put(e);
  1174. Query q = em.createQuery(
  1175. "select from " + HasDoubleJPA.class.getName() + " c where aDouble > -2.25");
  1176. @SuppressWarnings("unchecked")
  1177. List<KitchenSink> results = (List<KitchenSink>) q.getResultList();
  1178. assertEquals(1, results.size());
  1179. }
  1180. public void testQueryWithNegativeParam() {
  1181. ds.put(Book.newBookEntity("auth", "123432", "title", -40));
  1182. Query q = em.createQuery(
  1183. "select from " + Book.class.getName() + " c where firstPublished = :p");
  1184. q.setParameter("p", -40);
  1185. @SuppressWarnings("unchecked")
  1186. List<Book> results = (List<Book>) q.getResultList();
  1187. assertEquals(1, results.size());
  1188. }
  1189. public void testKeyQueryWithUnencodedStringPk() {
  1190. Entity e = new Entity(HasUnencodedStringPkJPA.class.getSimpleName(), "yar");
  1191. ds.put(e);
  1192. Query q = em.createQuery(
  1193. "select from " + HasUnencodedStringPkJPA.class.getName() + " c where id = :p");
  1194. q.setParameter("p", e.getKey().getName());
  1195. @SuppressWarnings("unchecked")
  1196. List<HasUnencodedStringPkJPA> results =
  1197. (List<HasUnencodedStringPkJPA>) q.getResultList();
  1198. assertEquals(1, results.size());
  1199. assertEquals(e.getKey().getName(), results.get(0).getId());
  1200. q = em.createQuery(
  1201. "select from " + HasUnencodedStringPkJPA.class.getName() + " c where id = :p");
  1202. q.setParameter("p", e.getKey());
  1203. @SuppressWarnings("unchecked")
  1204. List<HasUnencodedStringPkJPA> results2 =
  1205. (List<HasUnencodedStringPkJPA>) q.getResultList();
  1206. assertEquals(1, results2.size());
  1207. assertEquals(e.getKey().getName(), results2.get(0).getId());
  1208. }
  1209. public void testKeyQueryWithLongPk() {
  1210. Entity e = new Entity(HasLongPkJPA.class.getSimpleName());
  1211. ds.put(e);
  1212. Query q = em.createQuery(
  1213. "select from " + HasLongPkJPA.class.getName() + " c where id = :p");
  1214. q.setParameter("p", e.getKey().getId());
  1215. @SuppressWarnings("unchecked")
  1216. List<HasLongPkJPA> results = (List<HasLongPkJPA>) q.getResultList();
  1217. assertEquals(1, results.size());
  1218. assertEquals(Long.valueOf(e.getKey().getId()), results.get(0).getId());
  1219. q = em.createQuery(
  1220. "select from " + HasLongPkJPA.class.getName() + " c where id = :p");
  1221. q.setParameter("p", e.getKey().getId());
  1222. @SuppressWarnings("unchecked")
  1223. List<HasLongPkJPA> results2 = (List<HasLongPkJPA>) q.getResultList();
  1224. assertEquals(1, results2.size());
  1225. assertEquals(Long.valueOf(e.getKey().getId()), results2.get(0).getId());
  1226. }
  1227. public void testKeyQueryWithEncodedStringPk() {
  1228. Entity e = new Entity(HasEncodedStringPkJPA.class.getSimpleName(), "yar");
  1229. ds.put(e);
  1230. Query q = em.createQuery("select from " + HasEncodedStringPkJPA.class.getName() + " c where id = :p");
  1231. q.setParameter("p", e.getKey().getName());
  1232. HasEncodedStringPkJPA result = (HasEncodedStringPkJPA) q.getSingleResult();
  1233. assertEquals(KeyFactory.keyToString(e.getKey()), result.getId());
  1234. q = em.createQuery("select from " + HasEncodedStringPkJPA.class.getName() + " c where id = :p");
  1235. q.setParameter("p", e.getKey());
  1236. result = (HasEncodedStringPkJPA) q.getSingleResult();
  1237. assertEquals(KeyFactory.keyToString(e.getKey()), result.getId());
  1238. q = em.createQuery("select from " + HasEncodedStringPkJPA.class.getName() + " c where id = :p");
  1239. q.setParameter("p", e.getKey().getName());
  1240. result = (HasEncodedStringPkJPA) q.getSingleResult();
  1241. assertEquals(KeyFactory.keyToString(e.getKey()), result.getId());
  1242. }
  1243. public void testQuerySingleResult_OneResult() {
  1244. Entity e = Book.newBookEntity("max", "12345", "t1");
  1245. ds.put(e);
  1246. Query q = em.createQuery(
  1247. "select from " + Book.class.getName() + " c where title = :p");
  1248. q.setParameter("p", "t1");
  1249. Book pojo = (Book) q.getSingleResult();
  1250. assertEquals(e.getKey(), KeyFactory.stringToKey(pojo.getId()));
  1251. }
  1252. public void testQuerySingleResult_NoResult() {
  1253. Entity e = Book.newBookEntity("max", "12345", "t1");
  1254. ds.put(e);
  1255. Query q = em.createQuery(
  1256. "select from " + Book.class.getName() + " c where title = :p");
  1257. q.setParameter("p", "not t1");
  1258. try {
  1259. q.getSingleResult();
  1260. fail("expected exception");
  1261. } catch (NoResultException ex) {
  1262. // good
  1263. }
  1264. }
  1265. public void testQuerySingleResult_MultipleResults() {
  1266. Entity e1 = Book.newBookEntity("max", "12345", "t1");
  1267. Entity e2 = Book.newBookEntity("max", "12345", "t1");
  1268. ds.put(e1);
  1269. ds.put(e2);
  1270. Query q = em.createQuery(
  1271. "select from " + Book.class.getName() + " c where title = :p");
  1272. q.setParameter("p", "t1");
  1273. try {
  1274. q.getSingleResult();
  1275. fail("expected exception");
  1276. } catch (NonUniqueResultException ex) {
  1277. // good
  1278. }
  1279. }
  1280. public void testSortByUnknownProperty() {
  1281. try {
  1282. Query q = em.createQuery("select from " + Book.class.getName() + " c order by dne");
  1283. q.setHint(DatastoreManager.QUERYEXT_INMEMORY_WHEN_UNSUPPORTED, "false");
  1284. q.getResultList();
  1285. fail("expected exception");
  1286. } catch (PersistenceException e) {
  1287. // good
  1288. }
  1289. }
  1290. public void testDatastoreFailureWhileIterating() {
  1291. // Need to have enough data to ensure a Next call
  1292. for (int i = 0; i < 21; i++) {
  1293. Entity bookEntity = Book.newBookEntity("Joe Blow", "67890", "Bar Book");
  1294. ds.put(bookEntity);
  1295. }
  1296. ExceptionThrowingDatastoreDelegate.ExceptionPolicy policy =
  1297. new ExceptionThrowingDatastoreDelegate.BaseExceptionPolicy() {
  1298. boolean exploded = false;
  1299. protected void doIntercept(String methodName) {
  1300. if (!exploded && methodName.equals("Next")) {
  1301. exploded = true;
  1302. throw new DatastoreFailureException("boom: " + methodName);
  1303. }
  1304. }
  1305. };
  1306. ApiProxy.Delegate original = getDelegateForThread();
  1307. ExceptionThrowingDatastoreDelegate dd =
  1308. new ExceptionThrowingDatastoreDelegate(getDelegateForThread(), policy);
  1309. setDelegateForThread(dd);
  1310. try {
  1311. javax.persistence.Query q = em.createQuery(
  1312. "select from " + Book.class.getName() + " b");
  1313. try {
  1314. @SuppressWarnings("unchecked")
  1315. List<Book> books = (List<Book>) q.getResultList();
  1316. books.size();
  1317. fail("expected exception");
  1318. } catch (PersistenceException e) {
  1319. // good
  1320. assertTrue(e.getCause() instanceof DatastoreFailureException);
  1321. }
  1322. } finally {
  1323. setDelegateForThread(original);
  1324. }
  1325. }
  1326. public void testBadRequest() {
  1327. ExceptionThrowingDatastoreDelegate.ExceptionPolicy policy =
  1328. new ExceptionThrowingDatastoreDelegate.BaseExceptionPolicy() {
  1329. int count = 0;
  1330. protected void doIntercept(String methodName) {
  1331. count++;
  1332. if (count == 1) {
  1333. throw new IllegalArgumentException("boom");
  1334. }
  1335. }
  1336. };
  1337. ApiProxy.Delegate original = getDelegateForThread();
  1338. ExceptionThrowingDatastoreDelegate dd =
  1339. new ExceptionThrowingDatastoreDelegate(getDelegateForThread(), policy);
  1340. setDelegateForThread(dd);
  1341. try {
  1342. Query q = em.createQuery("select from " + Book.class.getName() + " b");
  1343. try {
  1344. q.getResultList();
  1345. fail("expected exception");
  1346. } catch (PersistenceException e) {
  1347. // good
  1348. assertTrue(e.getCause() instanceof IllegalArgumentException);
  1349. }
  1350. } finally {
  1351. setDelegateForThread(original);
  1352. }
  1353. }
  1354. public void testCountQuery() {
  1355. Query q = em.createQuery("select count(id) from " + Book.class.getName() + " c");
  1356. assertEquals(0l, q.getSingleResult());
  1357. Entity e1 = Book.newBookEntity("jimmy", "12345", "the title", 2003);
  1358. Entity e2 = Book.newBookEntity("jimmy", "12345", "the title", 2004);
  1359. ds.put(e1);
  1360. ds.put(e2);
  1361. q = em.createQuery("select count(id) from " + Book.class.getName() + " c");
  1362. assertEquals(2l, q.getSingleResult());
  1363. q = em.createQuery("select COUNT(id) from " + Book.class.getName() + " c");
  1364. assertEquals(2l, q.getSingleResult());
  1365. q = em.createQuery("select Count(id) from " + Book.class.getName() + " c");
  1366. assertEquals(2l, q.getSingleResult());
  1367. }
  1368. public void testProjectionQueryTyped() {
  1369. Entity e1 = Book.newBookEntity("jimmy", "12345", "the title", 2003);
  1370. Entity e2 = Book.newBookEntity("jimmy", "12345", "the title", 2004);
  1371. ds.put(e1);
  1372. ds.put(e2);
  1373. TypedQuery<Integer> q = em.createQuery(
  1374. "select firstPublished from " + Book.class.getName() + " b ORDER BY firstPublished ASC", Integer.class);
  1375. List<Integer> result = q.getResultList();
  1376. Iterator<Integer> resultIter = result.iterator();
  1377. Integer first = resultIter.next();
  1378. Integer second = resultIter.next();
  1379. assertEquals(2003, first.intValue());
  1380. assertEquals(2004, second.intValue());
  1381. }
  1382. public void testProjectionWithCreator() {
  1383. Entity e1 = Book.newBookEntity("jimmy", "12345", "the title 1", 2003);
  1384. Entity e2 = Book.newBookEntity("bobby", "12346", "the title 2", 2004);
  1385. ds.put(e1);
  1386. ds.put(e2);
  1387. TypedQuery<BookSummary> q = em.createQuery(
  1388. "SELECT NEW " + BookSummary.class.getName() + "(author, title) FROM " + Book.class.getName() + " b" +
  1389. " ORDER BY firstPublished ASC", BookSummary.class);
  1390. List<BookSummary> result = q.getResultList();
  1391. assertEquals("Number of results is wrong", 2, result.size());
  1392. Iterator<BookSummary> resultIter = result.iterator();
  1393. BookSummary first = resultIter.next();
  1394. BookSummary second = resultIter.next();
  1395. assertEquals("jimmy", first.getAuthor());
  1396. assertEquals("bobby", second.getAuthor());
  1397. assertEquals("the title 1", first.getTitle());
  1398. assertEquals("the title 2", second.getTitle());
  1399. }
  1400. public void testCountQueryWithFilter() {
  1401. Entity e1 = Book.newBookEntity("jimmy", "12345", "the title", 2003);
  1402. Entity e2 = Book.newBookEntity("jimmy", "12345", "the title", 2004);
  1403. ds.put(e1);
  1404. ds.put(e2);
  1405. Query q = em.createQuery(
  1406. "select count(id) from " + Book.class.getName() + " c" + " where firstPublished = 2003");
  1407. assertEquals(1l, q.getSingleResult());
  1408. }
  1409. public void testCountQueryWithUnknownCountProp() {
  1410. Entity e1 = Book.newBookEntity("jimmy", "12345", "the title", 2003);
  1411. Entity e2 = Book.newBookEntity("jimmy", "12345", "the title", 2004);
  1412. ds.put(e1);
  1413. ds.put(e2);
  1414. Query q = em.createQuery("select count(doesnotexist) from " + Book.class.getName() + " c");
  1415. try {
  1416. q.getSingleResult();
  1417. fail("expected exception");
  1418. } catch (PersistenceException e) {
  1419. // good
  1420. }
  1421. }
  1422. public void testCountQueryWithOffset() {
  1423. Entity e1 = Book.newBookEntity("jimmy", "12345", "the title", 2003);
  1424. Entity e2 = Book.newBookEntity("jimmy", "12345", "the title", 2004);
  1425. ds.put(e1);
  1426. ds.put(e2);
  1427. Query q = em.createQuery("select count(id) from " + Book.class.getName() + " c");
  1428. q.setFirstResult(1);
  1429. assertEquals(1l, q.getSingleResult());
  1430. }
  1431. public void testCountQueryWithLimit() {
  1432. Entity e1 = Book.newBookEntity("jimmy", "12345", "the title", 2003);
  1433. Entity e2 = Book.newBookEntity("jimmy", "12345", "the title", 2004);
  1434. ds.put(e1);
  1435. ds.put(e2);
  1436. Query q = em.createQuery("select count(id) from " + Book.class.getName() + " c");
  1437. q.setMaxResults(1);
  1438. assertEquals(1l, q.getSingleResult());
  1439. }
  1440. public void testCountQueryWithOffsetAndLimit() {
  1441. Entity e1 = Book.newBookEntity("jimmy", "12345", "the title", 2003);
  1442. Entity e2 = Book.newBookEntity("jimmy", "12345", "the title", 2004);
  1443. Entity e3 = Book.newBookEntity("jimmy", "12345", "the title", 2005);
  1444. ds.put(e1);
  1445. ds.put(e2);
  1446. ds.put(e3);
  1447. Query q = em.createQuery("select count(id) from " + Book.class.getName() + " c");
  1448. q.setFirstResult(1);
  1449. q.setMaxResults(1);
  1450. assertEquals(1l, q.getSingleResult());
  1451. }
  1452. public void testFilterByEnum_ProvideStringExplicitly() {
  1453. Entity e = new Entity(HasEnumJPA.class.getSimpleName());
  1454. e.setProperty("myEnum", HasEnumJPA.MyEnum.V1.name());
  1455. ds.put(e);
  1456. Query q = em.createQuery("select from " + HasEnumJPA.class.getName() + " c" + " where myEnum = :p1");
  1457. q.setParameter("p1", HasEnumJPA.MyEnum.V1.name());
  1458. List<HasEnumJPA> result = (List<HasEnumJPA>) q.getResultList();
  1459. assertEquals(1, result.size());
  1460. }
  1461. public void testFilterByEnum_ProvideEnumExplicitly() {
  1462. Entity e = new Entity(HasEnumJPA.class.getSimpleName());
  1463. e.setProperty("myEnum", HasEnumJPA.MyEnum.V1.name());
  1464. ds.put(e);
  1465. Query q = em.createQuery("select from " + HasEnumJPA.class.getName() + " c" + " where myEnum = :p1");
  1466. q.setParameter("p1", HasEnumJPA.MyEnum.V1);
  1467. List<HasEnumJPA> result = (List<HasEnumJPA>) q.getResultList();
  1468. assertEquals(1, result.size());
  1469. }
  1470. public void testFilterByEnum_ProvideLiteral() {
  1471. Entity e = new Entity(HasEnumJPA.class.getSimpleName());
  1472. e.setProperty("myEnum", HasEnumJPA.MyEnum.V1.name());
  1473. ds.put(e);
  1474. Query q = em.createQuery(
  1475. "select from " + HasEnumJPA.class.getName() + " c" + " where myEnum = '"
  1476. + HasEnumJPA.MyEnum.V1.name() + "'");
  1477. List<HasEnumJPA> result = (List<HasEnumJPA>) q.getResultList();
  1478. assertEquals(1, result.size());
  1479. }
  1480. public void testFilterByShortBlob() {
  1481. Entity e = new Entity(HasBytesJPA.class.getSimpleName());
  1482. e.setProperty("onePrimByte", 8L);
  1483. e.setProperty("shortBlob", new ShortBlob("short blob".getBytes()));
  1484. ds.put(e);
  1485. Query
  1486. q =
  1487. em.createQuery("select from " + HasBytesJPA.class.getName() + " c" + " where shortBlob = :p1");
  1488. q.setParameter("p1", new ShortBlob("short blob".getBytes()));
  1489. List<HasBytesJPA> result = (List<HasBytesJPA>) q.getResultList();
  1490. assertEquals(1, result.size());
  1491. }
  1492. public void testFilterByPrimitiveByteArray() {
  1493. Entity e = new Entity(HasBytesJPA.class.getSimpleName());
  1494. e.setProperty("onePrimByte", 8L);
  1495. e.setProperty("primBytes", new ShortBlob("short blob".getBytes()));
  1496. ds.put(e);
  1497. Query
  1498. q =
  1499. em.createQuery("select from " + HasBytesJPA.class.getName() + " c" + " where primBytes = :p1");
  1500. q.setParameter("p1", "short blob".getBytes());
  1501. List<HasBytesJPA> result = (List<HasBytesJPA>) q.getResultList();
  1502. assertEquals(1, result.size());
  1503. }
  1504. public void testFilterByByteArray() {
  1505. Entity e = new Entity(HasBytesJPA.class.getSimpleName());
  1506. e.setProperty("onePrimByte", 8L);
  1507. e.setProperty("bytes", new ShortBlob("short blob".getBytes()));
  1508. ds.put(e);
  1509. Query q = em.createQuery("select from " + HasBytesJPA.class.getName() + " c" + " where bytes = :p1");
  1510. q.setParameter("p1", PrimitiveArrays.asList("short blob".getBytes()).toArray(new Byte[0]));
  1511. List<HasBytesJPA> result = (List<HasBytesJPA>) q.getResultList();
  1512. assertEquals(1, result.size());
  1513. }
  1514. public void testAliasedFilter() {
  1515. Entity bookEntity = Book.newBookEntity("Joe Blow", "67890", "Bar Book");
  1516. ds.put(bookEntity);
  1517. javax.persistence.Query q = em.createQuery(
  1518. "select from " + Book.class.getName() + " b where b.id = :key");
  1519. q.setParameter("key", KeyFactory.keyToString(bookEntity.getKey()));
  1520. @SuppressWarnings("unchecked")
  1521. List<Book> books = (List<Book>) q.getResultList();
  1522. assertEquals(1, books.size());
  1523. assertEquals(bookEntity.getKey(), KeyFactory.stringToKey(books.get(0).getId()));
  1524. }
  1525. public void testAliasedSort() {
  1526. Entity bookEntity1 = Book.newBookEntity("Joe Blow", "67891", "Bar Book");
  1527. Entity bookEntity2 = Book.newBookEntity("Joe Blow", "67890", "Bar Book");
  1528. ds.put(bookEntity1);
  1529. ds.put(bookEntity2);
  1530. javax.persistence.Query q = em.createQuery(
  1531. "select from " + Book.class.getName() + " b order by b.isbn");
  1532. @SuppressWarnings("unchecked")
  1533. List<Book> books = (List<Book>) q.getResultList();
  1534. assertEquals(2, books.size());
  1535. assertEquals(bookEntity2.getKey(), KeyFactory.stringToKey(books.get(0).getId()));
  1536. assertEquals(bookEntity1.getKey(), KeyFactory.stringToKey(books.get(1).getId()));
  1537. }
  1538. public void testAliasedEmbeddedFilter() {
  1539. Entity entity = new Entity(Person.class.getSimpleName());
  1540. entity.setProperty("first", "max");
  1541. entity.setProperty("last", "ross");
  1542. entity.setProperty("anotherFirst", "notmax");
  1543. entity.setProperty("anotherLast", "notross");
  1544. ds.put(entity);
  1545. Query q = em.createQuery(
  1546. "select from " + Person.class.getName() + " p where p.name.first = \"max\"");
  1547. @SuppressWarnings("unchecked")
  1548. List<Person> result = (List<Person>) q.getResultList();
  1549. assertEquals(1, result.size());
  1550. }
  1551. public void testAliasedEmbeddedSort() {
  1552. Entity entity1 = new Entity(Person.class.getSimpleName());
  1553. entity1.setProperty("first", "max");
  1554. entity1.setProperty("last", "ross");
  1555. entity1.setProperty("anotherFirst", "notmax2");
  1556. entity1.setProperty("anotherLast", "notross");
  1557. ds.put(entity1);
  1558. Entity entity2 = new Entity(Person.class.getSimpleName());
  1559. entity2.setProperty("first", "max");
  1560. entity2.setProperty("last", "ross");
  1561. entity2.setProperty("anotherFirst", "notmax1");
  1562. entity2.setProperty("anotherLast", "notross");
  1563. ds.put(entity2);
  1564. Query q = em.createQuery(
  1565. "select from " + Person.class.getName() + " p order by p.anotherName.first");
  1566. @SuppressWarnings("unchecked")
  1567. List<Person> result = (List<Person>) q.getResultList();
  1568. assertEquals(2, result.size());
  1569. assertEquals(entity2.getKey(), TestUtils.createKey(Person.class, result.get(0).getId()));
  1570. assertEquals(entity1.getKey(), TestUtils.createKey(Person.class, result.get(1).getId()));
  1571. }
  1572. public void testFilterByNullValue_Literal() {
  1573. Entity e = new Entity(NullDataJPA.class.getSimpleName());
  1574. e.setProperty("string", null);
  1575. ds.put(e);
  1576. Query q = em.createQuery("select from " + NullDataJPA.class.getName() + " c where string = null");
  1577. @SuppressWarnings("unchecked")
  1578. List<NullDataJPA> results = (List<NullDataJPA>) q.getResultList();
  1579. assertEquals(1, results.size());
  1580. }
  1581. public void testFilterByNullValue_Param() {
  1582. Entity e = new Entity(NullDataJPA.class.getSimpleName());
  1583. e.setProperty("string", null);
  1584. ds.put(e);
  1585. Query q = em.createQuery("select from " + NullDataJPA.class.getName() + " c where string = :p");
  1586. q.setParameter("p", null);
  1587. @SuppressWarnings("unchecked")
  1588. List<NullDataJPA> results = (List<NullDataJPA>) q.getResultList();
  1589. assertEquals(1, results.size());
  1590. }
  1591. public void testQueryForOneToManySetWithKeyPk() {
  1592. Entity e = new Entity(HasOneToManyKeyPkSetJPA.class.getSimpleName());
  1593. ds.put(e);
  1594. beginTxn();
  1595. Query q = em.createQuery("select from " + HasOneToManyKeyPkSetJPA.class.getName() + " c");
  1596. @SuppressWarnings("unchecked")
  1597. List<HasOneToManyKeyPkSetJPA> results = q.getResultList();
  1598. assertEquals(1, results.size());
  1599. assertEquals(0, results.get(0).getBooks().size());
  1600. commitTxn();
  1601. }
  1602. public void testQueryForOneToManyListWithKeyPk() {
  1603. Entity e = new Entity(HasOneToManyKeyPkListJPA.class.getSimpleName());
  1604. ds.put(e);
  1605. beginTxn();
  1606. Query q = em.createQuery("select from " + HasOneToManyKeyPkListJPA.class.getName() + " c");
  1607. @SuppressWarnings("unchecked")
  1608. List<HasOneToManyKeyPkListJPA> results = q.getResultList();
  1609. assertEquals(1, results.size());
  1610. assertEquals(0, results.get(0).getBooks().size());
  1611. commitTxn();
  1612. }
  1613. public void testQueryForOneToManySetWithLongPk() {
  1614. Entity e = new Entity(HasOneToManyLongPkSetJPA.class.getSimpleName());
  1615. ds.put(e);
  1616. beginTxn();
  1617. Query q = em.createQuery("select from " + HasOneToManyLongPkSetJPA.class.getName() + " c");
  1618. @SuppressWarnings("unchecked")
  1619. List<HasOneToManyLongPkSetJPA> results = q.getResultList();
  1620. assertEquals(1, results.size());
  1621. assertEquals(0, results.get(0).getBooks().size());
  1622. commitTxn();
  1623. }
  1624. public void testQueryForOneToManyListWithLongPk() {
  1625. Entity e = new Entity(HasOneToManyLongPkListJPA.class.getSimpleName());
  1626. ds.put(e);
  1627. beginTxn();
  1628. Query q = em.createQuery("select from " + HasOneToManyLongPkListJPA.class.getName() + " c");
  1629. @SuppressWarnings("unchecked")
  1630. List<HasOneToManyLongPkListJPA> results = q.getResultList();
  1631. assertEquals(1, results.size());
  1632. assertEquals(0, results.get(0).getBooks().size());
  1633. commitTxn();
  1634. }
  1635. public void testQueryForOneToManySetWithUnencodedStringPk() {
  1636. Entity e = new Entity(HasOneToManyUnencodedStringPkSetJPA.class.getSimpleName(), "yar");
  1637. ds.put(e);
  1638. beginTxn();
  1639. Query q = em.createQuery("select from " + HasOneToManyUnencodedStringPkSetJPA.class.getName() + " c");
  1640. @SuppressWarnings("unchecked")
  1641. List<HasOneToManyUnencodedStringPkSetJPA> results = q.getResultList();
  1642. assertEquals(1, results.size());
  1643. assertEquals(0, results.get(0).getBooks().size());
  1644. commitTxn();
  1645. }
  1646. public void testQueryForOneToManyListWithUnencodedStringPk() {
  1647. Entity e = new Entity(HasOneToManyUnencodedStringPkListJPA.class.getSimpleName(), "yar");
  1648. ds.put(e);
  1649. beginTxn();
  1650. Query q = em.createQuery("select from " + HasOneToManyUnencodedStringPkListJPA.class.getName() + " c ");
  1651. @SuppressWarnings("unchecked")
  1652. List<HasOneToManyUnencodedStringPkListJPA> results = q.getResultList();
  1653. assertEquals(1, results.size());
  1654. assertEquals(0, results.get(0).getBooks().size());
  1655. commitTxn();
  1656. }
  1657. public void testBatchGet_NoTxn() {
  1658. switchDatasource(EntityManagerFactoryName.nontransactional_ds_non_transactional_ops_allowed);
  1659. Entity e1 = Book.newBookEntity("auth", "123432", "title", -40);
  1660. ds.put(e1);
  1661. Entity e2 = Book.newBookEntity("auth", "123432", "title", -40);
  1662. ds.put(e2);
  1663. Entity e3 = Book.newBookEntity("auth", "123432", "title", -40);
  1664. ds.put(e3);
  1665. Key key = KeyFactory.createKey("yar", "does not exist");
  1666. NoQueryDelegate nqd = new NoQueryDelegate().install();
  1667. try {
  1668. Query q = em.createQuery("select from " + Book.class.getName() + " c" + " where id = :ids");
  1669. q.setParameter("ids", Utils.newArrayList(key, e1.getKey(), e2.getKey()));
  1670. @SuppressWarnings("unchecked")
  1671. List<Book> books = (List<Book>) q.getResultList();
  1672. assertEquals(2, books.size());
  1673. assertEquals(e1.getKey(), KeyFactory.stringToKey(books.get(0).getId()));
  1674. assertEquals(e2.getKey(), KeyFactory.stringToKey(books.get(1).getId()));
  1675. } finally {
  1676. nqd.uninstall();
  1677. }
  1678. }
  1679. public void testBatchGet_NoTxn_EncodedStringParam() {
  1680. switchDatasource(EntityManagerFactoryName.nontransactional_ds_non_transactional_ops_allowed);
  1681. Entity e1 = Book.newBookEntity("auth", "123432", "title", -40);
  1682. ds.put(e1);
  1683. Entity e2 = Book.newBookEntity("auth", "123432", "title", -40);
  1684. ds.put(e2);
  1685. Entity e3 = Book.newBookEntity("auth", "123432", "title", -40);
  1686. ds.put(e3);
  1687. Key key = KeyFactory.createKey("yar", "does not exist");
  1688. NoQueryDelegate nqd = new NoQueryDelegate().install();
  1689. try {
  1690. Query q = em.createQuery("select from " + Book.class.getName() + " c" + " where id = :ids");
  1691. q.setParameter("ids", Utils.newArrayList(
  1692. KeyFactory.keyToString(key),
  1693. KeyFactory.keyToString(e1.getKey()),
  1694. KeyFactory.keyToString(e2.getKey())));
  1695. @SuppressWarnings("unchecked")
  1696. List<Book> books = (List<Book>) q.getResultList();
  1697. assertEquals(2, books.size());
  1698. assertEquals(e1.getKey(), KeyFactory.stringToKey(books.get(0).getId()));
  1699. assertEquals(e2.getKey(), KeyFactory.stringToKey(books.get(1).getId()));
  1700. } finally {
  1701. nqd.uninstall();
  1702. }
  1703. }
  1704. public void testBatchGet_NoTxn_In() {
  1705. switchDatasource(EntityManagerFactoryName.nontransactional_ds_non_transactional_ops_allowed);
  1706. Entity e1 = Book.newBookEntity("auth", "123432", "title", -40);
  1707. ds.put(e1);
  1708. Entity e2 = Book.newBookEntity("auth", "123432", "title", -40);
  1709. ds.put(e2);
  1710. Entity e3 = Book.newBookEntity("auth", "123432", "title", -40);
  1711. ds.put(e3);
  1712. NoQueryDelegate nqd = new NoQueryDelegate().install();
  1713. try {
  1714. Key key = KeyFactory.createKey("yar", "does not exist");
  1715. Query q = em.createQuery("select from " + Book.class.getName() + " c" + " where id IN (:ids)");
  1716. q.setParameter("ids", Utils.newArrayList(key, e1.getKey(), e2.getKey()));
  1717. @SuppressWarnings("unchecked")
  1718. List<Book> books = (List<Book>) q.getResultList();
  1719. assertEquals(2, books.size());
  1720. assertEquals(e1.getKey(), KeyFactory.stringToKey(books.get(0).getId()));
  1721. assertEquals(e2.getKey(), KeyFactory.stringToKey(books.get(1).getId()));
  1722. q = em.createQuery("select from " + Book.class.getName() + " c" + " where id IN (:id1, :id2, :id3)");
  1723. q.setParameter("id1", key);
  1724. q.setParameter("id2", e1.getKey());
  1725. q.setParameter("id3", e2.getKey());
  1726. books = (List<Book>) q.getResultList();
  1727. assertEquals(2, books.size());
  1728. assertEquals(e1.getKey(), KeyFactory.stringToKey(books.get(0).getId()));
  1729. assertEquals(e2.getKey(), KeyFactory.stringToKey(books.get(1).getId()));
  1730. q = em.createQuery("select from " + Book.class.getName() + " c" + " where "
  1731. + "id IN (:id1, :id3) OR id IN (:id2)");
  1732. q.setParameter("id1", key);
  1733. q.setParameter("id2", e1.getKey());
  1734. q.setParameter("id3", e2.getKey());
  1735. books = (List<Book>) q.getResultList();
  1736. assertEquals(2, books.size());
  1737. assertEquals(e1.getKey(), KeyFactory.stringToKey(books.get(1).getId()));
  1738. assertEquals(e2.getKey(), KeyFactory.stringToKey(books.get(0).getId()));
  1739. } finally {
  1740. nqd.uninstall();
  1741. }
  1742. }
  1743. public void testBatchGet_Count_NoTxn() {
  1744. switchDatasource(EntityManagerFactoryName.nontransactional_ds_non_transactional_ops_allowed);
  1745. Entity e1 = Book.newBookEntity("auth", "123432", "title", -40);
  1746. ds.put(e1);
  1747. Entity e2 = Book.newBookEntity("auth", "123432", "title", -40);
  1748. ds.put(e2);
  1749. Entity e3 = Book.newBookEntity("auth", "123432", "title", -40);
  1750. ds.put(e3);
  1751. NoQueryDelegate nqd = new NoQueryDelegate().install();
  1752. try {
  1753. Key key = KeyFactory.createKey("yar", "does not exist");
  1754. Query q = em.createQuery("select count(id) from " + Book.class.getName() + " c" + " where id = :ids");
  1755. q.setParameter("ids", Utils.newArrayList(key, e1.getKey(), e2.getKey()));
  1756. long count = (Long) q.getSingleResult();
  1757. assertEquals(2l, count);
  1758. } finally {
  1759. nqd.uninstall();
  1760. }
  1761. }
  1762. public void testBatchGet_Count_NoTxn_In() {
  1763. switchDatasource(EntityManagerFactoryName.nontransactional_ds_non_transactional_ops_allowed);
  1764. Entity e1 = Book.newBookEntity("auth", "123432", "title", -40);
  1765. ds.put(e1);
  1766. Entity e2 = Book.newBookEntity("auth", "123432", "title", -40);
  1767. ds.put(e2);
  1768. Entity e3 = Book.newBookEntity("auth", "123432", "title", -40);
  1769. ds.put(e3);
  1770. NoQueryDelegate nqd = new NoQueryDelegate().install();
  1771. try {
  1772. Key key = KeyFactory.createKey("yar", "does not exist");
  1773. Query q = em.createQuery("select count(id) from " + Book.class.getName() + " c" + " where id IN (:ids)");
  1774. q.setParameter("ids", Utils.newArrayList(key, e1.getKey(), e2.getKey()));
  1775. long count = (Long) q.getSingleResult();
  1776. assertEquals(2l, count);
  1777. q = em.createQuery("select count(id) from " + Book.class.getName() + " c" + " where id IN (:id1, :id2, :id3)");
  1778. q.setParameter("id1", key);
  1779. q.setParameter("id2", e1.getKey());
  1780. q.setParameter("id3", e2.getKey());
  1781. count = (Long) q.getSingleResult();
  1782. assertEquals(2l, count);
  1783. } finally {
  1784. nqd.uninstall();
  1785. }
  1786. }
  1787. public void testBatchGet_Txn() {
  1788. Entity e1 = Book.newBookEntity("auth", "123432", "title", -40);
  1789. ds.put(e1);
  1790. Entity e2 = Book.newBookEntity(e1.getKey(), "auth", "123432", "title", -40);
  1791. ds.put(e2);
  1792. Entity e3 = Book.newBookEntity("auth", "123432", "title", -40);
  1793. ds.put(e3);
  1794. NoQueryDelegate nqd = new NoQueryDelegate().install();
  1795. try {
  1796. Key key = KeyFactory.createKey(e1.getKey(), "yar", "does not exist");
  1797. Query q = em.createQuery("select from " + Book.class.getName() + " c" + " where id = :ids");
  1798. q.setParameter("ids", Utils.newArrayList(key, e1.getKey(), e2.getKey()));
  1799. @SuppressWarnings("unchecked")
  1800. List<Book> books = (List<Book>) q.getResultList();
  1801. assertEquals(2, books.size());
  1802. assertEquals(e1.getKey(), KeyFactory.stringToKey(books.get(0).getId()));
  1803. assertEquals(e2.getKey(), KeyFactory.stringToKey(books.get(1).getId()));
  1804. } finally {
  1805. nqd.uninstall();
  1806. }
  1807. }
  1808. public void testBatchGet_Txn_In() {
  1809. Entity e1 = Book.newBookEntity("auth", "123432", "title", -40);
  1810. ds.put(e1);
  1811. Entity e2 = Book.newBookEntity(e1.getKey(), "auth", "123432", "title", -40);
  1812. ds.put(e2);
  1813. Entity e3 = Book.newBookEntity("auth", "123432", "title", -40);
  1814. ds.put(e3);
  1815. NoQueryDelegate nqd = new NoQueryDelegate().install();
  1816. try {
  1817. Key key = KeyFactory.createKey(e1.getKey(), "yar", "does not exist");
  1818. Query q = em.createQuery("select from " + Book.class.getName() + " c" + " where id IN (:ids)");
  1819. q.setParameter("ids", Utils.newArrayList(key, e1.getKey(), e2.getKey()));
  1820. @SuppressWarnings("unchecked")
  1821. List<Book> books = (List<Book>) q.getResultList();
  1822. assertEquals(2, books.size());
  1823. assertEquals(e1.getKey(), KeyFactory.stringToKey(books.get(0).getId()));
  1824. assertEquals(e2.getKey(), KeyFactory.stringToKey(books.get(1).getId()));
  1825. q = em.createQuery("select from " + Book.class.getName() + " c" + " where id IN (:id1, :id2, :id3)");
  1826. q.setParameter("id1", key);
  1827. q.setParameter("id2", e1.getKey());
  1828. q.setParameter("id3", e2.getKey());
  1829. books = (List<Book>) q.getResultList();
  1830. assertEquals(2, books.size());
  1831. assertEquals(e1.getKey(), KeyFactory.stringToKey(books.get(0).getId()));
  1832. assertEquals(e2.getKey(), KeyFactory.stringToKey(books.get(1).getId()));
  1833. } finally {
  1834. nqd.uninstall();
  1835. }
  1836. }
  1837. public void testBatchGet_Illegal() {
  1838. switchDatasource(EntityManagerFactoryName.nontransactional_ds_non_transactional_ops_allowed);
  1839. Query q = em.createQuery("select from " + Flight.class.getName() + " c" + " where origin = :ids");
  1840. q.setParameter("ids", Utils.newArrayList());
  1841. q.setHint(DatastoreManager.QUERYEXT_INMEMORY_WHEN_UNSUPPORTED, "false");
  1842. try {
  1843. q.getResultList();
  1844. fail("expected exception");
  1845. } catch (PersistenceException e) {
  1846. // good
  1847. }
  1848. q = em.createQuery(
  1849. "select from " + Flight.class.getName() + " c" + " where id = :ids and origin = :origin");
  1850. q.setParameter("ids", Utils.newArrayList());
  1851. q.setParameter("origin", "bos");
  1852. q.setHint(DatastoreManager.QUERYEXT_INMEMORY_WHEN_UNSUPPORTED, "false");
  1853. try {
  1854. q.getResultList();
  1855. fail("expected exception");
  1856. } catch (PersistenceException e) {
  1857. // good
  1858. }
  1859. q = em.createQuery(
  1860. "select from " + Flight.class.getName() + " c" + " where origin = :origin and id = :ids");
  1861. q.setParameter("origin", "bos");
  1862. q.setParameter("ids", Utils.newArrayList());
  1863. q.setHint(DatastoreManager.QUERYEXT_INMEMORY_WHEN_UNSUPPORTED, "false");
  1864. try {
  1865. q.getResultList();
  1866. fail("expected exception");
  1867. } catch (PersistenceException e) {
  1868. // good
  1869. }
  1870. q = em.createQuery("select from " + Flight.class.getName() + " c" + " where id > :ids");
  1871. q.setParameter("ids", Utils.newArrayList());
  1872. q.setHint(DatastoreManager.QUERYEXT_INMEMORY_WHEN_UNSUPPORTED, "false");
  1873. try {
  1874. q.getResultList();
  1875. fail("expected exception");
  1876. } catch (PersistenceException e) {
  1877. // good
  1878. }
  1879. q = em.createQuery("select from " + Flight.class.getName() + " c" + " where id = :ids order by id");
  1880. q.setParameter("ids", Utils.newArrayList());
  1881. q.setHint(DatastoreManager.QUERYEXT_INMEMORY_WHEN_UNSUPPORTED, "false");
  1882. try {
  1883. q.getResultList();
  1884. fail("expected exception");
  1885. } catch (PersistenceException e) {
  1886. // good
  1887. }
  1888. }
  1889. public void testNamedQuery() {
  1890. Query q = em.createNamedQuery("namedQuery");
  1891. assertTrue(q.getResultList().isEmpty());
  1892. Entity e = Book.newBookEntity("author", "12345", "yam");
  1893. ds.put(e);
  1894. Book b = (Book) q.getSingleResult();
  1895. assertEquals(e.getKey(), KeyFactory.stringToKey(b.getId()));
  1896. }
  1897. public void testRestrictFetchedFields_UnknownField() {
  1898. Query q = em.createQuery("select dne from " + Book.class.getName());
  1899. q.setHint(DatastoreManager.QUERYEXT_INMEMORY_WHEN_UNSUPPORTED, "false");
  1900. try {
  1901. q.getResultList();
  1902. fail("expected exception");
  1903. } catch (PersistenceException e) {
  1904. // good
  1905. }
  1906. }
  1907. public void testRestrictFetchedFields_OneField() {
  1908. Entity e1 = Book.newBookEntity("author", "12345", "the title");
  1909. ds.put(e1);
  1910. Query q = em.createQuery("select title from " + Book.class.getName() + " c");
  1911. @SuppressWarnings("unchecked")
  1912. List<String> titles = (List<String>) q.getResultList();
  1913. assertEquals(1, titles.size());
  1914. assertEquals("the title", titles.get(0));
  1915. Entity e2 = Book.newBookEntity("another author", "123456", "the other title");
  1916. ds.put(e2);
  1917. @SuppressWarnings("unchecked")
  1918. List<String> titles2 = (List<String>) q.getResultList();
  1919. assertEquals(2, titles2.size());
  1920. assertEquals("the title", titles2.get(0));
  1921. assertEquals("the other title", titles2.get(1));
  1922. }
  1923. public void testRestrictFetchedFields_OneIdField() {
  1924. Entity e1 = Book.newBookEntity("author", "12345", "the title");
  1925. ds.put(e1);
  1926. Entity e2 = Book.newBookEntity("another author", "123456", "the other title");
  1927. ds.put(e2);
  1928. // Remove this blocker since the test needs to update!
  1929. DatastoreServiceInterceptor.uninstall();
  1930. beginTxn();
  1931. Query q = em.createQuery("select id from " + Book.class.getName() + " c");
  1932. @SuppressWarnings("unchecked")
  1933. List<String> ids = (List<String>) q.getResultList();
  1934. assertEquals(2, ids.size());
  1935. assertEquals(KeyFactory.keyToString(e1.getKey()), ids.get(0));
  1936. assertEquals(KeyFactory.keyToString(e2.getKey()), ids.get(1));
  1937. Book b = em.find(Book.class, e1.getKey());
  1938. assertEquals("author", b.getAuthor());
  1939. b.setAuthor("not author");
  1940. commitTxn();
  1941. beginTxn();
  1942. b = em.find(Book.class, e1.getKey());
  1943. assertEquals("not author", b.getAuthor());
  1944. commitTxn();
  1945. }
  1946. public void testRestrictFetchedFields_TwoFields() {
  1947. Entity e1 = Book.newBookEntity("author", "12345", "the title");
  1948. ds.put(e1);
  1949. Query q = em.createQuery("select author, isbn from " + Book.class.getName() + " c");
  1950. @SuppressWarnings("unchecked")
  1951. List<Object[]> results = (List<Object[]>) q.getResultList();
  1952. assertEquals(1, results.size());
  1953. assertEquals(2, results.get(0).length);
  1954. assertEquals("author", results.get(0)[0]);
  1955. assertEquals("12345", results.get(0)[1]);
  1956. Entity e2 = Book.newBookEntity("another author", null, "the other title");
  1957. ds.put(e2);
  1958. @SuppressWarnings("unchecked")
  1959. List<Object[]> results2 = (List<Object[]>) q.getResultList();
  1960. assertEquals(2, results2.size());
  1961. assertEquals(2, results2.get(0).length);
  1962. assertEquals("author", results2.get(0)[0]);
  1963. assertEquals("12345", results2.get(0)[1]);
  1964. assertEquals(2, results2.get(0).length);
  1965. assertEquals("another author", results2.get(1)[0]);
  1966. assertNull(results2.get(1)[1]);
  1967. }
  1968. public void testRestrictFetchedFields_TwoIdFields() {
  1969. Entity e1 = Book.newBookEntity("author", "12345", "the title");
  1970. ds.put(e1);
  1971. Query q = em.createQuery("select id, id from " + Book.class.getName() + " c");
  1972. @SuppressWarnings("unchecked")
  1973. List<Object[]> results = (List<Object[]>) q.getResultList();
  1974. assertEquals(1, results.size());
  1975. assertEquals(2, results.get(0).length);
  1976. assertEquals(KeyFactory.keyToString(e1.getKey()), results.get(0)[0]);
  1977. assertEquals(KeyFactory.keyToString(e1.getKey()), results.get(0)[1]);
  1978. Entity e2 = Book.newBookEntity("another author", null, "the other title");
  1979. ds.put(e2);
  1980. @SuppressWarnings("unchecked")
  1981. List<Object[]> results2 = (List<Object[]>) q.getResultList();
  1982. assertEquals(2, results2.size());
  1983. assertEquals(2, results2.get(0).length);
  1984. assertEquals(KeyFactory.keyToString(e1.getKey()), results2.get(0)[0]);
  1985. assertEquals(KeyFactory.keyToString(e1.getKey()), results2.get(0)[1]);
  1986. assertEquals(2, results2.get(0).length);
  1987. assertEquals(KeyFactory.keyToString(e2.getKey()), results2.get(1)[0]);
  1988. assertEquals(KeyFactory.keyToString(e2.getKey()), results2.get(1)[1]);
  1989. }
  1990. public void testRestrictFetchedFields_TwoIdFields_IdIsFirst() {
  1991. Entity e1 = Book.newBookEntity("author", "12345", "the title");
  1992. ds.put(e1);
  1993. Query q = em.createQuery("select id, author from " + Book.class.getName() + " c");
  1994. @SuppressWarnings("unchecked")
  1995. List<Object[]> results = (List<Object[]>) q.getResultList();
  1996. assertEquals(1, results.size());
  1997. assertEquals(2, results.get(0).length);
  1998. assertEquals(KeyFactory.keyToString(e1.getKey()), results.get(0)[0]);
  1999. assertEquals("author", results.get(0)[1]);
  2000. Entity e2 = Book.newBookEntity("another author", null, "the other title");
  2001. ds.put(e2);
  2002. @SuppressWarnings("unchecked")
  2003. List<Object[]> results2 = (List<Object[]>) q.getResultList();
  2004. assertEquals(2, results2.size());
  2005. assertEquals(2, results2.get(0).length);
  2006. assertEquals(KeyFactory.keyToString(e1.getKey()), results2.get(0)[0]);
  2007. assertEquals("author", results2.get(0)[1]);
  2008. assertEquals(2, results2.get(0).length);
  2009. assertEquals(KeyFactory.keyToString(e2.getKey()), results2.get(1)[0]);
  2010. assertEquals("another author", results2.get(1)[1]);
  2011. }
  2012. public void testRestrictFetchedFields_TwoIdFields_IdIsSecond() {
  2013. Entity e1 = Book.newBookEntity("author", "12345", "the title");
  2014. ds.put(e1);
  2015. Query q = em.createQuery("select author, id from " + Book.class.getName() + " c");
  2016. @SuppressWarnings("unchecked")
  2017. List<Object[]> results = (List<Object[]>) q.getResultList();
  2018. assertEquals(1, results.size());
  2019. assertEquals(2, results.get(0).length);
  2020. assertEquals("author", results.get(0)[0]);
  2021. assertEquals(KeyFactory.keyToString(e1.getKey()), results.get(0)[1]);
  2022. Entity e2 = Book.newBookEntity("another author", null, "the other title");
  2023. ds.put(e2);
  2024. @SuppressWarnings("unchecked")
  2025. List<Object[]> results2 = (List<Object[]>) q.getResultList();
  2026. assertEquals(2, results2.size());
  2027. assertEquals(2, results2.get(0).length);
  2028. assertEquals("author", results2.get(0)[0]);
  2029. assertEquals(KeyFactory.keyToString(e1.getKey()), results2.get(0)[1]);
  2030. assertEquals(2, results2.get(0).length);
  2031. assertEquals("another author", results2.get(1)[0]);
  2032. assertEquals(KeyFactory.keyToString(e2.getKey()), results2.get(1)[1]);
  2033. }
  2034. public void testRestrictFetchedFields_OneToOne() {
  2035. Entity e1 = new Entity(HasOneToOneJPA.class.getSimpleName());
  2036. ds.put(e1);
  2037. Entity e2 = Book.newBookEntity(e1.getKey(), "author", "12345", "the title");
  2038. ds.put(e2);
  2039. Query q = em.createQuery("select id, book from " + HasOneToOneJPA.class.getName() + " c");
  2040. @SuppressWarnings("unchecked")
  2041. List<Object[]> results = (List<Object[]>) q.getResultList();
  2042. assertEquals(1, results.size());
  2043. assertEquals(2, results.get(0).length);
  2044. assertEquals(KeyFactory.keyToString(e1.getKey()), results.get(0)[0]);
  2045. Book b = em.find(Book.class, e2.getKey());
  2046. assertEquals(b, results.get(0)[1]);
  2047. }
  2048. public void testRestrictFetchedFields_OneToMany() {
  2049. Entity e1 = new Entity(HasOneToManyListJPA.class.getSimpleName());
  2050. ds.put(e1);
  2051. Entity e2 = Book.newBookEntity(e1.getKey(), "author", "12345", "the title");
  2052. ds.put(e2);
  2053. e1.setProperty("books", Utils.newArrayList(e2.getKey()));
  2054. ds.put(e1);
  2055. Query q = em.createQuery("select id, books from " + HasOneToManyListJPA.class.getName() + " c");
  2056. @SuppressWarnings("unchecked")
  2057. List<Object[]> results = (List<Object[]>) q.getResultList();
  2058. assertEquals(1, results.size());
  2059. assertEquals(2, results.get(0).length);
  2060. assertEquals(KeyFactory.keyToString(e1.getKey()), results.get(0)[0]);
  2061. Book b = em.find(Book.class, e2.getKey());
  2062. List<Book> books = (List<Book>) results.get(0)[1];
  2063. assertEquals(1, books.size());
  2064. assertEquals(b, books.get(0));
  2065. }
  2066. public void testRestrictFetchedFields_AliasedField() {
  2067. Entity e1 = Book.newBookEntity("author", "12345", "the title");
  2068. ds.put(e1);
  2069. Query q = em.createQuery("select b.isbn from " + Book.class.getName() + " b");
  2070. @SuppressWarnings("unchecked")
  2071. List<String> isbns = (List<String>) q.getResultList();
  2072. assertEquals(1, isbns.size());
  2073. assertEquals("12345", isbns.get(0));
  2074. }
  2075. public void testRestrictFetchedFields_EmbeddedField() {
  2076. Entity entity = new Entity(Person.class.getSimpleName());
  2077. entity.setProperty("first", "max");
  2078. entity.setProperty("last", "ross");
  2079. entity.setProperty("anotherFirst", "notmax");
  2080. entity.setProperty("anotherLast", "notross");
  2081. ds.put(entity);
  2082. Query q = em.createQuery("select name.first, anotherName.last from " + Person.class.getName() + " c");
  2083. @SuppressWarnings("unchecked")
  2084. List<Object[]> result = (List<Object[]>) q.getResultList();
  2085. assertEquals(1, result.size());
  2086. }
  2087. public void testIsNull() {
  2088. Entity e = Book.newBookEntity("author", null, "title");
  2089. ds.put(e);
  2090. Query q = em.createQuery("select from " + Book.class.getName() + " c" + " where isbn is NULL");
  2091. @SuppressWarnings("unchecked")
  2092. List<Book> books = q.getResultList();
  2093. assertEquals(1, books.size());
  2094. }
  2095. public void testIsNotNull() {
  2096. Entity e = Book.newBookEntity("auth", "isbn", null);
  2097. ds.put(e);
  2098. Query q = em.createQuery("select from " + Book.class.getName() + " c" + " where title is not null");
  2099. assertTrue(q.getResultList().isEmpty());
  2100. Query q2 = em.createQuery("select from " + Book.class.getName() + " c" + " where title <> null");
  2101. assertTrue(q2.getResultList().isEmpty());
  2102. e = Book.newBookEntity("auth2", "isbn2", "not null");
  2103. ds.put(e);
  2104. Book b = (Book) q.getSingleResult();
  2105. assertEquals("not null", b.getTitle());
  2106. b = (Book) q2.getSingleResult();
  2107. assertEquals("not null", b.getTitle());
  2108. }
  2109. public void testIsNotNull_Param() {
  2110. Entity e = Book.newBookEntity("auth", "isbn", null);
  2111. ds.put(e);
  2112. Query q = em.createQuery("select from " + Book.class.getName() + " c" + " where title <> :p");
  2113. q.setParameter("p", null);
  2114. assertTrue(q.getResultList().isEmpty());
  2115. e = Book.newBookEntity("auth2", "isbn2", "not null");
  2116. ds.put(e);
  2117. Book b = (Book) q.getSingleResult();
  2118. assertEquals("not null", b.getTitle());
  2119. }
  2120. public void testNotEqual() {
  2121. Entity e = Book.newBookEntity("auth", "isbn", "yar");
  2122. ds.put(e);
  2123. Query q = em.createQuery("select from " + Book.class.getName() + " c" + " where title <> 'yar'");
  2124. assertTrue(q.getResultList().isEmpty());
  2125. e = Book.newBookEntity("auth2", "isbn2", "not yar");
  2126. ds.put(e);
  2127. Book b = (Book) q.getSingleResult();
  2128. assertEquals("not yar", b.getTitle());
  2129. }
  2130. public void testNotEqual_Param() {
  2131. Entity e = Book.newBookEntity("auth", "isbn", "yar");
  2132. ds.put(e);
  2133. Query q = em.createQuery("select from " + Book.class.getName() + " c" + " where title <> :p");
  2134. q.setParameter("p", "yar");
  2135. assertTrue(q.getResultList().isEmpty());
  2136. e = Book.newBookEntity("auth2", "isbn2", "not yar");
  2137. ds.put(e);
  2138. Book b = (Book) q.getSingleResult();
  2139. assertEquals("not yar", b.getTitle());
  2140. }
  2141. public void testIn_Literals() {
  2142. Entity e = Book.newBookEntity("auth1", "isbn1", "yar1");
  2143. Entity e2 = Book.newBookEntity("auth2", "isbn2", null);
  2144. Entity e3 = Book.newBookEntity("auth3", "isbn3", "yar3");
  2145. ds.put(Arrays.asList(e, e2, e3));
  2146. Query q = em.createQuery("select from " + Book.class.getName() + " c" + " where author IN ('auth1', 'auth3')");
  2147. List<Book> books = q.getResultList();
  2148. assertEquals(2, books.size());
  2149. assertEquals(KeyFactory.keyToString(e.getKey()), books.get(0).getId());
  2150. assertEquals(KeyFactory.keyToString(e3.getKey()), books.get(1).getId());
  2151. q = em.createQuery("select from " + Book.class.getName() + " c" + " where title IN (null, 'yar1')");
  2152. books = q.getResultList();
  2153. assertEquals(2, books.size());
  2154. assertEquals(KeyFactory.keyToString(e2.getKey()), books.get(0).getId());
  2155. assertEquals(KeyFactory.keyToString(e.getKey()), books.get(1).getId());
  2156. }
  2157. public void testIn_Params() {
  2158. Entity e = Book.newBookEntity("auth1", "isbn1", "yar1");
  2159. Entity e2 = Book.newBookEntity("auth2", "isbn2", "yar2");
  2160. Entity e3 = Book.newBookEntity("auth3", "isbn3", "yar3");
  2161. ds.put(Arrays.asList(e, e2, e3));
  2162. Query q = em.createQuery("select from " + Book.class.getName() + " c" + " where author IN (:p1, :p2)");
  2163. q.setParameter("p1", "auth1");
  2164. q.setParameter("p2", "auth3");
  2165. List<Book> books = q.getResultList();
  2166. assertEquals(2, books.size());
  2167. assertEquals(KeyFactory.keyToString(e.getKey()), books.get(0).getId());
  2168. assertEquals(KeyFactory.keyToString(e3.getKey()), books.get(1).getId());
  2169. q = em.createQuery("select from " + Book.class.getName() + " c" +
  2170. " where author IN (:p1) OR author IN (:p2)");
  2171. q.setParameter("p1", "auth1");
  2172. q.setParameter("p2", "auth3");
  2173. books = q.getResultList();
  2174. assertEquals(2, books.size());
  2175. assertEquals(KeyFactory.keyToString(e.getKey()), books.get(0).getId());
  2176. assertEquals(KeyFactory.keyToString(e3.getKey()), books.get(1).getId());
  2177. }
  2178. public void testIn_CollectionParam() {
  2179. Entity e = Book.newBookEntity("auth1", "isbn1", "yar1");
  2180. Entity e2 = Book.newBookEntity("auth2", "isbn2", "yar2");
  2181. Entity e3 = Book.newBookEntity("auth3", "isbn3", "yar3");
  2182. ds.put(Arrays.asList(e, e2, e3));
  2183. Query q = em.createQuery("select from " + Book.class.getName() + " c" + " where author IN (:p1)");
  2184. q.setParameter("p1", Arrays.asList("auth1", "auth3"));
  2185. List<Book> books = q.getResultList();
  2186. assertEquals(2, books.size());
  2187. assertEquals(KeyFactory.keyToString(e.getKey()), books.get(0).getId());
  2188. assertEquals(KeyFactory.keyToString(e3.getKey()), books.get(1).getId());
  2189. q = em.createQuery("select from " + Book.class.getName() + " c" +
  2190. " where author IN (:p1) OR author IN (:p2)");
  2191. q.setParameter("p1", Arrays.asList("auth1"));
  2192. q.setParameter("p2", Arrays.asList("auth3"));
  2193. books = q.getResultList();
  2194. assertEquals(2, books.size());
  2195. assertEquals(KeyFactory.keyToString(e.getKey()), books.get(0).getId());
  2196. assertEquals(KeyFactory.keyToString(e3.getKey()), books.get(1).getId());
  2197. }
  2198. public void testMultipleIn_Literals() {
  2199. Entity e = Book.newBookEntity("auth1", "isbn1", "yar1");
  2200. Entity e2 = Book.newBookEntity("auth2", "isbn2", "yar2");
  2201. Entity e3 = Book.newBookEntity("auth3", "isbn3", "yar3");
  2202. ds.put(Arrays.asList(e, e2, e3));
  2203. Query q = em.createQuery("select from " + Book.class.getName() + " c" + " where "
  2204. + "author IN ('auth1', 'auth3') AND isbn IN ('isbn3', 'isbn2')");
  2205. List<Book> books = q.getResultList();
  2206. assertEquals(1, books.size());
  2207. assertEquals(KeyFactory.keyToString(e3.getKey()), books.get(0).getId());
  2208. q = em.createQuery("select from " + Book.class.getName() + " c" + " where "
  2209. + "author IN ('auth1') OR author IN ('auth4', 'auth2')");
  2210. books = q.getResultList();
  2211. assertEquals(2, books.size());
  2212. assertEquals(KeyFactory.keyToString(e.getKey()), books.get(0).getId());
  2213. assertEquals(KeyFactory.keyToString(e2.getKey()), books.get(1).getId());
  2214. }
  2215. public void testMultipleIn_Params() {
  2216. Entity e = Book.newBookEntity("auth1", "isbn1", "yar1");
  2217. Entity e2 = Book.newBookEntity("auth2", "isbn2", "yar2");
  2218. Entity e3 = Book.newBookEntity("auth3", "isbn3", "yar3");
  2219. ds.put(Arrays.asList(e, e2, e3));
  2220. Query q = em.createQuery("select from " + Book.class.getName() + " c" + " where "
  2221. + "author IN (:p1, :p2) AND isbn IN (:p3, :p4)");
  2222. q.setParameter("p1", "auth1");
  2223. q.setParameter("p2", "auth3");
  2224. q.setParameter("p3", "isbn3");
  2225. q.setParameter("p4", "isbn2");
  2226. List<Book> books = q.getResultList();
  2227. assertEquals(1, books.size());
  2228. assertEquals(KeyFactory.keyToString(e3.getKey()), books.get(0).getId());
  2229. q = em.createQuery("select from " + Book.class.getName() + " c" + " where "
  2230. + "author IN (:p1, :p2) OR author IN (:p3, :p4)");
  2231. q.setParameter("p1", "auth1");
  2232. q.setParameter("p2", "auth3");
  2233. q.setParameter("p3", "auth4");
  2234. q.setParameter("p4", "auth5");
  2235. books = q.getResultList();
  2236. assertEquals(2, books.size());
  2237. assertEquals(KeyFactory.keyToString(e.getKey()), books.get(0).getId());
  2238. assertEquals(KeyFactory.keyToString(e3.getKey()), books.get(1).getId());
  2239. }
  2240. public void testMultipleIn_Params_KeyFilter() {
  2241. Entity e = Book.newBookEntity("auth1", "isbn1", "yar1");
  2242. Entity e2 = Book.newBookEntity("auth2", "isbn2", "yar2");
  2243. Entity e3 = Book.newBookEntity("auth3", "isbn3", "yar3");
  2244. ds.put(Arrays.asList(e, e2, e3));
  2245. Query q = em.createQuery("select from " + Book.class.getName() + " c" + " where "
  2246. + "id IN (:p1) AND isbn IN (:p2, :p3)");
  2247. q.setParameter("p1", e2.getKey());
  2248. q.setParameter("p2", "isbn2");
  2249. q.setParameter("p3", "isbn3");
  2250. @SuppressWarnings("unchecked")
  2251. List<Book> books = (List<Book>) q.getResultList();
  2252. assertEquals(1, books.size());
  2253. assertEquals(KeyFactory.keyToString(e2.getKey()), books.get(0).getId());
  2254. q = em.createQuery("select from " + Book.class.getName() + " c" + " where "
  2255. + "(id = :p1 or id = :p2) AND isbn IN (:p3, :p4)");
  2256. q.setParameter("p1", e2.getKey());
  2257. q.setParameter("p2", e3.getKey());
  2258. q.setParameter("p3", "isbn2");
  2259. q.setParameter("p4", "isbn3");
  2260. @SuppressWarnings("unchecked")
  2261. List<Book> books2 = (List<Book>) q.getResultList();
  2262. assertEquals(2, books2.size());
  2263. }
  2264. public void testOr_Literals() {
  2265. Entity e = Book.newBookEntity("auth1", "isbn1", "yar1");
  2266. Entity e2 = Book.newBookEntity("auth2", "isbn2", null);
  2267. Entity e3 = Book.newBookEntity("auth3", "isbn3", "yar3");
  2268. ds.put(Arrays.asList(e, e2, e3));
  2269. Query q = em.createQuery("select from " + Book.class.getName() + " c" +
  2270. " where author = 'auth1' or author = 'auth3'");
  2271. List<Book> books = q.getResultList();
  2272. assertEquals(2, books.size());
  2273. assertEquals(KeyFactory.keyToString(e.getKey()), books.get(0).getId());
  2274. assertEquals(KeyFactory.keyToString(e3.getKey()), books.get(1).getId());
  2275. q = em.createQuery("select from " + Book.class.getName() + " c" +
  2276. " where title is null or title = 'yar1'");
  2277. books = q.getResultList();
  2278. assertEquals(2, books.size());
  2279. assertEquals(KeyFactory.keyToString(e2.getKey()), books.get(0).getId());
  2280. assertEquals(KeyFactory.keyToString(e.getKey()), books.get(1).getId());
  2281. }
  2282. public void testOr_Params() {
  2283. Entity e = Book.newBookEntity("auth1", "isbn1", "yar1");
  2284. Entity e2 = Book.newBookEntity("auth2", "isbn2", "yar2");
  2285. Entity e3 = Book.newBookEntity("auth3", "isbn3", "yar3");
  2286. ds.put(Arrays.asList(e, e2, e3));
  2287. Query q = em.createQuery("select from " + Book.class.getName() + " c" +
  2288. " where author = :p1 or author = :p2");
  2289. q.setParameter("p1", "auth1");
  2290. q.setParameter("p2", "auth3");
  2291. List<Book> books = q.getResultList();
  2292. assertEquals(2, books.size());
  2293. assertEquals(KeyFactory.keyToString(e.getKey()), books.get(0).getId());
  2294. assertEquals(KeyFactory.keyToString(e3.getKey()), books.get(1).getId());
  2295. }
  2296. public void testMultipleOr_Literals() {
  2297. Entity e = Book.newBookEntity("auth1", "isbn1", "yar1");
  2298. Entity e2 = Book.newBookEntity("auth2", "isbn2", "yar2");
  2299. Entity e3 = Book.newBookEntity("auth3", "isbn3", "yar3");
  2300. ds.put(Arrays.asList(e, e2, e3));
  2301. Query q = em.createQuery("select from " + Book.class.getName() + " c" + " where "
  2302. + "(author = 'auth1' or author = 'auth3') AND "
  2303. + "(isbn = 'isbn3' or isbn = 'isbn2')");
  2304. List<Book> books = q.getResultList();
  2305. assertEquals(1, books.size());
  2306. assertEquals(KeyFactory.keyToString(e3.getKey()), books.get(0).getId());
  2307. }
  2308. public void testMultipleOr_Params() {
  2309. Entity e = Book.newBookEntity("auth1", "isbn1", "yar1");
  2310. Entity e2 = Book.newBookEntity("auth2", "isbn2", "yar2");
  2311. Entity e3 = Book.newBookEntity("auth3", "isbn3", "yar3");
  2312. ds.put(Arrays.asList(e, e2, e3));
  2313. Query q = em.createQuery("select from " + Book.class.getName() + " c" + " where "
  2314. + "(author = :p1 or author = :p2) AND "
  2315. + "(isbn = :p3 or isbn = :p4)");
  2316. q.setParameter("p1", "auth1");
  2317. q.setParameter("p2", "auth3");
  2318. q.setParameter("p3", "isbn3");
  2319. q.setParameter("p4", "isbn2");
  2320. List<Book> books = q.getResultList();
  2321. assertEquals(1, books.size());
  2322. assertEquals(KeyFactory.keyToString(e3.getKey()), books.get(0).getId());
  2323. }
  2324. public void testIsNullChild() {
  2325. Entity e = new Entity(HasOneToOneJPA.class.getSimpleName());
  2326. ds.put(e);
  2327. Query q = em.createQuery(
  2328. "select from " + HasOneToOneJPA.class.getName() + " c" + " where book is null");
  2329. q.setHint(DatastoreManager.QUERYEXT_INMEMORY_WHEN_UNSUPPORTED, "false");
  2330. try {
  2331. q.getResultList();
  2332. fail("expected");
  2333. } catch (PersistenceException pe) {
  2334. // good
  2335. }
  2336. }
  2337. public void testIsNullParent() {
  2338. Entity e = new Entity(HasOneToOneJPA.class.getSimpleName());
  2339. Key key = ds.put(e);
  2340. e = new Entity(HasOneToOneParentJPA.class.getSimpleName(), key);
  2341. ds.put(e);
  2342. Query q = em.createQuery(
  2343. "select from " + HasOneToOneParentJPA.class.getName() + " c" + " where parent is null");
  2344. q.setHint(DatastoreManager.QUERYEXT_INMEMORY_WHEN_UNSUPPORTED, "false");
  2345. try {
  2346. q.getResultList();
  2347. fail("expected");
  2348. } catch (PersistenceException pe) {
  2349. // good
  2350. }
  2351. }
  2352. public void testQueryWithEntityShortName() {
  2353. // Uninstall this since the test needs to update!
  2354. DatastoreServiceInterceptor.uninstall();
  2355. Query q = em.createQuery("select b from bookalias b where title = 'yam'");
  2356. assertTrue(q.getResultList().isEmpty());
  2357. Book b = new Book();
  2358. b.setTitle("yam");
  2359. beginTxn();
  2360. em.persist(b);
  2361. commitTxn();
  2362. assertEquals(b, q.getResultList().get(0));
  2363. q = em.createQuery("select from bookalias b where title = 'yam'");
  2364. assertEquals(b, q.getResultList().get(0));
  2365. q = em.createQuery("select from bookalias b where b.title = 'yam'");
  2366. assertEquals(b, q.getResultList().get(0));
  2367. }
  2368. public void testQueryWithSingleCharacterLiteral() {
  2369. Query q = em.createQuery("select from " + Book.class.getName() + " c" + " where title = 'y'");
  2370. assertTrue(q.getResultList().isEmpty());
  2371. Entity e = Book.newBookEntity("author", "12345", "y");
  2372. ds.put(e);
  2373. Book b = (Book) q.getSingleResult();
  2374. assertEquals(e.getKey(), KeyFactory.stringToKey(b.getId()));
  2375. }
  2376. public void testSetFirstResultAfterSetParameter() {
  2377. Entity e = Book.newBookEntity("author", "12345", "y");
  2378. ds.put(e);
  2379. e = Book.newBookEntity("author", "12345", "y");
  2380. ds.put(e);
  2381. Query query = em.createQuery("SELECT b FROM " + Book.class.getName() + " b WHERE b.title = :title");
  2382. query.setParameter("title", "y");
  2383. query.setFirstResult(1);
  2384. Book b = (Book) query.getSingleResult();
  2385. assertEquals(e.getKey(), KeyFactory.stringToKey(b.getId()));
  2386. }
  2387. public void testSetMaxResultsAfterSetParameter() {
  2388. Entity e = Book.newBookEntity("author", "12345", "y");
  2389. ds.put(e);
  2390. Entity e2 = Book.newBookEntity("author", "12345", "y");
  2391. ds.put(e2);
  2392. Query query = em.createQuery("SELECT b FROM " + Book.class.getName() + " b WHERE b.title = :title");
  2393. query.setParameter("title", "y");
  2394. query.setMaxResults(1);
  2395. Book b = (Book) query.getSingleResult();
  2396. assertEquals(e.getKey(), KeyFactory.stringToKey(b.getId()));
  2397. }
  2398. public void testSetFirstResultAfterSetPCParameter() {
  2399. Entity e = new Entity(HasOneToOneJPA.class.getSimpleName());
  2400. Key key = ds.put(e);
  2401. e = new Entity(HasOneToOneParentJPA.class.getSimpleName(), key);
  2402. ds.put(e);
  2403. e = new Entity(HasOneToOneParentJPA.class.getSimpleName(), key);
  2404. ds.put(e);
  2405. HasOneToOneJPA parent = em.find(HasOneToOneJPA.class, key);
  2406. Query q = em.createQuery(
  2407. "select from " + HasOneToOneParentJPA.class.getName() + " c" + " where parent = :p");
  2408. q.setParameter("p", parent);
  2409. q.setFirstResult(1);
  2410. HasOneToOneParentJPA child = (HasOneToOneParentJPA) q.getSingleResult();
  2411. assertEquals(e.getKey(), KeyFactory.stringToKey(child.getId()));
  2412. }
  2413. public void testSetMaxResultsAfterSetPCParameter() {
  2414. Entity e = new Entity(HasOneToOneJPA.class.getSimpleName());
  2415. Key key = ds.put(e);
  2416. Entity child1 = new Entity(HasOneToOneParentJPA.class.getSimpleName(), key);
  2417. ds.put(child1);
  2418. Entity child2 = new Entity(HasOneToOneParentJPA.class.getSimpleName(), key);
  2419. ds.put(child2);
  2420. HasOneToOneJPA parent = em.find(HasOneToOneJPA.class, key);
  2421. Query q = em.createQuery(
  2422. "select from " + HasOneToOneParentJPA.class.getName() + " c" + " where parent = :p");
  2423. q.setParameter("p", parent);
  2424. q.setMaxResults(1);
  2425. HasOneToOneParentJPA child = (HasOneToOneParentJPA) q.getSingleResult();
  2426. assertEquals(child1.getKey(), KeyFactory.stringToKey(child.getId()));
  2427. }
  2428. public void testAccessResultsAfterClose() {
  2429. for (int i = 0; i < 3; i++) {
  2430. Entity e = Book.newBookEntity("this", "that", "the other");
  2431. ds.put(e);
  2432. }
  2433. beginTxn();
  2434. Query q = em.createQuery("select from " + Book.class.getName() + " c");
  2435. List<Book> results = q.getResultList();
  2436. Iterator<Book> iter = results.iterator();
  2437. iter.next();
  2438. commitTxn();
  2439. em.close();
  2440. Book b = iter.next();
  2441. b.getIsbn();
  2442. b.getAuthor();
  2443. iter.next();
  2444. }
  2445. public void testAncestorQueryForDifferentEntityGroupWithCurrentTxn() {
  2446. switchDatasource(EntityManagerFactoryName.transactional_ds_non_transactional_ops_allowed);
  2447. Entity e1 = Book.newBookEntity("this", "that", "the other");
  2448. ds.put(e1);
  2449. beginTxn();
  2450. // Not used, but associates the txn with the book's entity group
  2451. /*Book b = */em.find(Book.class, e1.getKey());
  2452. Query q = em.createQuery(
  2453. "select from " + HasKeyAncestorStringPkJPA.class.getName() + " c" + " where ancestorKey = :p");
  2454. q.setParameter("p", KeyFactory.keyToString(KeyFactory.createKey("yar", 33L)));
  2455. try {
  2456. q.getResultList().iterator();
  2457. fail("expected iae");
  2458. } catch (PersistenceException e) {
  2459. // good
  2460. }
  2461. q.setHint("gae.exclude-query-from-txn", false);
  2462. try {
  2463. q.getResultList().iterator();
  2464. fail("expected exception");
  2465. } catch (PersistenceException e) {
  2466. // good
  2467. }
  2468. q.setHint("gae.exclude-query-from-txn", true);
  2469. q.getResultList();
  2470. }
  2471. public void testLikeQuery_Literal() {
  2472. Entity e1 = Book.newBookEntity("this", "that", "xxxx");
  2473. ds.put(e1);
  2474. Entity e2 = Book.newBookEntity("this", "that", "y");
  2475. ds.put(e2);
  2476. Entity e3 = Book.newBookEntity("this", "that", "yb");
  2477. ds.put(e3);
  2478. Entity e4 = Book.newBookEntity("this", "that", "z");
  2479. ds.put(e4);
  2480. Query q = em.createQuery("select from " + Book.class.getName() + " c" + " where title LIKE 'y%'");
  2481. @SuppressWarnings("unchecked")
  2482. List<Book> result = q.getResultList();
  2483. assertEquals(2, result.size());
  2484. assertEquals(KeyFactory.keyToString(e2.getKey()), result.get(0).getId());
  2485. assertEquals(KeyFactory.keyToString(e3.getKey()), result.get(1).getId());
  2486. q = em.createQuery("select from " + Book.class.getName() + " c" + " where title LIKE 'z%'");
  2487. @SuppressWarnings("unchecked")
  2488. List<Book> result2 = q.getResultList();
  2489. assertEquals(1, result2.size());
  2490. assertEquals(KeyFactory.keyToString(e4.getKey()), result2.get(0).getId());
  2491. q = em.createQuery("select from " + Book.class.getName() + " c" + " where title LIKE 'za%'");
  2492. @SuppressWarnings("unchecked")
  2493. List<Book> result3 = q.getResultList();
  2494. assertTrue(result3.isEmpty());
  2495. }
  2496. public void testLikeQuery_Literal2() {
  2497. for (int i = 0; i < 10; i++) {
  2498. Entity e1 = Book.newBookEntity("this", "that", "xxxx");
  2499. ds.put(e1);
  2500. }
  2501. Query q = em.createQuery("select from " + Book.class.getName() + " c" + " where title LIKE 'x%'");
  2502. @SuppressWarnings("unchecked")
  2503. List<Book> result = q.getResultList();
  2504. assertEquals(10, result.size());
  2505. }
  2506. public void testLikeQuery_Param() {
  2507. Entity e1 = Book.newBookEntity("this", "that", "xxxx");
  2508. ds.put(e1);
  2509. Entity e2 = Book.newBookEntity("this", "that", "y");
  2510. ds.put(e2);
  2511. Entity e3 = Book.newBookEntity("this", "that", "yb");
  2512. ds.put(e3);
  2513. Entity e4 = Book.newBookEntity("this", "that", "z");
  2514. ds.put(e4);
  2515. Query q = em.createQuery("select from " + Book.class.getName() + " c" + " where title LIKE :p");
  2516. q.setParameter("p", "y%");
  2517. @SuppressWarnings("unchecked")
  2518. List<Book> result = q.getResultList();
  2519. assertEquals(2, result.size());
  2520. assertEquals(KeyFactory.keyToString(e2.getKey()), result.get(0).getId());
  2521. assertEquals(KeyFactory.keyToString(e3.getKey()), result.get(1).getId());
  2522. q = em.createQuery("select from " + Book.class.getName() + " c" + " where title LIKE 'z%'");
  2523. q.setParameter("p", "y%");
  2524. @SuppressWarnings("unchecked")
  2525. List<Book> result2 = q.getResultList();
  2526. assertEquals(1, result2.size());
  2527. assertEquals(KeyFactory.keyToString(e4.getKey()), result2.get(0).getId());
  2528. q = em.createQuery("select from " + Book.class.getName() + " c" + " where title LIKE 'za%'");
  2529. q.setParameter("p", "y%");
  2530. @SuppressWarnings("unchecked")
  2531. List<Book> result3 = q.getResultList();
  2532. assertTrue(result3.isEmpty());
  2533. }
  2534. public void testLikeQuery_InvalidLiteral() {
  2535. Query q = em.createQuery("select from " + Book.class.getName() + " c" + " where title LIKE '%y'");
  2536. q.setHint(DatastoreManager.QUERYEXT_INMEMORY_WHEN_UNSUPPORTED, "false");
  2537. try {
  2538. q.getResultList();
  2539. fail("expected exception");
  2540. } catch (PersistenceException pe) {
  2541. if (pe.getCause() instanceof DatastoreQuery.UnsupportedDatastoreFeatureException) {
  2542. // good
  2543. }
  2544. else {
  2545. throw pe;
  2546. }
  2547. }
  2548. q = em.createQuery("select from " + Book.class.getName() + " c" + " where title LIKE 'y%y'");
  2549. q.setHint(DatastoreManager.QUERYEXT_INMEMORY_WHEN_UNSUPPORTED, "false");
  2550. try {
  2551. q.getResultList();
  2552. fail("expected exception");
  2553. } catch (PersistenceException pe) {
  2554. if (pe.getCause() instanceof DatastoreQuery.UnsupportedDatastoreFeatureException) {
  2555. // good
  2556. }
  2557. else {
  2558. throw pe;
  2559. }
  2560. }
  2561. q = em.createQuery("select from " + Book.class.getName() + " c" + " where title LIKE 'y'");
  2562. q.setHint(DatastoreManager.QUERYEXT_INMEMORY_WHEN_UNSUPPORTED, "false");
  2563. try {
  2564. q.getResultList();
  2565. fail("expected exception");
  2566. } catch (PersistenceException pe) {
  2567. if (pe.getCause() instanceof DatastoreQuery.UnsupportedDatastoreFeatureException) {
  2568. // good
  2569. }
  2570. else {
  2571. throw pe;
  2572. }
  2573. }
  2574. q = em.createQuery("select from " + Book.class.getName() + " c" + " where title LIKE 'y%' and author LIKE 'z%'");
  2575. q.setHint(DatastoreManager.QUERYEXT_INMEMORY_WHEN_UNSUPPORTED, "false");
  2576. try {
  2577. q.getResultList().iterator();
  2578. fail("expected exception");
  2579. } catch (PersistenceException pe) {
  2580. // good
  2581. }
  2582. }
  2583. public void testLikeQuery_InvalidParameter() {
  2584. Query q = em.createQuery("select from " + Book.class.getName() + " c" + " where title LIKE :p");
  2585. q.setParameter("p", "%y");
  2586. q.setHint(DatastoreManager.QUERYEXT_INMEMORY_WHEN_UNSUPPORTED, "false");
  2587. try {
  2588. q.getResultList().iterator();
  2589. fail("expected exception");
  2590. } catch (PersistenceException pe) {
  2591. if (pe.getCause() instanceof DatastoreQuery.UnsupportedDatastoreFeatureException) {
  2592. // good
  2593. }
  2594. else {
  2595. throw pe;
  2596. }
  2597. }
  2598. q.setParameter("p", "y%y");
  2599. try {
  2600. q.getResultList().iterator();
  2601. fail("expected exception");
  2602. } catch (PersistenceException pe) {
  2603. if (pe.getCause() instanceof DatastoreQuery.UnsupportedDatastoreFeatureException) {
  2604. // good
  2605. }
  2606. else {
  2607. throw pe;
  2608. }
  2609. }
  2610. q.setParameter("p", "y");
  2611. try {
  2612. q.getResultList().iterator();
  2613. fail("expected exception");
  2614. } catch (PersistenceException pe) {
  2615. if (pe.getCause() instanceof DatastoreQuery.UnsupportedDatastoreFeatureException) {
  2616. // good
  2617. }
  2618. else {
  2619. throw pe;
  2620. }
  2621. }
  2622. q.setParameter("p", 23);
  2623. try {
  2624. q.getResultList().iterator();
  2625. fail("expected exception");
  2626. } catch (PersistenceException pe) {
  2627. // good
  2628. }
  2629. q = em.createQuery("select from " + Book.class.getName() + " c" + " where title LIKE :p and author LIKE :q");
  2630. q.setParameter("p", "y%");
  2631. q.setParameter("q", "y%");
  2632. try {
  2633. q.getResultList().iterator();
  2634. fail("expected exception");
  2635. } catch (PersistenceException pe) {
  2636. // good
  2637. }
  2638. }
  2639. public void testLikeQuery_Literal_CustomEscapeChar() {
  2640. Entity e1 = Book.newBookEntity("this", "that", "xxxx");
  2641. ds.put(e1);
  2642. Entity e2 = Book.newBookEntity("this", "that", "%");
  2643. ds.put(e2);
  2644. Entity e3 = Book.newBookEntity("this", "that", "%a");
  2645. ds.put(e3);
  2646. Entity e4 = Book.newBookEntity("this", "that", "z");
  2647. ds.put(e4);
  2648. Query q = em.createQuery("select from " + Book.class.getName() + " c" + " where title LIKE '%^' ESCAPE '^'");
  2649. q.setHint(DatastoreManager.QUERYEXT_INMEMORY_WHEN_UNSUPPORTED, "false");
  2650. try {
  2651. q.getResultList();
  2652. fail("Expected exception but query executed!");
  2653. } catch (PersistenceException pe) {
  2654. if (pe.getCause() instanceof DatastoreQuery.UnsupportedDatastoreFeatureException) {
  2655. // We don't support ESCAPE yet
  2656. } else {
  2657. throw pe;
  2658. }
  2659. } catch (DatastoreQuery.UnsupportedDatastoreFeatureException uefe) {
  2660. }
  2661. // assertEquals(2, result.size());
  2662. // assertEquals(KeyFactory.keyToString(e2.getKey()), result.get(0).getId());
  2663. // assertEquals(KeyFactory.keyToString(e3.getKey()), result.get(1).getId());
  2664. //
  2665. // q = em.createQuery("select from " + Book.class.getName() + " where title LIKE 'a^' ESCAPE '^'");
  2666. // @SuppressWarnings("unchecked")
  2667. // List<Book> result3 = q.getResultList();
  2668. // assertTrue(result3.isEmpty());
  2669. }
  2670. public void testUpdateQueryFails() {
  2671. Query q = em.createQuery("update " + Book.class.getName() + " set author = 'yar'");
  2672. try {
  2673. q.executeUpdate();
  2674. fail("expected exception");
  2675. } catch (PersistenceException e) {
  2676. // good
  2677. }
  2678. }
  2679. public void testNullAncestorParam() {
  2680. Query q = em.createQuery(
  2681. "select from " + HasKeyAncestorStringPkJPA.class.getName() + " c" + " where ancestorKey = :p");
  2682. q.setParameter("p", null);
  2683. q.setHint(DatastoreManager.QUERYEXT_INMEMORY_WHEN_UNSUPPORTED, "false");
  2684. try {
  2685. q.getResultList();
  2686. fail("expected exception");
  2687. } catch (PersistenceException pe) {
  2688. if (pe.getCause() instanceof DatastoreQuery.UnsupportedDatastoreFeatureException) {
  2689. // good
  2690. }
  2691. else {
  2692. throw pe;
  2693. }
  2694. }
  2695. }
  2696. public void testCurrentDateFuncs() {
  2697. Entity e = KitchenSink.newKitchenSinkEntity("blarg", null);
  2698. ds.put(e);
  2699. for (String dateFunc : Arrays.asList("CURRENT_TIMESTAMP", "CURRENT_DATE")) {
  2700. Query q = em.createQuery("select from " + KitchenSink.class.getName() + " c where dateVal < " + dateFunc);
  2701. @SuppressWarnings("unchecked")
  2702. List<KitchenSink> results = (List<KitchenSink>) q.getResultList();
  2703. assertEquals(1, results.size());
  2704. DatastoreQuery.NowProvider orig = DatastoreQuery.NOW_PROVIDER;
  2705. DatastoreQuery.NOW_PROVIDER = new DatastoreQuery.NowProvider() {
  2706. public Date now() {
  2707. return new Date(KitchenSink.DATE1.getTime() - 1);
  2708. }
  2709. };
  2710. try {
  2711. e.setProperty("dateVal", new Date(KitchenSink.DATE1.getTime() - 1));
  2712. assertTrue(q.getResultList().isEmpty());
  2713. assertEquals(1, results.size());
  2714. } finally {
  2715. DatastoreQuery.NOW_PROVIDER = orig;
  2716. }
  2717. }
  2718. }
  2719. public void testPositionalParams() {
  2720. Entity e = Book.newBookEntity("me", "isbn", "return of yam");
  2721. ds.put(e);
  2722. List<Book> result =
  2723. em.createQuery("select b from " + Book.class.getName() + " b where isbn=?1 AND title=?2")
  2724. .setParameter(1, "isbn").setParameter(2, "return of yam").getResultList();
  2725. assertEquals(1, result.size());
  2726. }
  2727. public void testOutOfOrderPositionalParams() {
  2728. Entity e = Book.newBookEntity("me", "isbn", "return of yam");
  2729. ds.put(e);
  2730. List<Book> result =
  2731. em.createQuery("select b from " + Book.class.getName() + " b where isbn=?2 AND title=?1")
  2732. .setParameter(2, "isbn").setParameter(1, "return of yam").getResultList();
  2733. assertEquals(1, result.size());
  2734. }
  2735. public void testDefaultClassName() {
  2736. ds.put(new Entity(DetachableJPA.class.getSimpleName()));
  2737. assertEquals(1, em.createQuery("select o from " + DetachableJPA.class.getName() + " o").getResultList().size());
  2738. assertEquals(1, em.createQuery("select o from DetachableJPA o").getResultList().size());
  2739. }
  2740. public void testQueryWithEntityShortName2() {
  2741. // Uninstall this since the test needs to update!
  2742. DatastoreServiceInterceptor.uninstall();
  2743. Query q = em.createQuery("select b from bookalias b where title = 'yam'");
  2744. assertTrue(q.getResultList().isEmpty());
  2745. Book b = new Book();
  2746. b.setTitle("yam");
  2747. beginTxn();
  2748. em.persist(b);
  2749. commitTxn();
  2750. assertEquals(b, q.getResultList().get(0));
  2751. q = em.createQuery("select from bookalias c where title = 'yam'");
  2752. assertEquals(b, q.getResultList().get(0));
  2753. q = em.createQuery("select from bookalias b where b.title = 'yam'");
  2754. assertEquals(b, q.getResultList().get(0));
  2755. }
  2756. public void testQueryForClassWithNameStartingWithIn() {
  2757. // Uninstall this since the test needs to update!
  2758. DatastoreServiceInterceptor.uninstall();
  2759. // force the class metadata to load - we've seen occasional problems
  2760. // where the class can't be resolved for a query if we don't reference it first.
  2761. InTheHouseJPA pojo = new InTheHouseJPA();
  2762. beginTxn();
  2763. em.persist(pojo);
  2764. commitTxn();
  2765. assertNotNull(em.createQuery("select b from InTheHouseJPA b").getResultList().get(0));
  2766. }
  2767. public void testNonexistentClassThrowsReasonableException() {
  2768. try {
  2769. em.createQuery("select o from xyam o").getResultList();
  2770. fail("expected exception");
  2771. } catch (PersistenceException e) {
  2772. // good
  2773. }
  2774. }
  2775. public void testSubclassesNotSupported() {
  2776. JPQLQuery q = new JPQLQuery(getExecutionContext().getStoreManager(), getExecutionContext());
  2777. q.setCandidateClass(Base1.class);
  2778. q.setSubclasses(false);
  2779. try {
  2780. q.setSubclasses(true);
  2781. fail("expected nue");
  2782. } catch (NucleusUserException nue) {
  2783. // good
  2784. }
  2785. q.setCandidateClass(UnidirTop.class);
  2786. q.setSubclasses(false);
  2787. q.setSubclasses(true);
  2788. }
  2789. public void testQueryTimeout() {
  2790. DatastoreServiceFactoryInternal.setDatastoreService(null);
  2791. ApiProxy.ApiConfig config = new ApiProxy.ApiConfig();
  2792. config.setDeadlineInSeconds(3.0);
  2793. ApiProxy.Delegate delegate = EasyMock.createMock(ApiProxy.Delegate.class);
  2794. EasyMock.expect(delegate.makeAsyncCall(EasyMock.isA(ApiProxy.Environment.class),
  2795. EasyMock.eq(LocalDatastoreService.PACKAGE),
  2796. EasyMock.eq("RunQuery"),
  2797. EasyMock.isA(byte[].class),
  2798. ApiConfigMatcher.eqApiConfig(config)))
  2799. .andThrow(new DatastoreTimeoutException("too long")).anyTimes();
  2800. EasyMock.replay(delegate);
  2801. ApiProxy.Delegate original = getDelegateForThread();
  2802. setDelegateForThread(delegate);
  2803. try {
  2804. Query q = em.createQuery("select from " + Book.class.getName() + " c");
  2805. q.setHint("javax.persistence.query.timeout", 3000);
  2806. try {
  2807. q.getResultList().iterator();
  2808. fail("expected exception");
  2809. } catch (QueryTimeoutException e) {
  2810. // good
  2811. }
  2812. } finally {
  2813. setDelegateForThread(original);
  2814. }
  2815. EasyMock.verify(delegate);
  2816. }
  2817. public void testQueryTimeoutWhileIterating() {
  2818. DatastoreServiceFactoryInternal.setDatastoreService(null);
  2819. // Need to have enough data to ensure a Next call
  2820. for (int i = 0; i < 21; i++) {
  2821. Entity bookEntity = Book.newBookEntity("Joe Blow", "67890", "Bar Book");
  2822. ds.put(bookEntity);
  2823. }
  2824. ExceptionThrowingDatastoreDelegate.ExceptionPolicy policy =
  2825. new ExceptionThrowingDatastoreDelegate.BaseExceptionPolicy() {
  2826. boolean exploded = false;
  2827. protected void doIntercept(String methodName) {
  2828. if (!exploded && methodName.equals("Next")) {
  2829. exploded = true;
  2830. throw new DatastoreTimeoutException("boom: " + methodName);
  2831. }
  2832. }
  2833. };
  2834. ApiProxy.Delegate original = getDelegateForThread();
  2835. ExceptionThrowingDatastoreDelegate dd =
  2836. new ExceptionThrowingDatastoreDelegate(getDelegateForThread(), policy);
  2837. setDelegateForThread(dd);
  2838. try {
  2839. javax.persistence.Query q = em.createQuery(
  2840. "select from " + Book.class.getName() + " c");
  2841. try {
  2842. @SuppressWarnings("unchecked")
  2843. List<Book> books = (List<Book>) q.getResultList();
  2844. books.size();
  2845. fail("expected exception");
  2846. } catch (QueryTimeoutException qte) {
  2847. assertTrue(qte.getCause() instanceof org.datanucleus.store.query.QueryTimeoutException);
  2848. assertTrue(qte.getCause().getCause() instanceof DatastoreTimeoutException);
  2849. }
  2850. } finally {
  2851. setDelegateForThread(original);
  2852. }
  2853. }
  2854. public void testOverrideReadConsistency() throws ExecutionException, InterruptedException {
  2855. DatastoreServiceFactoryInternal.setDatastoreService(null);
  2856. ApiProxy.Delegate original = getDelegateForThread();
  2857. try {
  2858. ApiProxy.Delegate delegate = EasyMock.createMock(ApiProxy.Delegate.class);
  2859. Future<DatastorePb.QueryResult> result = EasyMock.createMock(Future.class);
  2860. setDelegateForThread(delegate);
  2861. ApiProxy.ApiConfig config = new ApiProxy.ApiConfig();
  2862. EasyMock.expect(delegate.makeAsyncCall(EasyMock.isA(ApiProxy.Environment.class),
  2863. EasyMock.eq(LocalDatastoreService.PACKAGE),
  2864. EasyMock.eq("RunQuery"),
  2865. FailoverMsMatcher.eqFailoverMs(null),
  2866. ApiConfigMatcher.eqApiConfig(config))).andReturn(result);
  2867. EasyMock.expect(result.get()).andReturn(null);
  2868. EasyMock.replay(delegate, result);
  2869. Query q = em.createQuery("select from " + Book.class.getName() + " c");
  2870. q.getResultList().isEmpty();
  2871. EasyMock.verify(delegate, result);
  2872. delegate = EasyMock.createMock(ApiProxy.Delegate.class);
  2873. setDelegateForThread(delegate);
  2874. result = EasyMock.createMock(Future.class);
  2875. EasyMock.expect(delegate.makeAsyncCall(EasyMock.isA(ApiProxy.Environment.class),
  2876. EasyMock.eq(LocalDatastoreService.PACKAGE),
  2877. EasyMock.eq("RunQuery"),
  2878. FailoverMsMatcher.eqFailoverMs(null),
  2879. ApiConfigMatcher.eqApiConfig(config))).andReturn(result);
  2880. EasyMock.expect(result.get()).andReturn(null);
  2881. EasyMock.replay(delegate, result);
  2882. q = em.createQuery("select from " + Book.class.getName() + " c");
  2883. q.setHint("datanucleus.appengine.datastoreReadConsistency", null);
  2884. q.getResultList().isEmpty();
  2885. EasyMock.verify(delegate);
  2886. delegate = EasyMock.createMock(ApiProxy.Delegate.class);
  2887. setDelegateForThread(delegate);
  2888. result = EasyMock.createMock(Future.class);
  2889. EasyMock.expect(delegate.makeAsyncCall(EasyMock.isA(ApiProxy.Environment.class),
  2890. EasyMock.eq(LocalDatastoreService.PACKAGE),
  2891. EasyMock.eq("RunQuery"),
  2892. FailoverMsMatcher.eqFailoverMs(null),
  2893. ApiConfigMatcher.eqApiConfig(config))).andReturn(result);
  2894. EasyMock.expect(result.get()).andReturn(null);
  2895. EasyMock.replay(delegate, result);
  2896. q = em.createQuery("select from " + Book.class.getName() + " c");
  2897. q.setHint("datanucleus.appengine.datastoreReadConsistency", "STRONG");
  2898. q.getResultList().isEmpty();
  2899. EasyMock.verify(delegate, result);
  2900. delegate = EasyMock.createMock(ApiProxy.Delegate.class);
  2901. setDelegateForThread(delegate);
  2902. result = EasyMock.createMock(Future.class);
  2903. EasyMock.expect(delegate.makeAsyncCall(EasyMock.isA(ApiProxy.Environment.class),
  2904. EasyMock.eq(LocalDatastoreService.PACKAGE),
  2905. EasyMock.eq("RunQuery"),
  2906. FailoverMsMatcher.eqFailoverMs(-1L),
  2907. ApiConfigMatcher.eqApiConfig(config))).andReturn(result);
  2908. EasyMock.expect(result.get()).andReturn(null);
  2909. EasyMock.replay(delegate, result);
  2910. q = em.createQuery("select from " + Book.class.getName() + " c");
  2911. q.setHint("datanucleus.appengine.datastoreReadConsistency", "EVENTUAL");
  2912. q.getResultList().isEmpty();
  2913. EasyMock.verify(delegate, result);
  2914. } finally {
  2915. setDelegateForThread(original);
  2916. }
  2917. }
  2918. public void testSetChunkSize() {
  2919. DatastoreServiceFactoryInternal.setDatastoreService(null);
  2920. ApiProxy.Delegate original = getDelegateForThread();
  2921. Future<DatastorePb.QueryResult> result = EasyMock.createNiceMock(Future.class);
  2922. try {
  2923. ApiProxy.Delegate delegate = EasyMock.createMock(ApiProxy.Delegate.class);
  2924. setDelegateForThread(delegate);
  2925. ApiProxy.ApiConfig config = new ApiProxy.ApiConfig();
  2926. EasyMock.expect(delegate.makeAsyncCall(EasyMock.isA(ApiProxy.Environment.class),
  2927. EasyMock.eq(LocalDatastoreService.PACKAGE),
  2928. EasyMock.eq("RunQuery"),
  2929. ChunkMatcher.eqChunkSize(33),
  2930. ApiConfigMatcher.eqApiConfig(config))).andReturn(result);
  2931. EasyMock.replay(delegate, result);
  2932. Query q = em.createQuery("select from " + Flight.class.getName() + " c");
  2933. q.setHint("datanucleus.query.fetchSize", 33);
  2934. q.getResultList();
  2935. EasyMock.verify(delegate);
  2936. } finally {
  2937. setDelegateForThread(original);
  2938. }
  2939. }
  2940. private void assertQueryUnsupportedByDatastore(String query, Class<?> expectedCauseClass) {
  2941. Query q = em.createQuery(query);
  2942. q.setHint(DatastoreManager.QUERYEXT_INMEMORY_WHEN_UNSUPPORTED, "false");
  2943. try {
  2944. q.getResultList().iterator();
  2945. fail("expected PersistenceException for query <" + query + ">");
  2946. } catch (PersistenceException e) {
  2947. // good
  2948. assertTrue(e.getCause().getClass().getName() + ": " + e.getCause().getMessage(),
  2949. expectedCauseClass.isAssignableFrom(e.getCause().getClass()));
  2950. }
  2951. }
  2952. private void assertQueryUnsupportedByOrm(String query,
  2953. Expression.Operator unsupportedOp) {
  2954. Query q = em.createQuery(query);
  2955. q.setHint(DatastoreManager.QUERYEXT_INMEMORY_WHEN_UNSUPPORTED, "false"); // Dont allow in-memory for unsupported syntax
  2956. try {
  2957. q.getResultList();
  2958. fail("expected PersistenceException->UnsupportedOperationException for query <" + query + ">");
  2959. } catch (PersistenceException e) {
  2960. Throwable cause = e.getCause();
  2961. if (cause instanceof DatastoreQuery.UnsupportedDatastoreOperatorException) {
  2962. // Good. Expression.Operator doesn't override equals
  2963. // so we just compare the string representation. Operator case-insensitive
  2964. assertEquals(unsupportedOp.toString().toLowerCase(), ((DatastoreQuery.UnsupportedDatastoreOperatorException)cause).getOperation().toString().toLowerCase());
  2965. }
  2966. else {
  2967. throw e;
  2968. }
  2969. }
  2970. }
  2971. private void assertQueryUnsupportedByOrm(String query,
  2972. Expression.Operator unsupportedOp,
  2973. Set<Expression.Operator> unsupportedOps) {
  2974. assertQueryUnsupportedByOrm(query, unsupportedOp);
  2975. unsupportedOps.remove(unsupportedOp);
  2976. }
  2977. private void assertQueryRequiresUnsupportedDatastoreFeature(String query) {
  2978. Query q = em.createQuery(query);
  2979. q.setHint(DatastoreManager.QUERYEXT_INMEMORY_WHEN_UNSUPPORTED, "false");
  2980. try {
  2981. q.getResultList();
  2982. fail("expected UnsupportedDatastoreFeatureException for query <" + query + ">");
  2983. } catch (PersistenceException pe) {
  2984. if (pe.getCause() instanceof DatastoreQuery.UnsupportedDatastoreFeatureException) {
  2985. // good
  2986. }
  2987. else {
  2988. throw pe;
  2989. }
  2990. }
  2991. }
  2992. private void assertQuerySupported(String query, List<FilterPredicate> addedFilters,
  2993. List<SortPredicate> addedSorts, Object... nameVals) {
  2994. javax.persistence.Query q = em.createQuery(query);
  2995. String name = null;
  2996. for (Object nameOrVal : nameVals) {
  2997. if (name == null) {
  2998. name = (String) nameOrVal;
  2999. } else {
  3000. q.setParameter(name, nameOrVal);
  3001. name = null;
  3002. }
  3003. }
  3004. q.getResultList();
  3005. assertFilterPredicatesEqual(addedFilters, getFilterPredicates(q));
  3006. assertEquals(addedSorts, getSortPredicates(q));
  3007. }
  3008. // TODO(maxr): Get rid of this when we've fixed the npe in FilterPredicate.equals().
  3009. private static void assertFilterPredicatesEqual(
  3010. List<FilterPredicate> expected, List<FilterPredicate> actual) {
  3011. List<FilterPredicate> expected2 = Utils.newArrayList();
  3012. for (FilterPredicate fp : expected) {
  3013. if (fp.getValue() == null) {
  3014. expected2.add(new FilterPredicate(fp.getPropertyName(), fp.getOperator(), "____null"));
  3015. } else {
  3016. expected2.add(fp);
  3017. }
  3018. }
  3019. List<FilterPredicate> actual2 = Utils.newArrayList();
  3020. for (FilterPredicate fp : actual) {
  3021. if (fp.getValue() == null) {
  3022. actual2.add(new FilterPredicate(fp.getPropertyName(), fp.getOperator(), "____null"));
  3023. } else {
  3024. actual2.add(fp);
  3025. }
  3026. }
  3027. assertEquals(expected2, actual2);
  3028. }
  3029. private DatastoreQuery getDatastoreQuery(javax.persistence.Query q) {
  3030. return ((JPQLQuery) ((JPAQuery) q).getInternalQuery()).getDatastoreQuery();
  3031. }
  3032. private List<FilterPredicate> getFilterPredicates(javax.persistence.Query q) {
  3033. return getDatastoreQuery(q).getLatestDatastoreQuery().getFilterPredicates();
  3034. }
  3035. private List<SortPredicate> getSortPredicates(javax.persistence.Query q) {
  3036. return getDatastoreQuery(q).getLatestDatastoreQuery().getSortPredicates();
  3037. }
  3038. }