1 package org.apache.torque.util;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.util.Calendar;
23 import java.util.Date;
24 import java.util.List;
25 import java.util.Map;
26
27 import org.apache.commons.configuration.BaseConfiguration;
28 import org.apache.commons.configuration.Configuration;
29 import org.apache.commons.lang.SerializationUtils;
30 import org.apache.torque.BaseTestCase;
31 import org.apache.torque.Torque;
32 import org.apache.torque.TorqueException;
33 import org.apache.torque.adapter.DBFactory;
34 import org.apache.torque.map.ColumnMap;
35 import org.apache.torque.map.DatabaseMap;
36 import org.apache.torque.map.TableMap;
37 import org.apache.torque.util.Criteria.Criterion;
38 import org.apache.torque.util.Criteria.Join;
39
40 /***
41 * Test class for Criteria.
42 *
43 * @author <a href="mailto:celkins@scardini.com">Christopher Elkins</a>
44 * @author <a href="mailto:sam@neurogrid.com">Sam Joseph</a>
45 * @author <a href="mailto:seade@backstagetech.com.au">Scott Eade</a>
46 * @version $Id: CriteriaTest.java 535591 2007-05-06 10:05:04Z tfischer $
47 */
48 public class CriteriaTest extends BaseTestCase
49 {
50
51 /*** The criteria to use in the test. */
52 private Criteria c;
53
54 /***
55 * Creates a new instance.
56 *
57 * @param name the name of the test to run
58 */
59 public CriteriaTest(String name)
60 {
61 super(name);
62 }
63
64 /***
65 * Initializes the criteria.
66 */
67 public void setUp()
68 {
69 super.setUp();
70 c = new Criteria();
71 }
72
73 /***
74 * Test basic adding of strings.
75 */
76 public void testAddString()
77 {
78 final String table = "myTable";
79 final String column = "myColumn";
80 final String value = "myValue";
81
82
83 c.add(table, column, (Object) value);
84
85
86 assertTrue(c.containsKey(table, column));
87
88
89 assertTrue(c.getString(table, column).equals(value));
90 }
91
92 /***
93 * test various properties of Criterion and nested criterion
94 */
95 public void testNestedCriterion()
96 {
97 final String table2 = "myTable2";
98 final String column2 = "myColumn2";
99 final String value2 = "myValue2";
100
101 final String table3 = "myTable3";
102 final String column3 = "myColumn3";
103 final String value3 = "myValue3";
104
105 final String table4 = "myTable4";
106 final String column4 = "myColumn4";
107 final String value4 = "myValue4";
108
109 final String table5 = "myTable5";
110 final String column5 = "myColumn5";
111 final String value5 = "myValue5";
112
113 Criteria.Criterion crit2 =
114 c.getNewCriterion(table2, column2, (Object) value2, Criteria.EQUAL);
115 Criteria.Criterion crit3 =
116 c.getNewCriterion(table3, column3, (Object) value3, Criteria.EQUAL);
117 Criteria.Criterion crit4 =
118 c.getNewCriterion(table4, column4, (Object) value4, Criteria.EQUAL);
119 Criteria.Criterion crit5 =
120 c.getNewCriterion(table5, column5, (Object) value5, Criteria.EQUAL);
121
122 crit2.and(crit3).or(crit4.and(crit5));
123 String expect =
124 "((myTable2.myColumn2='myValue2' "
125 + "AND myTable3.myColumn3='myValue3') "
126 + "OR (myTable4.myColumn4='myValue4' "
127 + "AND myTable5.myColumn5='myValue5'))";
128 String result = crit2.toString();
129 assertEquals(expect, result);
130
131 Criteria.Criterion crit6 =
132 c.getNewCriterion(table2, column2, (Object) value2, Criteria.EQUAL);
133 Criteria.Criterion crit7 =
134 c.getNewCriterion(table3, column3, (Object) value3, Criteria.EQUAL);
135 Criteria.Criterion crit8 =
136 c.getNewCriterion(table4, column4, (Object) value4, Criteria.EQUAL);
137 Criteria.Criterion crit9 =
138 c.getNewCriterion(table5, column5, (Object) value5, Criteria.EQUAL);
139
140 crit6.and(crit7).or(crit8).and(crit9);
141 expect =
142 "(((myTable2.myColumn2='myValue2' "
143 + "AND myTable3.myColumn3='myValue3') "
144 + "OR myTable4.myColumn4='myValue4') "
145 + "AND myTable5.myColumn5='myValue5')";
146 result = crit6.toString();
147 assertEquals(expect, result);
148
149
150
151 Criteria.Criterion[] crita = crit2.getAttachedCriterion();
152
153 assertEquals(crit2, crita[0]);
154 assertEquals(crit3, crita[1]);
155 assertEquals(crit4, crita[2]);
156 assertEquals(crit5, crita[3]);
157
158 List tables = crit2.getAllTables();
159
160 assertEquals(crit2.getTable(), tables.get(0));
161 assertEquals(crit3.getTable(), tables.get(1));
162 assertEquals(crit4.getTable(), tables.get(2));
163 assertEquals(crit5.getTable(), tables.get(3));
164
165
166 assertTrue(crit2.hashCode() == crit2.hashCode());
167 assertEquals(crit2.toString(), crit2.toString());
168 }
169
170 /***
171 * Tests <= and =>.
172 */
173 public void testBetweenCriterion()
174 {
175 Criteria.Criterion cn1 =
176 c.getNewCriterion(
177 "INVOICE.COST",
178 new Integer(1000),
179 Criteria.GREATER_EQUAL);
180 Criteria.Criterion cn2 =
181 c.getNewCriterion(
182 "INVOICE.COST",
183 new Integer(5000),
184 Criteria.LESS_EQUAL);
185 c.add(cn1.and(cn2));
186 String expect =
187 "SELECT FROM INVOICE WHERE "
188 + "(INVOICE.COST>=1000 AND INVOICE.COST<=5000)";
189 String result = null;
190 try
191 {
192 result = BasePeer.createQueryString(c);
193 }
194 catch (TorqueException e)
195 {
196 fail("TorqueException thrown in BasePeer.createQueryString()");
197 }
198
199 assertEquals(expect, result);
200 }
201
202 /***
203 * Verify that AND and OR criterion are nested correctly.
204 */
205 public void testPrecedence()
206 {
207 Criteria.Criterion cn1 =
208 c.getNewCriterion("INVOICE.COST", "1000", Criteria.GREATER_EQUAL);
209 Criteria.Criterion cn2 =
210 c.getNewCriterion("INVOICE.COST", "2000", Criteria.LESS_EQUAL);
211 Criteria.Criterion cn3 =
212 c.getNewCriterion("INVOICE.COST", "8000", Criteria.GREATER_EQUAL);
213 Criteria.Criterion cn4 =
214 c.getNewCriterion("INVOICE.COST", "9000", Criteria.LESS_EQUAL);
215 c.add(cn1.and(cn2));
216 c.or(cn3.and(cn4));
217
218 String expect =
219 "SELECT FROM INVOICE WHERE "
220 + "((INVOICE.COST>='1000' AND INVOICE.COST<='2000') "
221 + "OR (INVOICE.COST>='8000' AND INVOICE.COST<='9000'))";
222
223 String result = null;
224 try
225 {
226 result = BasePeer.createQueryString(c);
227 }
228 catch (TorqueException e)
229 {
230 fail("TorqueException thrown in BasePeer.createQueryString()");
231 }
232
233 assertEquals(expect, result);
234 }
235
236 /***
237 * Test Criterion.setIgnoreCase().
238 * As the output is db specific the test just prints the result to
239 * System.out
240 */
241 public void testCriterionIgnoreCase()
242 {
243 Criteria myCriteria = new Criteria();
244
245 Criteria.Criterion expected = myCriteria.getNewCriterion(
246 "TABLE.COLUMN", (Object)"FoObAr", Criteria.LIKE);
247 Criteria.Criterion result = expected.setIgnoreCase(true);
248 assertEquals("Criterion mis-match after calling setIgnoreCase(true)",
249 expected.toString(), result.toString());
250 }
251
252 /***
253 * Test that true is evaluated correctly.
254 */
255 public void testBoolean()
256 {
257 Criteria c = new Criteria().add("TABLE.COLUMN", true);
258
259 String expect = "SELECT FROM TABLE WHERE TABLE.COLUMN=1";
260
261 String result = null;
262 try
263 {
264 result = BasePeer.createQueryString(c);
265 }
266 catch (TorqueException e)
267 {
268 fail("TorqueException thrown in BasePeer.createQueryString()");
269 }
270
271 assertEquals(expect, result);
272
273
274 c = new Criteria();
275 Criteria.Criterion cc =
276 c.getNewCriterion("TABLE.COLUMN", Boolean.TRUE, Criteria.EQUAL);
277
278 Configuration conf = new BaseConfiguration();
279 conf.addProperty("driver", "org.postgresql.Driver");
280 try
281 {
282 cc.setDB(DBFactory.create("org.postgresql.Driver"));
283 }
284 catch (Exception e)
285 {
286 fail("Exception thrown in DBFactory");
287 }
288
289 assertEquals("TABLE.COLUMN=TRUE", cc.toString());
290 }
291
292 /***
293 * testcase for addDate()
294 */
295 public void testAddDate()
296 {
297 Criteria c = new Criteria();
298 c.addDate("TABLE.DATE_COLUMN", 2003, 0, 22);
299
300 String expect = "SELECT FROM TABLE WHERE TABLE.DATE_COLUMN='20030122000000'";
301
302 String result = null;
303 try
304 {
305 result = BasePeer.createQueryString(c);
306 }
307 catch (TorqueException e)
308 {
309 e.printStackTrace();
310 fail("TorqueException thrown in BasePeer.createQueryString()");
311 }
312 assertEquals(expect, result);
313 }
314
315 /***
316 * testcase for andDate()
317 * issue TORQUE-42
318 */
319 public void testAndDate()
320 {
321 Criteria c = new Criteria();
322 c.addDate("TABLE.DATE_COLUMN", 2003, 0, 22, Criteria.GREATER_THAN);
323 c.andDate("TABLE.DATE_COLUMN", 2004, 0, 22, Criteria.LESS_THAN);
324
325 String expect = "SELECT FROM TABLE WHERE (TABLE.DATE_COLUMN>'20030122000000' AND TABLE.DATE_COLUMN<'20040122000000')";
326
327 String result = null;
328 try
329 {
330 result = BasePeer.createQueryString(c);
331 }
332 catch (TorqueException e)
333 {
334 e.printStackTrace();
335 fail("TorqueException thrown in BasePeer.createQueryString()");
336 }
337 assertEquals(expect, result);
338 }
339
340 /***
341 * testcase for add(Date)
342 */
343 public void testDateAdd()
344 {
345 Calendar cal = Calendar.getInstance();
346 cal.set(2003, 0, 22, 0, 0, 0);
347 Date date = cal.getTime();
348 Criteria c = new Criteria();
349 c.add("TABLE.DATE_COLUMN", date);
350
351 String expect = "SELECT FROM TABLE WHERE TABLE.DATE_COLUMN='20030122000000'";
352
353 String result = null;
354 try
355 {
356 result = BasePeer.createQueryString(c);
357 }
358 catch (TorqueException e)
359 {
360 e.printStackTrace();
361 fail("TorqueException thrown in BasePeer.createQueryString()");
362 }
363 assertEquals(expect, result);
364 }
365
366 public void testCurrentDate()
367 {
368 Criteria c = new Criteria()
369 .add("TABLE.DATE_COLUMN", Criteria.CURRENT_DATE)
370 .add("TABLE.TIME_COLUMN", Criteria.CURRENT_TIME);
371
372 String expect = "SELECT FROM TABLE WHERE TABLE.TIME_COLUMN=CURRENT_TIME AND TABLE.DATE_COLUMN=CURRENT_DATE";
373
374 String result = null;
375 try
376 {
377 result = BasePeer.createQueryString(c);
378 }
379 catch (TorqueException e)
380 {
381 e.printStackTrace();
382 fail("TorqueException thrown in BasePeer.createQueryString()");
383 }
384
385 assertEquals(expect,result);
386 }
387
388 public void testCountAster()
389 {
390 Criteria c = new Criteria()
391 .addSelectColumn("COUNT(*)")
392 .add("TABLE.DATE_COLUMN", Criteria.CURRENT_DATE)
393 .add("TABLE.TIME_COLUMN", Criteria.CURRENT_TIME);
394
395 String expect = "SELECT COUNT(*) FROM TABLE WHERE TABLE.TIME_COLUMN=CURRENT_TIME AND TABLE.DATE_COLUMN=CURRENT_DATE";
396
397 String result = null;
398 try
399 {
400 result = BasePeer.createQueryString(c);
401 }
402 catch (TorqueException e)
403 {
404 e.printStackTrace();
405 fail("TorqueException thrown in BasePeer.createQueryString()");
406 }
407
408 assertEquals(expect,result);
409
410 }
411
412 /***
413 * This test case has been written to try out the fix applied to resolve
414 * TRQS73 - i.e. ensuring that Criteria.toString() does not alter any limit
415 * or offset that may be stored in the Criteria object. This testcase
416 * could actually pass without the fix if the database in use does not
417 * support native limits and offsets.
418 */
419 public void testCriteriaToStringOffset()
420 {
421 Criteria c = new Criteria()
422 .add("TABLE.DATE_COLUMN", Criteria.CURRENT_DATE)
423 .setOffset(3)
424 .setLimit(5);
425
426 String toStringExpect = "Criteria:: TABLE.DATE_COLUMN<=>TABLE.DATE_COLUMN=CURRENT_DATE: "
427 + "\nCurrent Query SQL (may not be complete or applicable): "
428 + "SELECT FROM TABLE WHERE TABLE.DATE_COLUMN=CURRENT_DATE LIMIT 5 OFFSET 3";
429
430 String cString = c.toString();
431
432 assertEquals(toStringExpect, cString);
433
434
435
436 cString = c.toString();
437
438 assertEquals(toStringExpect, cString);
439 }
440
441 /***
442 * TORQUE-87
443 */
444 public void testCriteriaWithOffsetNoLimit()
445 {
446 Criteria c = new Criteria()
447 .add("TABLE.DATE_COLUMN", Criteria.CURRENT_DATE)
448 .setOffset(3);
449
450 String toStringExpect = "Criteria:: TABLE.DATE_COLUMN<=>TABLE.DATE_COLUMN=CURRENT_DATE: "
451 + "\nCurrent Query SQL (may not be complete or applicable): "
452 + "SELECT FROM TABLE WHERE TABLE.DATE_COLUMN=CURRENT_DATE LIMIT 18446744073709551615 OFFSET 3";
453
454 String cString = c.toString();
455
456 assertEquals(toStringExpect, cString);
457
458
459
460 cString = c.toString();
461
462 assertEquals(toStringExpect, cString);
463 }
464
465 /***
466 * This test case has been written to try out the fix applied to resolve
467 * TRQS73 - i.e. ensuring that Criteria.toString() does not alter any limit
468 * or offset that may be stored in the Criteria object. This testcase
469 * could actually pass without the fix if the database in use does not
470 * support native limits and offsets.
471 */
472 public void testCriteriaToStringLimit()
473 {
474 Criteria c = new Criteria()
475 .add("TABLE.DATE_COLUMN", Criteria.CURRENT_DATE)
476 .setLimit(5);
477
478 String toStringExpect = "Criteria:: TABLE.DATE_COLUMN<=>TABLE.DATE_COLUMN=CURRENT_DATE: "
479 + "\nCurrent Query SQL (may not be complete or applicable): "
480 + "SELECT FROM TABLE WHERE TABLE.DATE_COLUMN=CURRENT_DATE LIMIT 5";
481
482 String cString = c.toString();
483
484 assertEquals(toStringExpect, cString);
485
486
487
488 cString = c.toString();
489
490 assertEquals(toStringExpect, cString);
491 }
492
493 /***
494 * This test case verifies if the Criteria.LIKE comparison type will
495 * get replaced through Criteria.EQUAL if there are no SQL wildcards
496 * in the given value.
497 */
498 public void testLikeWithoutWildcards()
499 {
500 Criteria c = new Criteria();
501 c.add("TABLE.COLUMN", (Object) "no wildcards", Criteria.LIKE);
502
503 String expect = "SELECT FROM TABLE WHERE TABLE.COLUMN = 'no wildcards'";
504
505 String result = null;
506 try
507 {
508 result = BasePeer.createQueryString(c);
509 }
510 catch (TorqueException e)
511 {
512 e.printStackTrace();
513 fail("TorqueException thrown in BasePeer.createQueryString()");
514 }
515
516 assertEquals(expect, result);
517 }
518
519 /***
520 * This test case verifies if the Criteria.NOT_LIKE comparison type will
521 * get replaced through Criteria.NOT_EQUAL if there are no SQL wildcards
522 * in the given value.
523 */
524 public void testNotLikeWithoutWildcards()
525 {
526 Criteria c = new Criteria();
527 c.add("TABLE.COLUMN", (Object) "no wildcards", Criteria.NOT_LIKE);
528
529 String firstExpect = "SELECT FROM TABLE WHERE TABLE.COLUMN != 'no wildcards'";
530 String secondExpect = "SELECT FROM TABLE WHERE TABLE.COLUMN <> 'no wildcards'";
531
532 String result = null;
533 try
534 {
535 result = BasePeer.createQueryString(c);
536 }
537 catch (TorqueException e)
538 {
539 e.printStackTrace();
540 fail("TorqueException thrown in BasePeer.createQueryString()");
541 }
542
543 assertTrue(result.equals(firstExpect) || result.equals(secondExpect));
544 }
545
546 /***
547 * Test that serialization works.
548 */
549 public void testSerialization()
550 {
551 c.setOffset(10);
552 c.setLimit(11);
553 c.setIgnoreCase(true);
554 c.setSingleRecord(true);
555 c.setCascade(true);
556 c.setDbName("myDB");
557 c.setAll();
558 c.setDistinct();
559 c.addSelectColumn("Author.NAME");
560 c.addSelectColumn("Author.AUTHOR_ID");
561 c.addDescendingOrderByColumn("Author.NAME");
562 c.addAscendingOrderByColumn("Author.AUTHOR_ID");
563 c.addAlias("Writer", "Author");
564 c.addAsColumn("AUTHOR_NAME", "Author.NAME");
565 c.addJoin("Author.AUTHOR_ID", "Book.AUTHOR_ID", Criteria.INNER_JOIN);
566 c.add("Author.NAME", (Object) "author%", Criteria.LIKE);
567
568
569 Criterion cn = c.getCriterion("Author.NAME");
570 cn.setIgnoreCase(true);
571 assertEquals("author%", cn.getValue());
572 assertEquals(Criteria.LIKE, cn.getComparison());
573 Criterion cnDirectClone = (Criterion) SerializationUtils.clone(cn);
574 assertEquals(cn, cnDirectClone);
575
576
577 Criteria cClone = (Criteria) SerializationUtils.clone(c);
578
579
580 assertEquals(c.size(), cClone.size());
581 assertEquals(10, cClone.getOffset());
582 assertEquals(c.getOffset(), cClone.getOffset());
583 assertEquals(11, cClone.getLimit());
584 assertEquals(c.getLimit(), cClone.getLimit());
585 assertEquals(true, cClone.isIgnoreCase());
586 assertEquals(c.isIgnoreCase(), cClone.isIgnoreCase());
587 assertEquals(true, cClone.isSingleRecord());
588 assertEquals(c.isSingleRecord(), cClone.isSingleRecord());
589 assertEquals(true, cClone.isCascade());
590 assertEquals(c.isCascade(), cClone.isCascade());
591 assertEquals("myDB", cClone.getDbName());
592 assertEquals(c.getDbName(), cClone.getDbName());
593 List selectModifiersClone = cClone.getSelectModifiers();
594 assertTrue(selectModifiersClone.contains(Criteria.ALL.toString()));
595 assertTrue(selectModifiersClone.contains(Criteria.DISTINCT.toString()));
596 assertEquals(c.getSelectModifiers(), cClone.getSelectModifiers());
597 List selectColumnsClone = cClone.getSelectColumns();
598 assertTrue(selectColumnsClone.contains("Author.NAME"));
599 assertTrue(selectColumnsClone.contains("Author.AUTHOR_ID"));
600 assertEquals(c.getSelectColumns(), cClone.getSelectColumns());
601 List orderByColumnsClone = cClone.getOrderByColumns();
602 assertTrue(orderByColumnsClone.contains("Author.NAME DESC"));
603 assertTrue(orderByColumnsClone.contains("Author.AUTHOR_ID ASC"));
604 assertEquals(c.getOrderByColumns(), cClone.getOrderByColumns());
605 Map aliasesClone = cClone.getAliases();
606 assertTrue(aliasesClone.containsKey("Writer"));
607 assertEquals("Author", aliasesClone.get("Writer"));
608 assertEquals(c.getAliases(), cClone.getAliases());
609 Map asColumnsClone = cClone.getAsColumns();
610 assertTrue(asColumnsClone.containsKey("AUTHOR_NAME"));
611 assertEquals("Author.NAME", asColumnsClone.get("AUTHOR_NAME"));
612 assertEquals(c.getAsColumns(), cClone.getAsColumns());
613
614
615 List joinsClone = cClone.getJoins();
616 Join joinClone = (Join) joinsClone.get(0);
617 assertEquals("Author.AUTHOR_ID", joinClone.getLeftColumn());
618 assertEquals("Book.AUTHOR_ID", joinClone.getRightColumn());
619 assertEquals(Criteria.INNER_JOIN, joinClone.getJoinType());
620 assertEquals(c.getJoins(), cClone.getJoins());
621
622
623 Criterion cnClone = cClone.getCriterion("Author.NAME");
624 assertEquals("author%", cnClone.getValue());
625 assertEquals(Criteria.LIKE, cnClone.getComparison());
626 assertEquals(cn.isIgnoreCase(), cnClone.isIgnoreCase());
627
628
629 assertEquals(c, cClone);
630
631
632 assertEquals(c.hashCode(), cClone.hashCode());
633 }
634
635 /***
636 * Test that {@link Criteria#equals(Object)} works correctly for a simple
637 * Criteria object.
638 * @throws TorqueException
639 */
640 public void testEquals() throws TorqueException
641 {
642 c.addSelectColumn("Author.NAME");
643 c.addSelectColumn("Author.AUTHOR_ID");
644 c.add("Author.NAME", "foobar");
645 Criteria cClone = (Criteria) SerializationUtils.clone(c);
646 assertTrue(c.equals(cClone));
647 }
648
649 /***
650 * Checks whether orderBy works.
651 */
652 public void testOrderBy() throws TorqueException
653 {
654
655 DatabaseMap dbMap = Torque.getDatabaseMap(Torque.getDefaultDB());
656
657 TableMap tableMap = new TableMap("AUTHOR", dbMap);
658 dbMap.addTable(tableMap);
659
660 ColumnMap columnMap = new ColumnMap("NAME", tableMap);
661 columnMap.setType("");
662 tableMap.addColumn(columnMap);
663
664 columnMap = new ColumnMap("AUTHOR_ID", tableMap);
665 columnMap.setType(new Integer(0));
666 tableMap.addColumn(columnMap);
667
668
669
670 Criteria criteria = new Criteria();
671 criteria.addSelectColumn("AUTHOR.NAME");
672 criteria.addAlias("a", "AUTHOR");
673 criteria.addJoin(
674 "AUTHOR.AUTHOR_ID",
675 "a." + "AUTHOR_ID");
676 criteria.addAscendingOrderByColumn(
677 "a.NAME");
678
679 String result = BasePeer.createQueryString(criteria);
680 assertEquals("SELECT AUTHOR.NAME, a.NAME "
681 + "FROM AUTHOR, AUTHOR a "
682 + "WHERE AUTHOR.AUTHOR_ID=a.AUTHOR_ID "
683 + "ORDER BY a.NAME ASC",
684 result);
685 }
686
687 }