001package com.avaje.ebean;
002
003import com.avaje.ebean.text.PathProperties;
004import org.jetbrains.annotations.Nullable;
005
006import javax.persistence.NonUniqueResultException;
007import java.io.Serializable;
008import java.sql.Timestamp;
009import java.util.Collection;
010import java.util.List;
011import java.util.Map;
012import java.util.Set;
013
014/**
015 * List of Expressions that make up a where or having clause.
016 * <p>
017 * An ExpressionList is returned from {@link Query#where()}.
018 * </p>
019 * <p>
020 * The ExpressionList has a list of convenience methods that create the standard
021 * expressions and add them to this list.
022 * </p>
023 * <p>
024 * The ExpressionList also duplicates methods that are found on the Query such
025 * as findList() and orderBy(). The purpose of these methods is provide a fluid
026 * API. The upside of this approach is that you can build and execute a query
027 * via chained methods. The down side is that this ExpressionList object has
028 * more methods than you would initially expect (the ones duplicated from
029 * Query).
030 * </p>
031 * 
032 * @see Query#where()
033 */
034public interface ExpressionList<T> extends Serializable {
035
036  /**
037   * Return the query that owns this expression list.
038   * <p>
039   * This is a convenience method solely to support a fluid API where the
040   * methods are chained together. Adding expressions returns this expression
041   * list and this method can be used after that to return back the original
042   * query so that further things can be added to it.
043   * </p>
044   */
045  Query<T> query();
046
047  /**
048   * Set the order by clause replacing the existing order by clause if there is
049   * one.
050   * <p>
051   * This follows SQL syntax using commas between each property with the
052   * optional asc and desc keywords representing ascending and descending order
053   * respectively.
054   * </p>
055   * <p>
056   * This is EXACTLY the same as {@link #orderBy(String)}.
057   * </p>
058   */
059  Query<T> order(String orderByClause);
060
061  /**
062   * Return the OrderBy so that you can append an ascending or descending
063   * property to the order by clause.
064   * <p>
065   * This will never return a null. If no order by clause exists then an 'empty'
066   * OrderBy object is returned.
067   * </p>
068   */
069  OrderBy<T> order();
070
071  /**
072   * Return the OrderBy so that you can append an ascending or descending
073   * property to the order by clause.
074   * <p>
075   * This will never return a null. If no order by clause exists then an 'empty'
076   * OrderBy object is returned.
077   * </p>
078   */
079  OrderBy<T> orderBy();
080
081  /**
082   * Add an orderBy clause to the query.
083   * 
084   * @see Query#orderBy(String)
085   */
086  Query<T> orderBy(String orderBy);
087
088  /**
089   * Add an orderBy clause to the query.
090   * 
091   * @see Query#orderBy(String)
092   */
093  Query<T> setOrderBy(String orderBy);
094
095  /**
096   * Apply the path properties to the query replacing the select and fetch clauses.
097   */
098  Query<T> apply(PathProperties pathProperties);
099
100  /**
101   * Perform an 'As of' query using history tables to return the object graph
102   * as of a time in the past.
103   * <p>
104   *   To perform this query the DB must have underlying history tables.
105   * </p>
106   *
107   * @param asOf the date time in the past at which you want to view the data
108   */
109  Query<T> asOf(Timestamp asOf);
110
111  /**
112   * Execute the query against the draft set of tables.
113   */
114  Query<T> asDraft();
115
116  /**
117   * Execute the query including soft deleted rows.
118   */
119  Query<T> includeSoftDeletes();
120
121  /**
122   * Execute as a delete query deleting the 'root level' beans that match the predicates
123   * in the query.
124   * <p>
125   * Note that if the query includes joins then the generated delete statement may not be
126   * optimal depending on the database platform.
127   * </p>
128   *
129   * @return the number of beans/rows that were deleted.
130   */
131  int delete();
132
133  /**
134   * Execute the query iterating over the results.
135   * 
136   * @see Query#findIterate()
137   */
138  QueryIterator<T> findIterate();
139
140  /**
141   * Execute the query process the beans one at a time.
142   *
143   * @see Query#findEach(QueryEachConsumer)
144   */
145  void findEach(QueryEachConsumer<T> consumer);
146
147  /**
148   * Execute the query processing the beans one at a time with the ability to
149   * stop processing before reading all the beans.
150   *
151   * @see Query#findEachWhile(QueryEachWhileConsumer)
152   */
153  void findEachWhile(QueryEachWhileConsumer<T> consumer);
154
155  /**
156   * Execute the query returning a list.
157   * 
158   * @see Query#findList()
159   */
160  List<T> findList();
161
162  /**
163   * Execute the query returning the list of Id's.
164   * 
165   * @see Query#findIds()
166   */
167  List<Object> findIds();
168
169  /**
170   * Return the count of entities this query should return.
171   * <p>
172   * This is the number of 'top level' or 'root level' entities.
173   * </p>
174   */
175  int findRowCount();
176
177  /**
178   * Execute the query returning a set.
179   * 
180   * @see Query#findSet()
181   */
182  Set<T> findSet();
183
184  /**
185   * Execute the query returning a map.
186   * 
187   * @see Query#findMap()
188   */
189  Map<?, T> findMap();
190
191  /**
192   * Return a typed map specifying the key property and type.
193   */
194  <K> Map<K, T> findMap(String keyProperty, Class<K> keyType);
195
196  /**
197   * Execute the query returning a single bean or null (if no matching
198   * bean is found).
199   * <p>
200   * If more than 1 row is found for this query then a NonUniqueResultException is
201   * thrown.
202   * </p>
203   *
204   * @throws NonUniqueResultException if more than one result was found
205   *
206   * @see Query#findUnique()
207   */
208  @Nullable
209  T findUnique();
210
211  /**
212   * Execute find row count query in a background thread.
213   * <p>
214   * This returns a Future object which can be used to cancel, check the
215   * execution status (isDone etc) and get the value (with or without a
216   * timeout).
217   * </p>
218   * 
219   * @return a Future object for the row count query
220   */
221  FutureRowCount<T> findFutureRowCount();
222
223  /**
224   * Execute find Id's query in a background thread.
225   * <p>
226   * This returns a Future object which can be used to cancel, check the
227   * execution status (isDone etc) and get the value (with or without a
228   * timeout).
229   * </p>
230   * 
231   * @return a Future object for the list of Id's
232   */
233  FutureIds<T> findFutureIds();
234
235  /**
236   * Execute find list query in a background thread.
237   * <p>
238   * This returns a Future object which can be used to cancel, check the
239   * execution status (isDone etc) and get the value (with or without a
240   * timeout).
241   * </p>
242   * 
243   * @return a Future object for the list result of the query
244   */
245  FutureList<T> findFutureList();
246
247  /**
248   * Return a PagedList for this query using pageIndex and pageSize.
249   * <p>
250   * The benefit of using this over just using the normal {@link Query#setFirstRow(int)} and
251   * {@link Query#setMaxRows(int)} is that it additionally wraps an optional call to
252   * {@link Query#findFutureRowCount()} to determine total row count, total page count etc.
253   * </p>
254   * <p>
255   * Internally this works using {@link Query#setFirstRow(int)} and {@link Query#setMaxRows(int)} on
256   * the query. This translates into SQL that uses limit offset, rownum or row_number
257   * function to limit the result set.
258   * </p>
259   * 
260   * @param pageIndex
261   *          The zero based index of the page.
262   * @param pageSize
263   *          The number of beans to return per page.
264   * @return The PagedList
265   */
266  PagedList<T> findPagedList(int pageIndex, int pageSize);
267
268  /**
269   * Return a PagedList for this query using firstRow and maxRows.
270   * <p>
271   * The benefit of using this over findList() is that it provides functionality to get the
272   * total row count etc.
273   * </p>
274   * <p>
275   * If maxRows is not set on the query prior to calling findPagedList() then a
276   * PersistenceException is thrown.
277   * </p>
278   *
279   * <pre>{@code
280   *
281   *  PagedList<Order> pagedList = Ebean.find(Order.class)
282   *       .setFirstRow(50)
283   *       .setMaxRows(20)
284   *       .findPagedList();
285   *
286   *       // fetch the total row count in the background
287   *       pagedList.loadRowCount();
288   *
289   *       List<Order> orders = pagedList.getList();
290   *       int totalRowCount = pagedList.getTotalRowCount();
291   *
292   * }</pre>
293   *
294   * @return The PagedList
295   *
296   * @see Query#findPagedList()
297   */
298  PagedList<T> findPagedList();
299
300  /**
301   * Return versions of a @History entity bean.
302   * <p>
303   *   Generally this query is expected to be a find by id or unique predicates query.
304   *   It will execute the query against the history returning the versions of the bean.
305   * </p>
306   */
307  List<Version<T>> findVersions();
308
309  /**
310   * Return versions of a @History entity bean between the 2 timestamps.
311   * <p>
312   *   Generally this query is expected to be a find by id or unique predicates query.
313   *   It will execute the query against the history returning the versions of the bean.
314   * </p>
315   */
316  List<Version<T>> findVersionsBetween(Timestamp start, Timestamp end);
317
318  /**
319   * Add some filter predicate expressions to the many property.
320   */
321  ExpressionList<T> filterMany(String prop);
322
323  /**
324   * Specify specific properties to fetch on the main/root bean (aka partial
325   * object).
326   * 
327   * @see Query#select(String)
328   */
329  Query<T> select(String properties);
330
331  /**
332   * Set whether this query uses DISTINCT.
333   * <p>
334   * The select() clause MUST be specified when setDistinct(true) is set. The reason for this is that
335   * generally ORM queries include the "id" property and this doesn't make sense for distinct queries.
336   * </p>
337   * <pre>{@code
338   *
339   *   List<Customer> customers =
340   *       Ebean.find(Customer.class)
341   *          .setDistinct(true)
342   *          .select("name")     // only select the customer name
343   *          .findList();
344   *
345   * }</pre>
346   */
347  Query<T> setDistinct(boolean distinct);
348
349  /**
350   * Set the first row to fetch.
351   * 
352   * @see Query#setFirstRow(int)
353   */
354  Query<T> setFirstRow(int firstRow);
355
356  /**
357   * Set the maximum number of rows to fetch.
358   * 
359   * @see Query#setMaxRows(int)
360   */
361  Query<T> setMaxRows(int maxRows);
362
363  /**
364   * Set the name of the property which values become the key of a map.
365   * 
366   * @see Query#setMapKey(String)
367   */
368  Query<T> setMapKey(String mapKey);
369
370  /**
371   * Set to true to use the query for executing this query.
372   * 
373   * @see Query#setUseCache(boolean)
374   */
375  Query<T> setUseCache(boolean useCache);
376
377  /**
378   * Set to true to use the query for executing this query.
379   *
380   * @see Query#setUseQueryCache(boolean)
381   */
382  Query<T> setUseQueryCache(boolean useCache);
383
384  /**
385   * Add expressions to the having clause.
386   * <p>
387   * The having clause is only used for queries based on raw sql (via SqlSelect
388   * annotation etc).
389   * </p>
390   */
391  ExpressionList<T> having();
392
393  /**
394   * Add another expression to the where clause.
395   */
396  ExpressionList<T> where();
397
398  /**
399   * Path exists - for the given path in a JSON document.
400   *
401   * <pre>{@code
402   *
403   *   where().jsonExists("content", "path.other")
404   *
405   * }</pre>
406   *
407   * @param propertyName the property that holds a JSON document
408   * @param path the nested path in the JSON document in dot notation
409   */
410  ExpressionList<T> jsonExists(String propertyName, String path);
411
412  /**
413   * Path does not exist - for the given path in a JSON document.
414   *
415   * <pre>{@code
416   *
417   *   where().jsonNotExists("content", "path.other")
418   *
419   * }</pre>
420   *
421   * @param propertyName the property that holds a JSON document
422   * @param path the nested path in the JSON document in dot notation
423   */
424  ExpressionList<T> jsonNotExists(String propertyName, String path);
425
426  /**
427   * Equal to expression for the value at the given path in the JSON document.
428   *
429   * <pre>{@code
430   *
431   *   where().jsonEqualTo("content", "path.other", 34)
432   *
433   * }</pre>
434   *
435   * @param propertyName the property that holds a JSON document
436   * @param path the nested path in the JSON document in dot notation
437   * @param value the value used to test against the document path's value
438   */
439  ExpressionList<T> jsonEqualTo(String propertyName, String path, Object value);
440
441  /**
442   * Not Equal to - for the given path in a JSON document.
443   *
444   * <pre>{@code
445   *
446   *   where().jsonNotEqualTo("content", "path.other", 34)
447   *
448   * }</pre>
449   *
450   * @param propertyName the property that holds a JSON document
451   * @param path the nested path in the JSON document in dot notation
452   * @param value the value used to test against the document path's value
453   */
454  ExpressionList<T> jsonNotEqualTo(String propertyName, String path, Object value);
455
456  /**
457   * Greater than - for the given path in a JSON document.
458   *
459   * <pre>{@code
460   *
461   *   where().jsonGreaterThan("content", "path.other", 34)
462   *
463   * }</pre>
464   */
465  ExpressionList<T> jsonGreaterThan(String propertyName, String path, Object value);
466
467  /**
468   * Greater than or equal to - for the given path in a JSON document.
469   *
470   * <pre>{@code
471   *
472   *   where().jsonGreaterOrEqual("content", "path.other", 34)
473   *
474   * }</pre>
475   */
476  ExpressionList<T> jsonGreaterOrEqual(String propertyName, String path, Object value);
477
478  /**
479   * Less than - for the given path in a JSON document.
480   *
481   * <pre>{@code
482   *
483   *   where().jsonLessThan("content", "path.other", 34)
484   *
485   * }</pre>
486   */
487  ExpressionList<T> jsonLessThan(String propertyName, String path, Object value);
488
489  /**
490   * Less than or equal to - for the given path in a JSON document.
491   *
492   * <pre>{@code
493   *
494   *   where().jsonLessOrEqualTo("content", "path.other", 34)
495   *
496   * }</pre>
497   */
498  ExpressionList<T> jsonLessOrEqualTo(String propertyName, String path, Object value);
499
500  /**
501   * Between - for the given path in a JSON document.
502   *
503   * <pre>{@code
504   *
505   *   where().jsonBetween("content", "orderDate", lowerDateTime, upperDateTime)
506   *
507   * }</pre>
508   */
509  ExpressionList<T> jsonBetween(String propertyName, String path, Object lowerValue, Object upperValue);
510
511  /**
512   * Add an Expression to the list.
513   * <p>
514   * This returns the list so that add() can be chained.
515   * </p>
516   *
517   * <pre>{@code
518   *
519   * Query<Customer> query = Ebean.find(Customer.class);
520   * query.where()
521   *     .like("name","Rob%")
522   *     .eq("status", Customer.ACTIVE);
523   *
524   * List<Customer> list = query.findList();
525   * ...
526   *
527   * }</pre>
528   */
529  ExpressionList<T> add(Expression expr);
530
531  /**
532   * Add a list of Expressions to this ExpressionList.s
533   */
534  ExpressionList<T> addAll(ExpressionList<T> exprList);
535
536  /**
537   * Equal To - property is equal to a given value.
538   */
539  ExpressionList<T> eq(String propertyName, Object value);
540
541  /**
542   * Not Equal To - property not equal to the given value.
543   */
544  ExpressionList<T> ne(String propertyName, Object value);
545
546  /**
547   * Case Insensitive Equal To - property equal to the given value (typically
548   * using a lower() function to make it case insensitive).
549   */
550  ExpressionList<T> ieq(String propertyName, String value);
551
552  /**
553   * Between - property between the two given values.
554   */
555  ExpressionList<T> between(String propertyName, Object value1, Object value2);
556
557  /**
558   * Between - value between the two properties.
559   */
560  ExpressionList<T> betweenProperties(String lowProperty, String highProperty, Object value);
561
562  /**
563   * Greater Than - property greater than the given value.
564   */
565  ExpressionList<T> gt(String propertyName, Object value);
566
567  /**
568   * Greater Than or Equal to - property greater than or equal to the given
569   * value.
570   */
571  ExpressionList<T> ge(String propertyName, Object value);
572
573  /**
574   * Less Than - property less than the given value.
575   */
576  ExpressionList<T> lt(String propertyName, Object value);
577
578  /**
579   * Less Than or Equal to - property less than or equal to the given value.
580   */
581  ExpressionList<T> le(String propertyName, Object value);
582
583  /**
584   * Is Null - property is null.
585   */
586  ExpressionList<T> isNull(String propertyName);
587
588  /**
589   * Is Not Null - property is not null.
590   */
591  ExpressionList<T> isNotNull(String propertyName);
592
593  /**
594   * A "Query By Example" type of expression.
595   * <p>
596   * Pass in an example entity and for each non-null scalar properties an
597   * expression is added.
598   * </p>
599   * <p>
600   * By Default this case sensitive, will ignore numeric zero values and will
601   * use a Like for string values (you must put in your own wildcards).
602   * </p>
603   * <p>
604   * To get control over the options you can create an ExampleExpression and set
605   * those options such as case insensitive etc.
606   * </p>
607   * 
608   * <pre>{@code
609   *
610   * // create an example bean and set the properties
611   * // with the query parameters you want
612   * Customer example = new Customer();
613   * example.setName("Rob%");
614   * example.setNotes("%something%");
615   * 
616   * List&lt;Customer&gt; list = Ebean.find(Customer.class).where()
617   *     // pass the bean into the where() clause
618   *     .exampleLike(example)
619   *     // you can add other expressions to the same query
620   *     .gt("id", 2).findList();
621   * 
622   * }</pre>
623   * 
624   * Similarly you can create an ExampleExpression
625   * 
626   * <pre>{@code
627   *
628   * Customer example = new Customer();
629   * example.setName("Rob%");
630   * example.setNotes("%something%");
631   * 
632   * // create a ExampleExpression with more control
633   * ExampleExpression qbe = new ExampleExpression(example, true, LikeType.EQUAL_TO).includeZeros();
634   * 
635   * List<Customer> list = Ebean.find(Customer.class).where().add(qbe).findList();
636   *
637   * }</pre>
638   */
639  ExpressionList<T> exampleLike(Object example);
640
641  /**
642   * Case insensitive version of {@link #exampleLike(Object)}
643   */
644  ExpressionList<T> iexampleLike(Object example);
645
646  /**
647   * Like - property like value where the value contains the SQL wild card
648   * characters % (percentage) and _ (underscore).
649   */
650  ExpressionList<T> like(String propertyName, String value);
651
652  /**
653   * Case insensitive Like - property like value where the value contains the
654   * SQL wild card characters % (percentage) and _ (underscore). Typically uses
655   * a lower() function to make the expression case insensitive.
656   */
657  ExpressionList<T> ilike(String propertyName, String value);
658
659  /**
660   * Starts With - property like value%.
661   */
662  ExpressionList<T> startsWith(String propertyName, String value);
663
664  /**
665   * Case insensitive Starts With - property like value%. Typically uses a
666   * lower() function to make the expression case insensitive.
667   */
668  ExpressionList<T> istartsWith(String propertyName, String value);
669
670  /**
671   * Ends With - property like %value.
672   */
673  ExpressionList<T> endsWith(String propertyName, String value);
674
675  /**
676   * Case insensitive Ends With - property like %value. Typically uses a lower()
677   * function to make the expression case insensitive.
678   */
679  ExpressionList<T> iendsWith(String propertyName, String value);
680
681  /**
682   * Contains - property like %value%.
683   */
684  ExpressionList<T> contains(String propertyName, String value);
685
686  /**
687   * Case insensitive Contains - property like %value%. Typically uses a lower()
688   * function to make the expression case insensitive.
689   */
690  ExpressionList<T> icontains(String propertyName, String value);
691
692  /**
693   * In - using a subQuery.
694   */
695  ExpressionList<T> in(String propertyName, Query<?> subQuery);
696
697  /**
698   * In - property has a value in the array of values.
699   */
700  ExpressionList<T> in(String propertyName, Object... values);
701
702  /**
703   * In - property has a value in the collection of values.
704   */
705  ExpressionList<T> in(String propertyName, Collection<?> values);
706
707  /**
708   * Not In - property has a value in the array of values.
709   */
710  ExpressionList<T> notIn(String propertyName, Object... values);
711
712  /**
713   * Not In - property has a value in the collection of values.
714   */
715  ExpressionList<T> notIn(String propertyName, Collection<?> values);
716
717  /**
718   * Not In - using a subQuery.
719   */
720  ExpressionList<T> notIn(String propertyName, Query<?> subQuery);
721
722  /**
723   * Exists expression
724   */
725  ExpressionList<T> exists(Query<?> subQuery);
726  
727  /**
728   * Not exists expression
729   */
730  ExpressionList<T> notExists(Query<?> subQuery);
731
732  /**
733   * Id IN a list of id values.
734   */
735  ExpressionList<T> idIn(List<?> idValues);
736
737  /**
738   * Id Equal to - ID property is equal to the value.
739   */
740  ExpressionList<T> idEq(Object value);
741
742  /**
743   * All Equal - Map containing property names and their values.
744   * <p>
745   * Expression where all the property names in the map are equal to the
746   * corresponding value.
747   * </p>
748   * 
749   * @param propertyMap
750   *          a map keyed by property names.
751   */
752  ExpressionList<T> allEq(Map<String, Object> propertyMap);
753
754  /**
755   * Add raw expression with a single parameter.
756   * <p>
757   * The raw expression should contain a single ? at the location of the
758   * parameter.
759   * </p>
760   * <p>
761   * When properties in the clause are fully qualified as table-column names
762   * then they are not translated. logical property name names (not fully
763   * qualified) will still be translated to their physical name.
764   * </p>
765   *
766   * <h4>Example:</h4>
767   * <pre>{@code
768   *
769   *   // use a database function
770   *   raw("add_days(orderDate, 10) < ?", someDate)
771   *
772   * }</pre>
773   */
774  ExpressionList<T> raw(String raw, Object value);
775
776  /**
777   * Add raw expression with an array of parameters.
778   * <p>
779   * The raw expression should contain the same number of ? as there are
780   * parameters.
781   * </p>
782   * <p>
783   * When properties in the clause are fully qualified as table-column names
784   * then they are not translated. logical property name names (not fully
785   * qualified) will still be translated to their physical name.
786   * </p>
787   */
788  ExpressionList<T> raw(String raw, Object... values);
789
790  /**
791   * Add raw expression with no parameters.
792   * <p>
793   * When properties in the clause are fully qualified as table-column names
794   * then they are not translated. logical property name names (not fully
795   * qualified) will still be translated to their physical name.
796   * </p>
797   *
798   * <pre>{@code
799   *
800   *   raw("orderQty < shipQty")
801   *
802   * }</pre>
803   */
804  ExpressionList<T> raw(String raw);
805
806  /**
807   * And - join two expressions with a logical and.
808   */
809  ExpressionList<T> and(Expression expOne, Expression expTwo);
810
811  /**
812   * Or - join two expressions with a logical or.
813   */
814  ExpressionList<T> or(Expression expOne, Expression expTwo);
815
816  /**
817   * Negate the expression (prefix it with NOT).
818   */
819  ExpressionList<T> not(Expression exp);
820
821  /**
822   * Return a list of expressions that will be joined by AND's.
823   */
824  Junction<T> conjunction();
825
826  /**
827   * Return a list of expressions that will be joined by OR's.
828   */
829  Junction<T> disjunction();
830
831  /**
832   * End a Conjunction or Disjunction returning the parent expression list.
833   * <p>
834   * Alternatively you can always use where() to return the top level expression
835   * list.
836   * </p>
837   */
838  ExpressionList<T> endJunction();
839
840}