001package io.ebean;
002
003import io.ebean.search.Match;
004import io.ebean.search.MultiMatch;
005import io.ebean.search.TextCommonTerms;
006import io.ebean.search.TextQueryString;
007import io.ebean.search.TextSimple;
008
009import javax.annotation.Nonnull;
010import javax.annotation.Nullable;
011import javax.persistence.NonUniqueResultException;
012import java.sql.Connection;
013import java.sql.Timestamp;
014import java.util.Collection;
015import java.util.List;
016import java.util.Map;
017import java.util.Optional;
018import java.util.Set;
019import java.util.function.Consumer;
020import java.util.function.Predicate;
021
022/**
023 * List of Expressions that make up a where or having clause.
024 * <p>
025 * An ExpressionList is returned from {@link Query#where()}.
026 * </p>
027 * <p>
028 * The ExpressionList has a list of convenience methods that create the standard
029 * expressions and add them to this list.
030 * </p>
031 * <p>
032 * The ExpressionList also duplicates methods that are found on the Query such
033 * as findList() and order(). The purpose of these methods is provide a fluid
034 * API. The upside of this approach is that you can build and execute a query
035 * via chained methods. The down side is that this ExpressionList object has
036 * more methods than you would initially expect (the ones duplicated from
037 * Query).
038 * </p>
039 *
040 * @see Query#where()
041 */
042public interface ExpressionList<T> {
043
044  /**
045   * Return the query that owns this expression list.
046   * <p>
047   * This is a convenience method solely to support a fluid API where the
048   * methods are chained together. Adding expressions returns this expression
049   * list and this method can be used after that to return back the original
050   * query so that further things can be added to it.
051   * </p>
052   */
053  Query<T> query();
054
055  /**
056   * Controls, if paginated queries should always append an 'order by id' statement at the end to
057   * guarantee a deterministic sort result. This may affect performance.
058   * If this is not enabled, and an orderBy is set on the query, it's up to the programmer that
059   * this query provides a deterministic result.
060   */
061  Query<T> orderById(boolean orderById);
062
063  /**
064   * Set the order by clause replacing the existing order by clause if there is
065   * one.
066   * <p>
067   * This follows SQL syntax using commas between each property with the
068   * optional asc and desc keywords representing ascending and descending order
069   * respectively.
070   */
071  ExpressionList<T> order(String orderByClause);
072
073  /**
074   * Set the order by clause replacing the existing order by clause if there is
075   * one.
076   * <p>
077   * This follows SQL syntax using commas between each property with the
078   * optional asc and desc keywords representing ascending and descending order
079   * respectively.
080   */
081  ExpressionList<T> orderBy(String orderBy);
082
083  /**
084   * Return the OrderBy so that you can append an ascending or descending
085   * property to the order by clause.
086   * <p>
087   * This will never return a null. If no order by clause exists then an 'empty'
088   * OrderBy object is returned.
089   * <p>
090   * This is the same as <code>orderBy()</code>
091   */
092  OrderBy<T> order();
093
094  /**
095   * Return the OrderBy so that you can append an ascending or descending
096   * property to the order by clause.
097   * <p>
098   * This will never return a null. If no order by clause exists then an 'empty'
099   * OrderBy object is returned.
100   * <p>
101   * This is the same as <code>order()</code>
102   */
103  OrderBy<T> orderBy();
104
105  /**
106   * Deprecated migrate to {@link #orderBy(String)}
107   */
108  @Deprecated
109  Query<T> setOrderBy(String orderBy);
110
111  /**
112   * Apply the path properties to the query replacing the select and fetch clauses.
113   */
114  Query<T> apply(FetchPath fetchPath);
115
116  /**
117   * Perform an 'As of' query using history tables to return the object graph
118   * as of a time in the past.
119   * <p>
120   * To perform this query the DB must have underlying history tables.
121   * </p>
122   *
123   * @param asOf the date time in the past at which you want to view the data
124   */
125  Query<T> asOf(Timestamp asOf);
126
127  /**
128   * Execute the query against the draft set of tables.
129   */
130  Query<T> asDraft();
131
132  /**
133   * Convert the query to a DTO bean query.
134   * <p>
135   * We effectively use the underlying ORM query to build the SQL and then execute
136   * and map it into DTO beans.
137   */
138  <D> DtoQuery<D> asDto(Class<D> dtoClass);
139
140  /**
141   * Return the underlying query as an UpdateQuery.
142   * <p>
143   * Typically this is used with query beans to covert a query bean
144   * query into an UpdateQuery like the examples below.
145   * </p>
146   *
147   * <pre>{@code
148   *
149   *  int rowsUpdated = new QCustomer()
150   *       .name.startsWith("Rob")
151   *       .asUpdate()
152   *       .set("active", false)
153   *       .update();;
154   *
155   * }</pre>
156   *
157   * <pre>{@code
158   *
159   *   int rowsUpdated = new QContact()
160   *       .notes.note.startsWith("Make Inactive")
161   *       .email.endsWith("@foo.com")
162   *       .customer.id.equalTo(42)
163   *       .asUpdate()
164   *       .set("inactive", true)
165   *       .setRaw("email = lower(email)")
166   *       .update();
167   *
168   * }</pre>
169   */
170  UpdateQuery<T> asUpdate();
171
172  /**
173   * Execute using "for update" clause which results in the DB locking the record.
174   */
175  Query<T> forUpdate();
176
177  /**
178   * Execute using "for update" clause with No Wait option.
179   * <p>
180   * This is typically a Postgres and Oracle only option at this stage.
181   * </p>
182   */
183  Query<T> forUpdateNoWait();
184
185  /**
186   * Execute using "for update" clause with Skip Locked option.
187   * <p>
188   * This is typically a Postgres and Oracle only option at this stage.
189   * </p>
190   */
191  Query<T> forUpdateSkipLocked();
192
193  /**
194   * Execute the query including soft deleted rows.
195   */
196  Query<T> setIncludeSoftDeletes();
197
198  /**
199   * Execute the query using the given transaction.
200   */
201  Query<T> usingTransaction(Transaction transaction);
202
203  /**
204   * Execute the query using the given connection.
205   */
206  Query<T> usingConnection(Connection connection);
207
208  /**
209   * Execute as a delete query deleting the 'root level' beans that match the predicates
210   * in the query.
211   * <p>
212   * Note that if the query includes joins then the generated delete statement may not be
213   * optimal depending on the database platform.
214   * </p>
215   *
216   * @return the number of rows that were deleted.
217   */
218  int delete();
219
220  /**
221   * Execute as a delete query deleting the 'root level' beans that match the predicates
222   * in the query.
223   * <p>
224   * Note that if the query includes joins then the generated delete statement may not be
225   * optimal depending on the database platform.
226   * </p>
227   *
228   * @return the number of rows that were deleted.
229   */
230  int delete(Transaction transaction);
231
232  /**
233   * Execute as a update query.
234   *
235   * @return the number of rows that were updated.
236   * @see UpdateQuery
237   */
238  int update();
239
240  /**
241   * Execute as a update query with the given transaction.
242   *
243   * @return the number of rows that were updated.
244   * @see UpdateQuery
245   */
246  int update(Transaction transaction);
247
248  /**
249   * Execute the query returning true if a row is found.
250   * <p>
251   * The query is executed using max rows of 1 and will only select the id property.
252   * This method is really just a convenient way to optimise a query to perform a
253   * 'does a row exist in the db' check.
254   * </p>
255   *
256   * <h2>Example:</h2>
257   * <pre>{@code
258   *
259   *   boolean userExists = query().where().eq("email", "[email protected]").exists();
260   *
261   * }</pre>
262   *
263   * <h2>Example using a query bean:</h2>
264   * <pre>{@code
265   *
266   *   boolean userExists = new QContact().email.equalTo("[email protected]").exists();
267   *
268   * }</pre>
269   *
270   * @return True if the query finds a matching row in the database
271   */
272  boolean exists();
273
274  /**
275   * Execute the query iterating over the results.
276   *
277   * @see Query#findIterate()
278   */
279  QueryIterator<T> findIterate();
280
281  /**
282   * Execute the query process the beans one at a time.
283   *
284   * @see Query#findEach(Consumer)
285   */
286  void findEach(Consumer<T> consumer);
287
288  /**
289   * Execute the query processing the beans one at a time with the ability to
290   * stop processing before reading all the beans.
291   *
292   * @see Query#findEachWhile(Predicate)
293   */
294  void findEachWhile(Predicate<T> consumer);
295
296  /**
297   * Execute the query returning a list.
298   *
299   * @see Query#findList()
300   */
301  @Nonnull
302  List<T> findList();
303
304  /**
305   * Execute the query returning the list of Id's.
306   *
307   * @see Query#findIds()
308   */
309  @Nonnull
310  <A> List<A> findIds();
311
312  /**
313   * Return the count of entities this query should return.
314   * <p>
315   * This is the number of 'top level' or 'root level' entities.
316   * </p>
317   */
318  int findCount();
319
320  /**
321   * Execute the query returning a set.
322   *
323   * @see Query#findSet()
324   */
325  @Nonnull
326  Set<T> findSet();
327
328  /**
329   * Execute the query returning a map.
330   *
331   * @see Query#findMap()
332   */
333  @Nonnull
334  <K> Map<K, T> findMap();
335
336  /**
337   * Execute the query returning a list of values for a single property.
338   *
339   * <h3>Example 1:</h3>
340   * <pre>{@code
341   *
342   *  List<String> names =
343   *    DB.find(Customer.class)
344   *      .select("name")
345   *      .order().asc("name")
346   *      .findSingleAttributeList();
347   *
348   * }</pre>
349   *
350   * <h3>Example 2:</h3>
351   * <pre>{@code
352   *
353   *  List<String> names =
354   *    DB.find(Customer.class)
355   *      .setDistinct(true)
356   *      .select("name")
357   *      .where().eq("status", Customer.Status.NEW)
358   *      .order().asc("name")
359   *      .setMaxRows(100)
360   *      .findSingleAttributeList();
361   *
362   * }</pre>
363   *
364   * @return the list of values for the selected property
365   */
366  @Nonnull
367  <A> List<A> findSingleAttributeList();
368
369  /**
370   * Execute a query returning a single value of a single property/column.
371   * <pre>{@code
372   *
373   *  String name =
374   *    DB.find(Customer.class)
375   *      .select("name")
376   *      .where().eq("id", 42)
377   *      .findSingleAttribute();
378   *
379   * }</pre>
380   */
381  default <A> A findSingleAttribute() {
382    List<A> list = findSingleAttributeList();
383    return !list.isEmpty() ? list.get(0) : null;
384  }
385
386  /**
387   * Execute the query returning a single bean or null (if no matching
388   * bean is found).
389   * <p>
390   * If more than 1 row is found for this query then a NonUniqueResultException is
391   * thrown.
392   * </p>
393   *
394   * @throws NonUniqueResultException if more than one result was found
395   * @see Query#findOne()
396   */
397  @Nullable
398  T findOne();
399
400  /**
401   * Execute the query returning an optional bean.
402   */
403  @Nonnull
404  Optional<T> findOneOrEmpty();
405
406  /**
407   * Execute find row count query in a background thread.
408   * <p>
409   * This returns a Future object which can be used to cancel, check the
410   * execution status (isDone etc) and get the value (with or without a
411   * timeout).
412   * </p>
413   *
414   * @return a Future object for the row count query
415   */
416  @Nonnull
417  FutureRowCount<T> findFutureCount();
418
419  /**
420   * Execute find Id's query in a background thread.
421   * <p>
422   * This returns a Future object which can be used to cancel, check the
423   * execution status (isDone etc) and get the value (with or without a
424   * timeout).
425   * </p>
426   *
427   * @return a Future object for the list of Id's
428   */
429  @Nonnull
430  FutureIds<T> findFutureIds();
431
432  /**
433   * Execute find list query in a background thread.
434   * <p>
435   * This returns a Future object which can be used to cancel, check the
436   * execution status (isDone etc) and get the value (with or without a
437   * timeout).
438   * </p>
439   *
440   * @return a Future object for the list result of the query
441   */
442  @Nonnull
443  FutureList<T> findFutureList();
444
445  /**
446   * Return a PagedList for this query using firstRow and maxRows.
447   * <p>
448   * The benefit of using this over findList() is that it provides functionality to get the
449   * total row count etc.
450   * </p>
451   * <p>
452   * If maxRows is not set on the query prior to calling findPagedList() then a
453   * PersistenceException is thrown.
454   * </p>
455   * <pre>{@code
456   *
457   *  PagedList<Order> pagedList = DB.find(Order.class)
458   *       .setFirstRow(50)
459   *       .setMaxRows(20)
460   *       .findPagedList();
461   *
462   *       // fetch the total row count in the background
463   *       pagedList.loadRowCount();
464   *
465   *       List<Order> orders = pagedList.getList();
466   *       int totalRowCount = pagedList.getTotalRowCount();
467   *
468   * }</pre>
469   *
470   * @return The PagedList
471   * @see Query#findPagedList()
472   */
473  @Nonnull
474  PagedList<T> findPagedList();
475
476  /**
477   * Return versions of a @History entity bean.
478   * <p>
479   * Generally this query is expected to be a find by id or unique predicates query.
480   * It will execute the query against the history returning the versions of the bean.
481   * </p>
482   */
483  @Nonnull
484  List<Version<T>> findVersions();
485
486  /**
487   * Return versions of a @History entity bean between the 2 timestamps.
488   * <p>
489   * Generally this query is expected to be a find by id or unique predicates query.
490   * It will execute the query against the history returning the versions of the bean.
491   * </p>
492   */
493  @Nonnull
494  List<Version<T>> findVersionsBetween(Timestamp start, Timestamp end);
495
496  /**
497   * Add some filter predicate expressions to the many property.
498   */
499  @Nonnull
500  ExpressionList<T> filterMany(String manyProperty);
501
502  /**
503   * Add filter expressions to the many property.
504   *
505   * <pre>{@code
506   *
507   *   DB.find(Customer.class)
508   *   .where()
509   *   .eq("name", "Rob")
510   *   .filterMany("orders", "status = ?", Status.NEW)
511   *   .findList();
512   *
513   * }</pre>
514   *
515   * @param manyProperty The many property
516   * @param expressions  Filter expressions with and, or and ? or ?1 type bind parameters
517   * @param params       Bind parameters used in the expressions
518   */
519  ExpressionList<T> filterMany(String manyProperty, String expressions, Object... params);
520
521  /**
522   * Specify specific properties to fetch on the main/root bean (aka partial
523   * object).
524   *
525   * @see Query#select(String)
526   */
527  Query<T> select(String properties);
528
529  /**
530   * Apply the fetchGroup which defines what part of the object graph to load.
531   */
532  Query<T> select(FetchGroup<T> fetchGroup);
533
534  /**
535   * Set whether this query uses DISTINCT.
536   * <p>
537   * The select() clause MUST be specified when setDistinct(true) is set. The reason for this is that
538   * generally ORM queries include the "id" property and this doesn't make sense for distinct queries.
539   * </p>
540   * <pre>{@code
541   *
542   *   List<Customer> customers =
543   *       DB.find(Customer.class)
544   *          .setDistinct(true)
545   *          .select("name")     // only select the customer name
546   *          .findList();
547   *
548   * }</pre>
549   */
550  Query<T> setDistinct(boolean distinct);
551
552  /**
553   * Set the index(es) to search for a document store which uses partitions.
554   * <p>
555   * For example, when executing a query against ElasticSearch with daily indexes we can
556   * explicitly specify the indexes to search against.
557   * </p>
558   *
559   * @param indexName The index or indexes to search against
560   * @return This query
561   * @see Query#setDocIndexName(String)
562   */
563  Query<T> setDocIndexName(String indexName);
564
565  /**
566   * Set the first row to fetch.
567   *
568   * @see Query#setFirstRow(int)
569   */
570  ExpressionList<T> setFirstRow(int firstRow);
571
572  /**
573   * Set the maximum number of rows to fetch.
574   *
575   * @see Query#setMaxRows(int)
576   */
577  ExpressionList<T> setMaxRows(int maxRows);
578
579  /**
580   * Set the name of the property which values become the key of a map.
581   *
582   * @see Query#setMapKey(String)
583   */
584  Query<T> setMapKey(String mapKey);
585
586  /**
587   * Set to true when this query should use the bean cache.
588   * <p>
589   * This is now the same as setUseBeanCache(CacheMode.ON) and will be deprecated.
590   * </p>
591   *
592   * @see Query#setUseCache(boolean)
593   */
594  Query<T> setUseCache(boolean useCache);
595
596  /**
597   * Set the mode to use the bean cache when executing this query.
598   *
599   * @see Query#setBeanCacheMode(CacheMode)
600   */
601  Query<T> setBeanCacheMode(CacheMode beanCacheMode);
602
603  /**
604   * Set the {@link CacheMode} to use the query cache for executing this query.
605   *
606   * @see Query#setUseQueryCache(boolean)
607   */
608  Query<T> setUseQueryCache(CacheMode useCache);
609
610  /**
611   * Extended version for setDistinct in conjunction with "findSingleAttributeList";
612   * <pre>{@code
613   *
614   *  List<CountedValue<Order.Status>> orderStatusCount =
615   *
616   *     DB.find(Order.class)
617   *      .select("status")
618   *      .where()
619   *      .gt("orderDate", LocalDate.now().minusMonths(3))
620   *
621   *      // fetch as single attribute with a COUNT
622   *      .setCountDistinct(CountDistinctOrder.COUNT_DESC_ATTR_ASC)
623   *      .findSingleAttributeList();
624   *
625   *     for (CountedValue<Order.Status> entry : orderStatusCount) {
626   *       System.out.println(" count:" + entry.getCount()+" orderStatus:" + entry.getValue() );
627   *     }
628   *
629   *   // produces
630   *
631   *   count:3 orderStatus:NEW
632   *   count:1 orderStatus:SHIPPED
633   *   count:1 orderStatus:COMPLETE
634   *
635   * }</pre>
636   */
637  Query<T> setCountDistinct(CountDistinctOrder orderBy);
638
639  /**
640   * Calls {@link #setUseQueryCache(CacheMode)} with <code>ON</code> or <code>OFF</code>.
641   *
642   * @see Query#setUseQueryCache(CacheMode)
643   */
644  default Query<T> setUseQueryCache(boolean enabled) {
645    return setUseQueryCache(enabled ? CacheMode.ON : CacheMode.OFF);
646  }
647
648  /**
649   * Set to true if this query should execute against the doc store.
650   * <p>
651   * When setting this you may also consider disabling lazy loading.
652   * </p>
653   */
654  Query<T> setUseDocStore(boolean useDocsStore);
655
656  /**
657   * Set true if you want to disable lazy loading.
658   * <p>
659   * That is, once the object graph is returned further lazy loading is disabled.
660   * </p>
661   */
662  Query<T> setDisableLazyLoading(boolean disableLazyLoading);
663
664  /**
665   * Disable read auditing for this query.
666   * <p>
667   * This is intended to be used when the query is not a user initiated query and instead
668   * part of the internal processing in an application to load a cache or document store etc.
669   * In these cases we don't want the query to be part of read auditing.
670   * </p>
671   */
672  Query<T> setDisableReadAuditing();
673
674  /**
675   * Set a label on the query (to help identify query execution statistics).
676   */
677  Query<T> setLabel(String label);
678
679  /**
680   * Add expressions to the having clause.
681   * <p>
682   * The having clause is only used for queries based on raw sql (via SqlSelect
683   * annotation etc).
684   * </p>
685   */
686  ExpressionList<T> having();
687
688  /**
689   * Add another expression to the where clause.
690   */
691  ExpressionList<T> where();
692
693  /**
694   * Add the expressions to this expression list.
695   *
696   * @param expressions The expressions that are parsed and added to this expression list
697   * @param params      Bind parameters to match ? or ?1 bind positions.
698   */
699  ExpressionList<T> where(String expressions, Object... params);
700
701  /**
702   * Path exists - for the given path in a JSON document.
703   * <pre>{@code
704   *
705   *   where().jsonExists("content", "path.other")
706   *
707   * }</pre>
708   *
709   * @param propertyName the property that holds a JSON document
710   * @param path         the nested path in the JSON document in dot notation
711   */
712  ExpressionList<T> jsonExists(String propertyName, String path);
713
714  /**
715   * Path does not exist - for the given path in a JSON document.
716   * <pre>{@code
717   *
718   *   where().jsonNotExists("content", "path.other")
719   *
720   * }</pre>
721   *
722   * @param propertyName the property that holds a JSON document
723   * @param path         the nested path in the JSON document in dot notation
724   */
725  ExpressionList<T> jsonNotExists(String propertyName, String path);
726
727  /**
728   * Equal to expression for the value at the given path in the JSON document.
729   * <pre>{@code
730   *
731   *   where().jsonEqualTo("content", "path.other", 34)
732   *
733   * }</pre>
734   *
735   * @param propertyName the property that holds a JSON document
736   * @param path         the nested path in the JSON document in dot notation
737   * @param value        the value used to test against the document path's value
738   */
739  ExpressionList<T> jsonEqualTo(String propertyName, String path, Object value);
740
741  /**
742   * Not Equal to - for the given path in a JSON document.
743   * <pre>{@code
744   *
745   *   where().jsonNotEqualTo("content", "path.other", 34)
746   *
747   * }</pre>
748   *
749   * @param propertyName the property that holds a JSON document
750   * @param path         the nested path in the JSON document in dot notation
751   * @param value        the value used to test against the document path's value
752   */
753  ExpressionList<T> jsonNotEqualTo(String propertyName, String path, Object value);
754
755  /**
756   * Greater than - for the given path in a JSON document.
757   * <pre>{@code
758   *
759   *   where().jsonGreaterThan("content", "path.other", 34)
760   *
761   * }</pre>
762   */
763  ExpressionList<T> jsonGreaterThan(String propertyName, String path, Object value);
764
765  /**
766   * Greater than or equal to - for the given path in a JSON document.
767   * <pre>{@code
768   *
769   *   where().jsonGreaterOrEqual("content", "path.other", 34)
770   *
771   * }</pre>
772   */
773  ExpressionList<T> jsonGreaterOrEqual(String propertyName, String path, Object value);
774
775  /**
776   * Less than - for the given path in a JSON document.
777   * <pre>{@code
778   *
779   *   where().jsonLessThan("content", "path.other", 34)
780   *
781   * }</pre>
782   */
783  ExpressionList<T> jsonLessThan(String propertyName, String path, Object value);
784
785  /**
786   * Less than or equal to - for the given path in a JSON document.
787   * <pre>{@code
788   *
789   *   where().jsonLessOrEqualTo("content", "path.other", 34)
790   *
791   * }</pre>
792   */
793  ExpressionList<T> jsonLessOrEqualTo(String propertyName, String path, Object value);
794
795  /**
796   * Between - for the given path in a JSON document.
797   * <pre>{@code
798   *
799   *   where().jsonBetween("content", "orderDate", lowerDateTime, upperDateTime)
800   *
801   * }</pre>
802   */
803  ExpressionList<T> jsonBetween(String propertyName, String path, Object lowerValue, Object upperValue);
804
805  /**
806   * Add an Expression to the list.
807   */
808  ExpressionList<T> add(Expression expr);
809
810  /**
811   * Add a list of Expressions to this ExpressionList.s
812   */
813  ExpressionList<T> addAll(ExpressionList<T> exprList);
814
815  /**
816   * Equal To - property is equal to a given value.
817   */
818  ExpressionList<T> eq(String propertyName, Object value);
819
820  /**
821   * Equal To or Null - property is equal to a given value or null.
822   */
823  ExpressionList<T> eqOrNull(String propertyName, Object value);
824
825  /**
826   * Not Equal To - property not equal to the given value.
827   */
828  ExpressionList<T> ne(String propertyName, Object value);
829
830  /**
831   * Case Insensitive Equal To - property equal to the given value (typically
832   * using a lower() function to make it case insensitive).
833   */
834  ExpressionList<T> ieq(String propertyName, String value);
835
836  /**
837   * Case Insensitive Not Equal To - property not equal to the given value (typically
838   * using a lower() function to make it case insensitive).
839   */
840  ExpressionList<T> ine(String propertyName, String value);
841
842  /**
843   * Value in Range between 2 properties.
844   *
845   * <pre>{@code
846   *
847   *    .startDate.inRangeWith(endDate, now)
848   *
849   *    // which equates to
850   *    startDate <= now and (endDate > now or endDate is null)
851   *
852   * }</pre>
853   *
854   * <p>
855   * This is a convenience expression combining a number of simple expressions.
856   * The most common use of this could be called "effective dating" where 2 date or
857   * timestamp columns represent the date range in which
858   */
859  ExpressionList<T> inRangeWith(String lowProperty, String highProperty, Object value);
860
861  /**
862   * In Range - {@code property >= value1 and property < value2}.
863   * <p>
864   * Unlike Between inRange is "half open" and usually more useful for use with dates or timestamps.
865   * </p>
866   */
867  ExpressionList<T> inRange(String propertyName, Object value1, Object value2);
868
869  /**
870   * Between - property between the two given values.
871   */
872  ExpressionList<T> between(String propertyName, Object value1, Object value2);
873
874  /**
875   * Between - value between the two properties.
876   */
877  ExpressionList<T> betweenProperties(String lowProperty, String highProperty, Object value);
878
879  /**
880   * Greater Than - property greater than the given value.
881   */
882  ExpressionList<T> gt(String propertyName, Object value);
883
884  /**
885   * Greater Than or Null - property greater than the given value or null.
886   */
887  ExpressionList<T> gtOrNull(String propertyName, Object value);
888
889  /**
890   * Greater Than or Equal to OR Null - <code> >= or null </code>.
891   */
892  ExpressionList<T> geOrNull(String propertyName, Object value);
893
894  /**
895   * Greater Than or Equal to - property greater than or equal to the given
896   * value.
897   */
898  ExpressionList<T> ge(String propertyName, Object value);
899
900  /**
901   * Less Than - property less than the given value.
902   */
903  ExpressionList<T> lt(String propertyName, Object value);
904
905  /**
906   * Less Than or Null - property less than the given value or null.
907   */
908  ExpressionList<T> ltOrNull(String propertyName, Object value);
909
910  /**
911   * Less Than or Equal to OR Null - <code> <= or null </code>.
912   */
913  ExpressionList<T> leOrNull(String propertyName, Object value);
914
915  /**
916   * Less Than or Equal to - property less than or equal to the given value.
917   */
918  ExpressionList<T> le(String propertyName, Object value);
919
920  /**
921   * Is Null - property is null.
922   */
923  ExpressionList<T> isNull(String propertyName);
924
925  /**
926   * Is Not Null - property is not null.
927   */
928  ExpressionList<T> isNotNull(String propertyName);
929
930  /**
931   * A "Query By Example" type of expression.
932   * <p>
933   * Pass in an example entity and for each non-null scalar properties an
934   * expression is added.
935   * </p>
936   * <p>
937   * By Default this case sensitive, will ignore numeric zero values and will
938   * use a Like for string values (you must put in your own wildcards).
939   * </p>
940   * <p>
941   * To get control over the options you can create an ExampleExpression and set
942   * those options such as case insensitive etc.
943   * </p>
944   * <pre>{@code
945   *
946   * // create an example bean and set the properties
947   * // with the query parameters you want
948   * Customer example = new Customer();
949   * example.setName("Rob%");
950   * example.setNotes("%something%");
951   *
952   * List<Customer> list =
953   *   DB.find(Customer.class)
954   *     .where().exampleLike(example)
955   *     .findList();
956   *
957   * }</pre>
958   * <p>
959   * Similarly you can create an ExampleExpression
960   * </p>
961   * <pre>{@code
962   *
963   * Customer example = new Customer();
964   * example.setName("Rob%");
965   * example.setNotes("%something%");
966   *
967   * // create a ExampleExpression with more control
968   * ExampleExpression qbe = new ExampleExpression(example, true, LikeType.EQUAL_TO).includeZeros();
969   *
970   * List<Customer> list = DB.find(Customer.class).where().add(qbe).findList();
971   *
972   * }</pre>
973   */
974  ExpressionList<T> exampleLike(Object example);
975
976  /**
977   * Case insensitive version of {@link #exampleLike(Object)}
978   */
979  ExpressionList<T> iexampleLike(Object example);
980
981  /**
982   * Like - property like value where the value contains the SQL wild card
983   * characters % (percentage) and _ (underscore).
984   */
985  ExpressionList<T> like(String propertyName, String value);
986
987  /**
988   * Case insensitive Like - property like value where the value contains the
989   * SQL wild card characters % (percentage) and _ (underscore). Typically uses
990   * a lower() function to make the expression case insensitive.
991   */
992  ExpressionList<T> ilike(String propertyName, String value);
993
994  /**
995   * Starts With - property like value%.
996   */
997  ExpressionList<T> startsWith(String propertyName, String value);
998
999  /**
1000   * Case insensitive Starts With - property like value%. Typically uses a
1001   * lower() function to make the expression case insensitive.
1002   */
1003  ExpressionList<T> istartsWith(String propertyName, String value);
1004
1005  /**
1006   * Ends With - property like %value.
1007   */
1008  ExpressionList<T> endsWith(String propertyName, String value);
1009
1010  /**
1011   * Case insensitive Ends With - property like %value. Typically uses a lower()
1012   * function to make the expression case insensitive.
1013   */
1014  ExpressionList<T> iendsWith(String propertyName, String value);
1015
1016  /**
1017   * Contains - property like %value%.
1018   */
1019  ExpressionList<T> contains(String propertyName, String value);
1020
1021  /**
1022   * Case insensitive Contains - property like %value%. Typically uses a lower()
1023   * function to make the expression case insensitive.
1024   */
1025  ExpressionList<T> icontains(String propertyName, String value);
1026
1027  /**
1028   * In expression using pairs of value objects.
1029   */
1030  ExpressionList<T> inPairs(Pairs pairs);
1031
1032  /**
1033   * In - using a subQuery.
1034   */
1035  ExpressionList<T> in(String propertyName, Query<?> subQuery);
1036
1037  /**
1038   * In - property has a value in the array of values.
1039   */
1040  ExpressionList<T> in(String propertyName, Object... values);
1041
1042  /**
1043   * In - property has a value in the collection of values.
1044   */
1045  ExpressionList<T> in(String propertyName, Collection<?> values);
1046
1047  /**
1048   * In where null or empty values means that no predicate is added to the query.
1049   * <p>
1050   * That is, only add the IN predicate if the values are not null or empty.
1051   * <p>
1052   * Without this we typically need to code an <code>if</code> block to only add
1053   * the IN predicate if the collection is not empty like:
1054   * </p>
1055   *
1056   * <h3>Without inOrEmpty()</h3>
1057   * <pre>{@code
1058   *
1059   *   query.where() // add some predicates
1060   *     .eq("status", Status.NEW);
1061   *
1062   *   if (ids != null && !ids.isEmpty()) {
1063   *     query.where().in("customer.id", ids);
1064   *   }
1065   *
1066   *   query.findList();
1067   *
1068   * }</pre>
1069   *
1070   * <h3>Using inOrEmpty()</h3>
1071   * <pre>{@code
1072   *
1073   *   query.where()
1074   *     .eq("status", Status.NEW)
1075   *     .inOrEmpty("customer.id", ids)
1076   *     .findList();
1077   *
1078   * }</pre>
1079   */
1080  ExpressionList<T> inOrEmpty(String propertyName, Collection<?> values);
1081
1082  /**
1083   * In - using a subQuery.
1084   * <p>
1085   * This is exactly the same as in() and provided due to "in" being a Kotlin keyword
1086   * (and hence to avoid the slightly ugly escaping when using in() in Kotlin)
1087   */
1088  default ExpressionList<T> isIn(String propertyName, Query<?> subQuery) {
1089    return in(propertyName, subQuery);
1090  }
1091
1092  /**
1093   * In - property has a value in the array of values.
1094   * <p>
1095   * This is exactly the same as in() and provided due to "in" being a Kotlin keyword
1096   * (and hence to avoid the slightly ugly escaping when using in() in Kotlin)
1097   */
1098  default ExpressionList<T> isIn(String propertyName, Object... values) {
1099    return in(propertyName, values);
1100  }
1101
1102  /**
1103   * In - property has a value in the collection of values.
1104   * <p>
1105   * This is exactly the same as in() and provided due to "in" being a Kotlin keyword
1106   * (and hence to avoid the slightly ugly escaping when using in() in Kotlin)
1107   */
1108  default ExpressionList<T> isIn(String propertyName, Collection<?> values) {
1109    return in(propertyName, values);
1110  }
1111
1112  /**
1113   * Not In - property has a value in the array of values.
1114   */
1115  ExpressionList<T> notIn(String propertyName, Object... values);
1116
1117  /**
1118   * Not In - property has a value in the collection of values.
1119   */
1120  ExpressionList<T> notIn(String propertyName, Collection<?> values);
1121
1122  /**
1123   * Not In - using a subQuery.
1124   */
1125  ExpressionList<T> notIn(String propertyName, Query<?> subQuery);
1126
1127  /**
1128   * Is empty expression for collection properties.
1129   */
1130  ExpressionList<T> isEmpty(String propertyName);
1131
1132  /**
1133   * Is not empty expression for collection properties.
1134   */
1135  ExpressionList<T> isNotEmpty(String propertyName);
1136
1137  /**
1138   * Exists expression
1139   */
1140  ExpressionList<T> exists(Query<?> subQuery);
1141
1142  /**
1143   * Not exists expression
1144   */
1145  ExpressionList<T> notExists(Query<?> subQuery);
1146
1147  /**
1148   * Id IN a list of id values.
1149   */
1150  ExpressionList<T> idIn(Object... idValues);
1151
1152  /**
1153   * Id IN a collection of id values.
1154   */
1155  ExpressionList<T> idIn(Collection<?> idValues);
1156
1157  /**
1158   * Id Equal to - ID property is equal to the value.
1159   */
1160  ExpressionList<T> idEq(Object value);
1161
1162  /**
1163   * All Equal - Map containing property names and their values.
1164   * <p>
1165   * Expression where all the property names in the map are equal to the
1166   * corresponding value.
1167   * </p>
1168   *
1169   * @param propertyMap a map keyed by property names.
1170   */
1171  ExpressionList<T> allEq(Map<String, Object> propertyMap);
1172
1173  /**
1174   * Array property contains entries with the given values.
1175   */
1176  ExpressionList<T> arrayContains(String propertyName, Object... values);
1177
1178  /**
1179   * Array does not contain the given values.
1180   * <p>
1181   * Array support is effectively limited to Postgres at this time.
1182   * </p>
1183   */
1184  ExpressionList<T> arrayNotContains(String propertyName, Object... values);
1185
1186  /**
1187   * Array is empty - for the given array property.
1188   * <p>
1189   * Array support is effectively limited to Postgres at this time.
1190   * </p>
1191   */
1192  ExpressionList<T> arrayIsEmpty(String propertyName);
1193
1194  /**
1195   * Array is not empty - for the given array property.
1196   * <p>
1197   * Array support is effectively limited to Postgres at this time.
1198   * </p>
1199   */
1200  ExpressionList<T> arrayIsNotEmpty(String propertyName);
1201
1202  /**
1203   * Add expression for ANY of the given bit flags to be set.
1204   * <pre>{@code
1205   *
1206   * where().bitwiseAny("flags", BwFlags.HAS_BULK + BwFlags.HAS_COLOUR)
1207   *
1208   * }</pre>
1209   *
1210   * @param propertyName The property that holds the flags value
1211   * @param flags        The flags we are looking for
1212   */
1213  ExpressionList<T> bitwiseAny(String propertyName, long flags);
1214
1215  /**
1216   * Add expression for ALL of the given bit flags to be set.
1217   * <pre>{@code
1218   *
1219   * where().bitwiseAll("flags", BwFlags.HAS_BULK + BwFlags.HAS_COLOUR)
1220   *
1221   * }</pre>
1222   *
1223   * @param propertyName The property that holds the flags value
1224   * @param flags        The flags we are looking for
1225   */
1226  ExpressionList<T> bitwiseAll(String propertyName, long flags);
1227
1228  /**
1229   * Add expression for the given bit flags to be NOT set.
1230   * <pre>{@code
1231   *
1232   * where().bitwiseNot("flags", BwFlags.HAS_COLOUR)
1233   *
1234   * }</pre>
1235   *
1236   * @param propertyName The property that holds the flags value
1237   * @param flags        The flags we are looking for
1238   */
1239  ExpressionList<T> bitwiseNot(String propertyName, long flags);
1240
1241  /**
1242   * Add bitwise AND expression of the given bit flags to compare with the match/mask.
1243   * <p>
1244   * <pre>{@code
1245   *
1246   * // Flags Bulk + Size = Size
1247   * // ... meaning Bulk is not set and Size is set
1248   *
1249   * long selectedFlags = BwFlags.HAS_BULK + BwFlags.HAS_SIZE;
1250   * long mask = BwFlags.HAS_SIZE; // Only Size flag set
1251   *
1252   * where().bitwiseAnd("flags", selectedFlags, mask)
1253   *
1254   * }</pre>
1255   *
1256   * @param propertyName The property that holds the flags value
1257   * @param flags        The flags we are looking for
1258   */
1259  ExpressionList<T> bitwiseAnd(String propertyName, long flags, long match);
1260
1261  /**
1262   * Add raw expression with a single parameter.
1263   * <p>
1264   * The raw expression should contain a single ? or ?1
1265   * at the location of the parameter.  We use ?1 when binding a
1266   * collection for an IN expression.
1267   * <p>
1268   * When properties in the clause are fully qualified as table-column names
1269   * then they are not translated. logical property name names (not fully
1270   * qualified) will still be translated to their physical name.
1271   * <p>
1272   * <h4>Examples:</h4>
1273   * <pre>{@code
1274   *
1275   *   // use a database function
1276   *   raw("add_days(orderDate, 10) < ?", someDate)
1277   *
1278   *   raw("name like ?", "Rob%")
1279   *
1280   *   raw("name in (?1)", asList("Rob", "Fiona", "Jack"))
1281   *
1282   *   raw("name = any(?)", asList("Rob", "Fiona", "Jack"))
1283   *
1284   * }</pre>
1285   *
1286   * <h4>Subquery examples:</h4>
1287   * <pre>{@code
1288   *
1289   *   // Bind collection using ?1
1290   *   .raw("id in (select c.id from o_customer c where c.name in (?1))", asList("Rob", "Fiona", "Jack"))
1291   *
1292   *   // Using Postgres ANY expression
1293   *   .raw("t0.customer_id in (select customer_id from customer_group where group_id = any(?::uuid[]))", groupIds)
1294   *
1295   * }</pre>
1296   */
1297  ExpressionList<T> raw(String raw, Object value);
1298
1299  /**
1300   * Add raw expression with an array of parameters.
1301   * <p>
1302   * The raw expression should contain the same number of ? or ?1, ?2 ... bind parameters
1303   * as there are values. We use ?1, ?2 etc when binding a collection for an IN expression.
1304   * <p>
1305   * When properties in the clause are fully qualified as table-column names
1306   * then they are not translated. logical property name names (not fully
1307   * qualified) will still be translated to their physical name.
1308   * </p>
1309   *
1310   * <h4>Examples:</h4>
1311   * <pre>{@code
1312   *
1313   *   raw("unitPrice > ? and product.id > ?", 2, 3)
1314   *
1315   *   raw("(status = ? or (orderDate < ? and shipDate is null) or customer.name like ?)",
1316   *         Order.Status.APPROVED,
1317   *         new Timestamp(System.currentTimeMillis()),
1318   *         "Rob")
1319   *
1320   * }</pre></pre>
1321   */
1322  ExpressionList<T> raw(String raw, Object... values);
1323
1324  /**
1325   * Add raw expression with no parameters.
1326   * <p>
1327   * When properties in the clause are fully qualified as table-column names
1328   * then they are not translated. logical property name names (not fully
1329   * qualified) will still be translated to their physical name.
1330   * </p>
1331   * <pre>{@code
1332   *
1333   *   raw("orderQty < shipQty")
1334   *
1335   * }</pre>
1336   *
1337   * <h4>Subquery example:</h4>
1338   * <pre>{@code
1339   *
1340   *   .raw("t0.customer_id in (select customer_id from customer_group where group_id = any(?::uuid[]))", groupIds)
1341   *
1342   * }</pre>
1343   */
1344  ExpressionList<T> raw(String raw);
1345
1346  /**
1347   * Only add the raw expression if the values is not null or empty.
1348   * <p>
1349   * This is a pure convenience expression to make it nicer to deal with the pattern where we use
1350   * raw() expression with a subquery and only want to add the subquery predicate when the collection
1351   * of values is not empty.
1352   * </p>
1353   * <h3>Without inOrEmpty()</h3>
1354   * <pre>{@code
1355   *
1356   *   query.where() // add some predicates
1357   *     .eq("status", Status.NEW);
1358   *
1359   *   // common pattern - we can use rawOrEmpty() instead
1360   *   if (orderIds != null && !orderIds.isEmpty()) {
1361   *     query.where().raw("t0.customer_id in (select o.customer_id from orders o where o.id in (?1))", orderIds);
1362   *   }
1363   *
1364   *   query.findList();
1365   *
1366   * }</pre>
1367   *
1368   * <h3>Using rawOrEmpty()</h3>
1369   * Note that in the example below we use the <code>?1</code> bind parameter to get  "parameter expansion"
1370   * for each element in the collection.
1371   *
1372   * <pre>{@code
1373   *
1374   *   query.where()
1375   *     .eq("status", Status.NEW)
1376   *     // only add the expression if orderIds is not empty
1377   *     .rawOrEmpty("t0.customer_id in (select o.customer_id from orders o where o.id in (?1))", orderIds);
1378   *     .findList();
1379   *
1380   * }</pre>
1381   *
1382   * <h3>Postgres ANY</h3>
1383   * With Postgres we would often use the SQL <code>ANY</code> expression and array parameter binding
1384   * rather than <code>IN</code>.
1385   *
1386   * <pre>{@code
1387   *
1388   *   query.where()
1389   *     .eq("status", Status.NEW)
1390   *     .rawOrEmpty("t0.customer_id in (select o.customer_id from orders o where o.id = any(?))", orderIds);
1391   *     .findList();
1392   *
1393   * }</pre>
1394   * <p>
1395   * Note that we need to cast the Postgres array for UUID types like:
1396   * </p>
1397   * <pre>{@code
1398   *
1399   *   " ... = any(?::uuid[])"
1400   *
1401   * }</pre>
1402   *
1403   * @param raw    The raw expression that is typically a subquery
1404   * @param values The values which is typically a list or set of id values.
1405   */
1406  ExpressionList<T> rawOrEmpty(String raw, Collection<?> values);
1407
1408  /**
1409   * Add a match expression.
1410   *
1411   * @param propertyName The property name for the match
1412   * @param search       The search value
1413   */
1414  ExpressionList<T> match(String propertyName, String search);
1415
1416  /**
1417   * Add a match expression with options.
1418   *
1419   * @param propertyName The property name for the match
1420   * @param search       The search value
1421   */
1422  ExpressionList<T> match(String propertyName, String search, Match options);
1423
1424  /**
1425   * Add a multi-match expression.
1426   */
1427  ExpressionList<T> multiMatch(String search, String... properties);
1428
1429  /**
1430   * Add a multi-match expression using options.
1431   */
1432  ExpressionList<T> multiMatch(String search, MultiMatch options);
1433
1434  /**
1435   * Add a simple query string expression.
1436   */
1437  ExpressionList<T> textSimple(String search, TextSimple options);
1438
1439  /**
1440   * Add a query string expression.
1441   */
1442  ExpressionList<T> textQueryString(String search, TextQueryString options);
1443
1444  /**
1445   * Add common terms expression.
1446   */
1447  ExpressionList<T> textCommonTerms(String search, TextCommonTerms options);
1448
1449  /**
1450   * And - join two expressions with a logical and.
1451   */
1452  ExpressionList<T> and(Expression expOne, Expression expTwo);
1453
1454  /**
1455   * Or - join two expressions with a logical or.
1456   */
1457  ExpressionList<T> or(Expression expOne, Expression expTwo);
1458
1459  /**
1460   * Negate the expression (prefix it with NOT).
1461   */
1462  ExpressionList<T> not(Expression exp);
1463
1464  /**
1465   * Start a list of expressions that will be joined by AND's
1466   * returning the expression list the expressions are added to.
1467   * <p>
1468   * This is exactly the same as conjunction();
1469   * </p>
1470   * <p>
1471   * Use endAnd() or endJunction() to end the AND junction.
1472   * </p>
1473   * <p>
1474   * Note that a where() clause defaults to an AND junction so
1475   * typically you only explicitly need to use the and() junction
1476   * when it is nested inside an or() or not() junction.
1477   * </p>
1478   * <pre>{@code
1479   *
1480   *  // Example: Nested and()
1481   *
1482   *    .where()
1483   *    .or()
1484   *      .and() // nested and
1485   *        .startsWith("name", "r")
1486   *        .eq("anniversary", onAfter)
1487   *        .endAnd()
1488   *      .and()
1489   *        .eq("status", Customer.Status.ACTIVE)
1490   *        .gt("id", 0)
1491   *        .endAnd()
1492   *      .order().asc("name")
1493   *      .findList();
1494   * }</pre>
1495   */
1496  Junction<T> and();
1497
1498  /**
1499   * Return a list of expressions that will be joined by OR's.
1500   * This is exactly the same as disjunction();
1501   * <p>
1502   * Use endOr() or endJunction() to end the OR junction.
1503   * </p>
1504   *
1505   * <pre>{@code
1506   *
1507   *  // Example: (status active OR anniversary is null)
1508   *
1509   *    .where()
1510   *    .or()
1511   *      .eq("status", Customer.Status.ACTIVE)
1512   *      .isNull("anniversary")
1513   *    .order().asc("name")
1514   *    .findList();
1515   *
1516   * }</pre>
1517   *
1518   * <pre>{@code
1519   *
1520   *  // Example: Use or() to join
1521   *  // two nested and() expressions
1522   *
1523   *    .where()
1524   *    .or()
1525   *      .and()
1526   *        .startsWith("name", "r")
1527   *        .eq("anniversary", onAfter)
1528   *        .endAnd()
1529   *      .and()
1530   *        .eq("status", Customer.Status.ACTIVE)
1531   *        .gt("id", 0)
1532   *        .endAnd()
1533   *      .order().asc("name")
1534   *      .findList();
1535   *
1536   * }</pre>
1537   */
1538  Junction<T> or();
1539
1540  /**
1541   * Return a list of expressions that will be wrapped by NOT.
1542   * <p>
1543   * Use endNot() or endJunction() to end expressions being added to the
1544   * NOT expression list.
1545   * </p>
1546   *
1547   * <pre>{@code
1548   *
1549   *    .where()
1550   *      .not()
1551   *        .gt("id", 1)
1552   *        .eq("anniversary", onAfter)
1553   *        .endNot()
1554   *
1555   * }</pre>
1556   *
1557   * <pre>{@code
1558   *
1559   * // Example: nested not()
1560   *
1561   *   .where()
1562   *     .eq("status", Customer.Status.ACTIVE)
1563   *     .not()
1564   *       .gt("id", 1)
1565   *       .eq("anniversary", onAfter)
1566   *       .endNot()
1567   *     .order()
1568   *       .asc("name")
1569   *     .findList();
1570   *
1571   * }</pre>
1572   */
1573  Junction<T> not();
1574
1575  /**
1576   * Start (and return) a list of expressions that will be joined by AND's.
1577   * <p>
1578   * This is the same as and().
1579   * </p>
1580   */
1581  Junction<T> conjunction();
1582
1583  /**
1584   * Start (and return) a list of expressions that will be joined by OR's.
1585   * <p>
1586   * This is the same as or().
1587   * </p>
1588   */
1589  Junction<T> disjunction();
1590
1591  /**
1592   * Start a list of expressions that will be joined by MUST.
1593   * <p>
1594   * This automatically makes the query a useDocStore(true) query that
1595   * will execute against the document store (ElasticSearch etc).
1596   * </p>
1597   * <p>
1598   * This is logically similar to and().
1599   * </p>
1600   */
1601  Junction<T> must();
1602
1603  /**
1604   * Start a list of expressions that will be joined by SHOULD.
1605   * <p>
1606   * This automatically makes the query a useDocStore(true) query that
1607   * will execute against the document store (ElasticSearch etc).
1608   * </p>
1609   * <p>
1610   * This is logically similar to or().
1611   * </p>
1612   */
1613  Junction<T> should();
1614
1615  /**
1616   * Start a list of expressions that will be joined by MUST NOT.
1617   * <p>
1618   * This automatically makes the query a useDocStore(true) query that
1619   * will execute against the document store (ElasticSearch etc).
1620   * </p>
1621   * <p>
1622   * This is logically similar to not().
1623   * </p>
1624   */
1625  Junction<T> mustNot();
1626
1627  /**
1628   * End a junction returning the parent expression list.
1629   * <p>
1630   * Ends a and(), or(), not(), must(), mustNot() or should() junction
1631   * such that you get the parent expression.
1632   * </p>
1633   * <p>
1634   * Alternatively you can always use where() to return the top level expression list.
1635   * </p>
1636   */
1637  ExpressionList<T> endJunction();
1638
1639  /**
1640   * End a AND junction - synonym for endJunction().
1641   */
1642  ExpressionList<T> endAnd();
1643
1644  /**
1645   * End a AND junction - synonym for endJunction().
1646   */
1647  ExpressionList<T> endOr();
1648
1649  /**
1650   * End a NOT junction - synonym for endJunction().
1651   */
1652  ExpressionList<T> endNot();
1653
1654}