001package io.ebean.typequery;
002
003import io.ebean.CacheMode;
004import io.ebean.DB;
005import io.ebean.Database;
006import io.ebean.DtoQuery;
007import io.ebean.ExpressionList;
008import io.ebean.FetchConfig;
009import io.ebean.FetchGroup;
010import io.ebean.FutureIds;
011import io.ebean.FutureList;
012import io.ebean.FutureRowCount;
013import io.ebean.PagedList;
014import io.ebean.PersistenceContextScope;
015import io.ebean.ProfileLocation;
016import io.ebean.Query;
017import io.ebean.QueryIterator;
018import io.ebean.RawSql;
019import io.ebean.Transaction;
020import io.ebean.UpdateQuery;
021import io.ebean.Version;
022import io.ebean.search.MultiMatch;
023import io.ebean.search.TextCommonTerms;
024import io.ebean.search.TextQueryString;
025import io.ebean.search.TextSimple;
026import io.ebean.service.SpiFetchGroupQuery;
027import io.ebean.text.PathProperties;
028import io.ebeaninternal.server.util.ArrayStack;
029
030import javax.annotation.Nonnull;
031import javax.annotation.Nullable;
032import java.sql.Connection;
033import java.sql.Timestamp;
034import java.util.Collection;
035import java.util.List;
036import java.util.Map;
037import java.util.Optional;
038import java.util.Set;
039import java.util.function.Consumer;
040import java.util.function.Predicate;
041import java.util.stream.Stream;
042
043/**
044 * Base root query bean.
045 * <p>
046 * With code generation for each entity bean type a query bean is created that extends this.
047 * <p>
048 * Provides common features for all root query beans
049 * </p>
050 * <p>
051 * <h2>Example - QCustomer extends TQRootBean</h2>
052 * <p>
053 * These 'query beans' like QCustomer are generated using the <code>avaje-ebeanorm-typequery-generator</code>.
054 * </p>
055 * <pre>{@code
056 *
057 *   public class QCustomer extends TQRootBean<Customer,QCustomer> {
058 *
059 *     // properties
060 *     public PLong<QCustomer> id;
061 *
062 *     public PString<QCustomer> name;
063 *     ...
064 *
065 * }</pre>
066 * <p>
067 * <h2>Example - usage of QCustomer</h2>
068 * <pre>{@code
069 *
070 *    Date fiveDaysAgo = ...
071 *
072 *    List<Customer> customers =
073 *        new QCustomer()
074 *          .name.ilike("rob")
075 *          .status.equalTo(Customer.Status.GOOD)
076 *          .registered.after(fiveDaysAgo)
077 *          .contacts.email.endsWith("@foo.com")
078 *          .orderBy()
079 *            .name.asc()
080 *            .registered.desc()
081 *          .findList();
082 *
083 * }</pre>
084 * <p>
085 * <h2>Resulting SQL where</h2>
086 * <p>
087 * <pre>{@code sql
088 *
089 *     where lower(t0.name) like ?  and t0.status = ?  and t0.registered > ?  and u1.email like ?
090 *     order by t0.name, t0.registered desc;
091 *
092 *     --bind(rob,GOOD,Mon Jul 27 12:05:37 NZST 2015,%@foo.com)
093 * }</pre>
094 *
095 * @param <T> the entity bean type (normal entity bean type e.g. Customer)
096 * @param <R> the specific root query bean type (e.g. QCustomer)
097 */
098public abstract class TQRootBean<T, R> {
099
100  /**
101   * The underlying query.
102   */
103  private final Query<T> query;
104
105  /**
106   * The underlying expression lists held as a stack. Pushed and popped based on and/or (conjunction/disjunction).
107   */
108  private ArrayStack<ExpressionList<T>> whereStack;
109
110  /**
111   * Stack of Text expressions ("query" section of ElasticSearch query rather than "filter" section).
112   */
113  private ArrayStack<ExpressionList<T>> textStack;
114
115  /**
116   * When true expressions should be added to the "text" stack - ElasticSearch "query" section
117   * rather than the "where" stack.
118   */
119  private boolean textMode;
120
121  /**
122   * The root query bean instance. Used to provide fluid query construction.
123   */
124  private R root;
125
126  /**
127   * Construct using the type of bean to query on and the default database.
128   */
129  public TQRootBean(Class<T> beanType) {
130    this(beanType, DB.getDefault());
131  }
132
133  /**
134   * Construct using the type of bean to query on and a given database.
135   */
136  public TQRootBean(Class<T> beanType, Database database) {
137    this(database.find(beanType));
138  }
139
140  /**
141   * Construct with a transaction.
142   */
143  protected TQRootBean(Class<T> beanType, Transaction transaction) {
144    this(beanType);
145    query.usingTransaction(transaction);
146  }
147
148  /**
149   * Construct with a database and transaction.
150   */
151  protected TQRootBean(Class<T> beanType, Database database, Transaction transaction) {
152    this(beanType, database);
153    query.usingTransaction(transaction);
154  }
155
156  /**
157   * Construct using a query.
158   */
159  @SuppressWarnings("unchecked")
160  public TQRootBean(Query<T> query) {
161    this.query = query;
162    this.root = (R) this;
163  }
164
165  /**
166   * Construct for using as an 'Alias' to use the properties as known string
167   * values for select() and fetch().
168   */
169  public TQRootBean(boolean aliasDummy) {
170    this.query = null;
171  }
172
173  /**
174   * Return the fetch group.
175   */
176  public FetchGroup<T> buildFetchGroup() {
177    return ((SpiFetchGroupQuery) query()).buildFetchGroup();
178  }
179
180  /**
181   * Sets the root query bean instance. Used to provide fluid query construction.
182   */
183  protected void setRoot(R root) {
184    this.root = root;
185  }
186
187  /**
188   * Return the underlying query.
189   * <p>
190   * Generally it is not expected that you will need to do this but typically use
191   * the find methods available on this 'root query bean' instance like findList().
192   * </p>
193   */
194  @Nonnull
195  public Query<T> query() {
196    return query;
197  }
198
199  /**
200   * Explicitly set a comma delimited list of the properties to fetch on the
201   * 'main' root level entity bean (aka partial object). Note that '*' means all
202   * properties.
203   * <p>
204   * You use {@link #fetch(String, String)} to specify specific properties to fetch
205   * on other non-root level paths of the object graph.
206   * </p>
207   * <p>
208   * <pre>{@code
209   *
210   * List<Customer> customers =
211   *     new QCustomer()
212   *     // Only fetch the customer id, name and status.
213   *     // This is described as a "Partial Object"
214   *     .select("name, status")
215   *     .name.ilike("rob%")
216   *     .findList();
217   *
218   * }</pre>
219   *
220   * @param properties the properties to fetch for this bean (* = all properties).
221   */
222  public R select(String properties) {
223    query.select(properties);
224    return root;
225  }
226
227  /**
228   * Set a FetchGroup to control what part of the object graph is loaded.
229   * <p>
230   * This is an alternative to using select() and fetch() providing a nice clean separation
231   * between what a query should load and the query predicates.
232   * </p>
233   *
234   * <pre>{@code
235   *
236   * FetchGroup<Customer> fetchGroup = FetchGroup.of(Customer.class)
237   *   .select("name, status")
238   *   .fetch("contacts", "firstName, lastName, email")
239   *   .build();
240   *
241   * List<Customer> customers =
242   *
243   *   new QCustomer()
244   *   .select(fetchGroup)
245   *   .findList();
246   *
247   * }</pre>
248   */
249  public R select(FetchGroup<T> fetchGroup) {
250    query.select(fetchGroup);
251    return root;
252  }
253
254  /**
255   * Tune the query by specifying the properties to be loaded on the
256   * 'main' root level entity bean (aka partial object).
257   * <pre>{@code
258   *
259   *   // alias for the customer properties in select()
260   *   QCustomer cust = QCustomer.alias();
261   *
262   *   // alias for the contact properties in contacts.fetch()
263   *   QContact contact = QContact.alias();
264   *
265   *   List<Customer> customers =
266   *     new QCustomer()
267   *       // tune query
268   *       .select(cust.id, cust.name)
269   *       .contacts.fetch(contact.firstName, contact.lastName, contact.email)
270   *
271   *       // predicates
272   *       .id.greaterThan(1)
273   *       .findList();
274   *
275   * }</pre>
276   *
277   * @param properties the list of properties to fetch
278   */
279  @SafeVarargs
280  public final R select(TQProperty<R>... properties) {
281    StringBuilder selectProps = new StringBuilder(50);
282    for (int i = 0; i < properties.length; i++) {
283      if (i > 0) {
284        selectProps.append(",");
285      }
286      selectProps.append(properties[i].propertyName());
287    }
288    query.select(selectProps.toString());
289    return root;
290  }
291
292  /**
293   * Specify a path to load including all its properties.
294   * <p>
295   * The same as {@link #fetch(String, String)} with the fetchProperties as "*".
296   * </p>
297   * <pre>{@code
298   *
299   * List<Customer> customers =
300   *     new QCustomer()
301   *     // eager fetch the contacts
302   *     .fetch("contacts")
303   *     .findList();
304   *
305   * }</pre>
306   *
307   * @param path the property path of an associated (OneToOne, OneToMany, ManyToOne or ManyToMany) bean.
308   */
309  public R fetch(String path) {
310    query.fetch(path);
311    return root;
312  }
313
314  /**
315   * Specify a path to load including all its properties using a "query join".
316   *
317   * <pre>{@code
318   *
319   * List<Customer> customers =
320   *     new QCustomer()
321   *     // eager fetch the contacts using a "query join"
322   *     .fetchQuery("contacts")
323   *     .findList();
324   *
325   * }</pre>
326   *
327   * @param path the property path of an associated (OneToOne, OneToMany, ManyToOne or ManyToMany) bean.
328   */
329  public R fetchQuery(String path) {
330    query.fetchQuery(path);
331    return root;
332  }
333
334  /**
335   * Specify a path to load from L2 cache including all its properties.
336   *
337   * <pre>{@code
338   *
339   * List<Order> orders =
340   *     new QOrder()
341   *     // eager fetch the customer using L2 cache
342   *     .fetchCache("customer")
343   *     .findList();
344   *
345   * }</pre>
346   *
347   * @param path the property path to load from L2 cache.
348   */
349  public R fetchCache(String path) {
350    query.fetchCache(path);
351    return root;
352  }
353
354  /**
355   * Specify a path and properties to load using a "query join".
356   *
357   * <pre>{@code
358   *
359   * List<Customer> customers =
360   *     new QCustomer()
361   *     // eager fetch contacts using a "query join"
362   *     .fetchQuery("contacts", "email, firstName, lastName")
363   *     .findList();
364   *
365   * }</pre>
366   *
367   * @param path       the property path of an associated (OneToOne, OneToMany, ManyToOne or ManyToMany) bean.
368   * @param properties the properties to load for this path.
369   */
370  public R fetchQuery(String path, String properties) {
371    query.fetchQuery(path, properties);
372    return root;
373  }
374
375  /**
376   * Specify a path and properties to load from L2 cache.
377   *
378   * <pre>{@code
379   *
380   * List<Order> orders =
381   *     new QOrder()
382   *     // eager fetch the customer using L2 cache
383   *     .fetchCache("customer", "name,status")
384   *     .findList();
385   *
386   * }</pre>
387   *
388   * @param path       the property path to load from L2 cache.
389   * @param properties the properties to load for this path.
390   */
391  public R fetchCache(String path, String properties) {
392    query.fetchCache(path, properties);
393    return root;
394  }
395
396  /**
397   * Specify a path to <em>fetch</em> with its specific properties to include
398   * (aka partial object).
399   * <p>
400   * When you specify a join this means that property (associated bean(s)) will
401   * be fetched and populated. If you specify "*" then all the properties of the
402   * associated bean will be fetched and populated. You can specify a comma
403   * delimited list of the properties of that associated bean which means that
404   * only those properties are fetched and populated resulting in a
405   * "Partial Object" - a bean that only has some of its properties populated.
406   * </p>
407   * <p>
408   * <pre>{@code
409   *
410   * // query orders...
411   * List<Order> orders =
412   *     new QOrder()
413   *       .fetch("customer", "name, phoneNumber")
414   *       .fetch("customer.billingAddress", "*")
415   *       .findList();
416   *
417   * }</pre>
418   * <p>
419   * If columns is null or "*" then all columns/properties for that path are fetched.
420   * </p>
421   *
422   * <pre>{@code
423   *
424   * List<Customer> customers =
425   *     new QCustomer()
426   *     .select("name, status")
427   *     .fetch("contacts", "firstName,lastName,email")
428   *     .findList();
429   *
430   * }</pre>
431   *
432   * @param path       the path of an associated (OneToOne, OneToMany, ManyToOne or ManyToMany) bean.
433   * @param properties properties of the associated bean that you want to include in the
434   *                   fetch (* means all properties, null also means all properties).
435   */
436  public R fetch(String path, String properties) {
437    query.fetch(path, properties);
438    return root;
439  }
440
441  /**
442   * Additionally specify a FetchConfig to use a separate query or lazy loading
443   * to load this path.
444   * <p>
445   * <pre>{@code
446   *
447   * // fetch customers (their id, name and status)
448   * List<Customer> customers =
449   *     new QCustomer()
450   *     .select("name, status")
451   *     .fetch("contacts", "firstName,lastName,email", new FetchConfig().lazy(10))
452   *     .findList();
453   *
454   * }</pre>
455   */
456  public R fetch(String path, String properties, FetchConfig fetchConfig) {
457    query.fetch(path, properties, fetchConfig);
458    return root;
459  }
460
461  /**
462   * Additionally specify a FetchConfig to specify a "query join" and or define
463   * the lazy loading query.
464   * <p>
465   * <pre>{@code
466   *
467   * // fetch customers (their id, name and status)
468   * List<Customer> customers =
469   *     new QCustomer()
470   *       // lazy fetch contacts with a batch size of 100
471   *       .fetch("contacts", new FetchConfig().lazy(100))
472   *       .findList();
473   *
474   * }</pre>
475   */
476  public R fetch(String path, FetchConfig fetchConfig) {
477    query.fetch(path, fetchConfig);
478    return root;
479  }
480
481  /**
482   * Apply the path properties replacing the select and fetch clauses.
483   * <p>
484   * This is typically used when the PathProperties is applied to both the query and the JSON output.
485   * </p>
486   */
487  public R apply(PathProperties pathProperties) {
488    query.apply(pathProperties);
489    return root;
490  }
491
492  /**
493   * Perform an 'As of' query using history tables to return the object graph
494   * as of a time in the past.
495   * <p>
496   * To perform this query the DB must have underlying history tables.
497   * </p>
498   *
499   * @param asOf the date time in the past at which you want to view the data
500   */
501  public R asOf(Timestamp asOf) {
502    query.asOf(asOf);
503    return root;
504  }
505
506  /**
507   * Execute the query against the draft set of tables.
508   */
509  public R asDraft() {
510    query.asDraft();
511    return root;
512  }
513
514  /**
515   * Execute the query including soft deleted rows.
516   */
517  public R setIncludeSoftDeletes() {
518    query.setIncludeSoftDeletes();
519    return root;
520  }
521
522  /**
523   * Set root table alias.
524   */
525  public R alias(String alias) {
526    query.alias(alias);
527    return root;
528  }
529
530  /**
531   * Set the maximum number of rows to return in the query.
532   *
533   * @param maxRows the maximum number of rows to return in the query.
534   */
535  public R setMaxRows(int maxRows) {
536    query.setMaxRows(maxRows);
537    return root;
538  }
539
540  /**
541   * Set the first row to return for this query.
542   *
543   * @param firstRow the first row to include in the query result.
544   */
545  public R setFirstRow(int firstRow) {
546    query.setFirstRow(firstRow);
547    return root;
548  }
549
550  /**
551   * Execute the query allowing properties with invalid JSON to be collected and not fail the query.
552   * <pre>{@code
553   *
554   *   // fetch a bean with JSON content
555   *   EBasicJsonList bean= new QEBasicJsonList()
556   *       .id.equalTo(42)
557   *       .setAllowLoadErrors()  // collect errors into bean state if we have invalid JSON
558   *       .findOne();
559   *
560   *
561   *   // get the invalid JSON errors from the bean state
562   *   Map<String, Exception> errors = server().getBeanState(bean).getLoadErrors();
563   *
564   *   // If this map is not empty tell we have invalid JSON
565   *   // and should try and fix the JSON content or inform the user
566   *
567   * }</pre>
568   */
569  public R setAllowLoadErrors() {
570    query.setAllowLoadErrors();
571    return root;
572  }
573
574  /**
575   * Explicitly specify whether to use AutoTune for this query.
576   * <p>
577   * If you do not call this method on a query the "Implicit AutoTune mode" is
578   * used to determine if AutoTune should be used for a given query.
579   * </p>
580   * <p>
581   * AutoTune can add additional fetch paths to the query and specify which
582   * properties are included for each path. If you have explicitly defined some
583   * fetch paths AutoTune will not remove them.
584   * </p>
585   */
586  public R setAutoTune(boolean autoTune) {
587    query.setAutoTune(autoTune);
588    return root;
589  }
590
591  /**
592   * A hint which for JDBC translates to the Statement.fetchSize().
593   * <p>
594   * Gives the JDBC driver a hint as to the number of rows that should be
595   * fetched from the database when more rows are needed for ResultSet.
596   * </p>
597   */
598  public R setBufferFetchSizeHint(int fetchSize) {
599    query.setBufferFetchSizeHint(fetchSize);
600    return root;
601  }
602
603  /**
604   * Set whether this query uses DISTINCT.
605   */
606  public R setDistinct(boolean distinct) {
607    query.setDistinct(distinct);
608    return root;
609  }
610
611  /**
612   * Set the index(es) to search for a document store which uses partitions.
613   * <p>
614   * For example, when executing a query against ElasticSearch with daily indexes we can
615   * explicitly specify the indexes to search against.
616   * </p>
617   * <pre>{@code
618   *
619   *   // explicitly specify the indexes to search
620   *   query.setDocIndexName("logstash-2016.11.5,logstash-2016.11.6")
621   *
622   *   // search today's index
623   *   query.setDocIndexName("$today")
624   *
625   *   // search the last 3 days
626   *   query.setDocIndexName("$last-3")
627   *
628   * }</pre>
629   * <p>
630   * If the indexName is specified with ${daily} e.g. "logstash-${daily}" ... then we can use
631   * $today and $last-x as the search docIndexName like the examples below.
632   * </p>
633   * <pre>{@code
634   *
635   *   // search today's index
636   *   query.setDocIndexName("$today")
637   *
638   *   // search the last 3 days
639   *   query.setDocIndexName("$last-3")
640   *
641   * }</pre>
642   *
643   * @param indexName The index or indexes to search against
644   * @return This query
645   */
646  public R setDocIndexName(String indexName) {
647    query.setDocIndexName(indexName);
648    return root;
649  }
650
651  /**
652   * Restrict the query to only return subtypes of the given inherit type.
653   * <pre>{@code
654   *
655   *   List<Animal> animals =
656   *     new QAnimal()
657   *       .name.startsWith("Fluffy")
658   *       .setInheritType(Cat.class)
659   *       .findList();
660   *
661   * }</pre>
662   */
663  public R setInheritType(Class<? extends T> type) {
664    query.setInheritType(type);
665    return root;
666  }
667
668  /**
669   * Set the base table to use for this query.
670   * <p>
671   * Typically this is used when a table has partitioning and we wish to specify a specific
672   * partition/table to query against.
673   * </p>
674   * <pre>{@code
675   *
676   *   QOrder()
677   *   .setBaseTable("order_2019_05")
678   *   .status.equalTo(Status.NEW)
679   *   .findList();
680   *
681   * }</pre>
682   */
683  public R setBaseTable(String baseTable) {
684    query.setBaseTable(baseTable);
685    return root;
686  }
687
688  /**
689   * Execute the query with the given lock type and WAIT.
690   * <p>
691   * Note that <code>forUpdate()</code> is the same as
692   * <code>withLock(LockType.UPDATE)</code>.
693   * <p>
694   * Provides us with the ability to explicitly use Postgres
695   * SHARE, KEY SHARE, NO KEY UPDATE and UPDATE row locks.
696   */
697  R withLock(Query.LockType lockType) {
698    query.withLock(lockType);
699    return root;
700  }
701
702  /**
703   * Execute the query with the given lock type and lock wait.
704   * <p>
705   * Note that <code>forUpdateNoWait()</code> is the same as
706   * <code>withLock(LockType.UPDATE, LockWait.NOWAIT)</code>.
707   * <p>
708   * Provides us with the ability to explicitly use Postgres
709   * SHARE, KEY SHARE, NO KEY UPDATE and UPDATE row locks.
710   */
711  R withLock(Query.LockType lockType, Query.LockWait lockWait) {
712    query.withLock(lockType, lockWait);
713    return root;
714  }
715
716  /**
717   * Execute using "for update" clause which results in the DB locking the record.
718   */
719  public R forUpdate() {
720    query.forUpdate();
721    return root;
722  }
723
724  /**
725   * Deprecated - migrate to withLock().
726   * Execute using "for update" with given lock type (currently Postgres only).
727   */
728  @Deprecated
729  public R forUpdate(Query.LockType lockType) {
730    query.forUpdate(lockType);
731    return root;
732  }
733
734  /**
735   * Execute using "for update" clause with "no wait" option.
736   * <p>
737   * This is typically a Postgres and Oracle only option at this stage.
738   */
739  public R forUpdateNoWait() {
740    query.forUpdateNoWait();
741    return root;
742  }
743
744  /**
745   * Deprecated - migrate to withLock().
746   * Execute using "for update nowait" with given lock type (currently Postgres only).
747   */
748  @Deprecated
749  public R forUpdateNoWait(Query.LockType lockType) {
750    query.forUpdateNoWait(lockType);
751    return root;
752  }
753
754  /**
755   * Execute using "for update" clause with "skip locked" option.
756   * <p>
757   * This is typically a Postgres and Oracle only option at this stage.
758   * </p>
759   */
760  public R forUpdateSkipLocked() {
761    query.forUpdateSkipLocked();
762    return root;
763  }
764
765  /**
766   * Deprecated - migrate to withLock().
767   * Execute using "for update skip locked" with given lock type (currently Postgres only).
768   */
769  @Deprecated
770  public R forUpdateSkipLocked(Query.LockType lockType) {
771    query.forUpdateSkipLocked(lockType);
772    return root;
773  }
774
775  /**
776   * Return this query as an UpdateQuery.
777   *
778   * <pre>{@code
779   *
780   *   int rows =
781   *     new QCustomer()
782   *     .name.startsWith("Rob")
783   *     .organisation.id.equalTo(42)
784   *     .asUpdate()
785   *       .set("active", false)
786   *       .update()
787   *
788   * }</pre>
789   *
790   * @return This query as an UpdateQuery
791   */
792  public UpdateQuery<T> asUpdate() {
793    return query.asUpdate();
794  }
795
796  /**
797   * Convert the query to a DTO bean query.
798   * <p>
799   * We effectively use the underlying ORM query to build the SQL and then execute
800   * and map it into DTO beans.
801   */
802  public <D> DtoQuery<D> asDto(Class<D> dtoClass) {
803    return query.asDto(dtoClass);
804  }
805
806  /**
807   * Set the Id value to query. This is used with findOne().
808   * <p>
809   * You can use this to have further control over the query. For example adding
810   * fetch joins.
811   * </p>
812   * <p>
813   * <pre>{@code
814   *
815   * Order order =
816   *   new QOrder()
817   *     .setId(1)
818   *     .fetch("details")
819   *     .findOne();
820   *
821   * // the order details were eagerly fetched
822   * List<OrderDetail> details = order.getDetails();
823   *
824   * }</pre>
825   */
826  public R setId(Object id) {
827    query.setId(id);
828    return root;
829  }
830
831  /**
832   * Set a list of Id values to match.
833   * <p>
834   * <pre>{@code
835   *
836   * List<Order> orders =
837   *   new QOrder()
838   *     .setIdIn(42, 43, 44)
839   *     .findList();
840   *
841   * // the order details were eagerly fetched
842   * List<OrderDetail> details = order.getDetails();
843   *
844   * }</pre>
845   */
846  public R setIdIn(Object... ids) {
847    query.where().idIn(ids);
848    return root;
849  }
850
851  /**
852   * Set a label on the query.
853   * <p>
854   * This label can be used to help identify query performance metrics but we can also use
855   * profile location enhancement on Finders so for some that would be a better option.
856   * </p>
857   */
858  public R setLabel(String label) {
859    query.setLabel(label);
860    return root;
861  }
862
863  /**
864   * Set the profile location.
865   * <p>
866   * This is typically set automatically via enhancement when profile location enhancement
867   * is turned on. It is generally not set by application code.
868   * </p>
869   */
870  public R setProfileLocation(ProfileLocation profileLocation) {
871    query.setProfileLocation(profileLocation);
872    return root;
873  }
874
875  /**
876   * Set the default lazy loading batch size to use.
877   * <p>
878   * When lazy loading is invoked on beans loaded by this query then this sets the
879   * batch size used to load those beans.
880   *
881   * @param lazyLoadBatchSize the number of beans to lazy load in a single batch
882   */
883  public R setLazyLoadBatchSize(int lazyLoadBatchSize) {
884    query.setLazyLoadBatchSize(lazyLoadBatchSize);
885    return root;
886  }
887
888  /**
889   * When set to true all the beans from this query are loaded into the bean
890   * cache.
891   */
892  public R setLoadBeanCache(boolean loadBeanCache) {
893    query.setLoadBeanCache(loadBeanCache);
894    return root;
895  }
896
897  /**
898   * Set the property to use as keys for a map.
899   * <p>
900   * If no property is set then the id property is used.
901   * </p>
902   * <p>
903   * <pre>{@code
904   *
905   * // Assuming sku is unique for products...
906   *
907   * Map<String,Product> productMap =
908   *     new QProduct()
909   *     // use sku for keys...
910   *     .setMapKey("sku")
911   *     .findMap();
912   *
913   * }</pre>
914   *
915   * @param mapKey the property to use as keys for a map.
916   */
917  public R setMapKey(String mapKey) {
918    query.setMapKey(mapKey);
919    return root;
920  }
921
922  /**
923   * Specify the PersistenceContextScope to use for this query.
924   * <p>
925   * When this is not set the 'default' configured on {@link io.ebean.config.ServerConfig#setPersistenceContextScope(PersistenceContextScope)}
926   * is used - this value defaults to {@link io.ebean.PersistenceContextScope#TRANSACTION}.
927   * <p>
928   * Note that the same persistence Context is used for subsequent lazy loading and query join queries.
929   * <p>
930   * Note that #findEach uses a 'per object graph' PersistenceContext so this scope is ignored for
931   * queries executed as #findIterate, #findEach, #findEachWhile.
932   *
933   * @param scope The scope to use for this query and subsequent lazy loading.
934   */
935  public R setPersistenceContextScope(PersistenceContextScope scope) {
936    query.setPersistenceContextScope(scope);
937    return root;
938  }
939
940  /**
941   * Set RawSql to use for this query.
942   */
943  public R setRawSql(RawSql rawSql) {
944    query.setRawSql(rawSql);
945    return root;
946  }
947
948  /**
949   * When set to true when you want the returned beans to be read only.
950   */
951  public R setReadOnly(boolean readOnly) {
952    query.setReadOnly(readOnly);
953    return root;
954  }
955
956  /**
957   * Set this to true to use the bean cache.
958   * <p>
959   * If the query result is in cache then by default this same instance is
960   * returned. In this sense it should be treated as a read only object graph.
961   * </p>
962   */
963  public R setUseCache(boolean useCache) {
964    query.setUseCache(useCache);
965    return root;
966  }
967
968
969  /**
970   * Set the mode to use the bean cache when executing this query.
971   * <p>
972   * By default "find by id" and "find by natural key" will use the bean cache
973   * when bean caching is enabled. Setting this to false means that the query
974   * will not use the bean cache and instead hit the database.
975   * </p>
976   * <p>
977   * By default findList() with natural keys will not use the bean cache. In that
978   * case we need to explicitly use the bean cache.
979   * </p>
980   */
981  public R setBeanCacheMode(CacheMode beanCacheMode) {
982    query.setBeanCacheMode(beanCacheMode);
983    return root;
984  }
985
986  /**
987   * Set to true if this query should execute against the doc store.
988   * <p>
989   * When setting this you may also consider disabling lazy loading.
990   * </p>
991   */
992  public R setUseDocStore(boolean useDocStore) {
993    query.setUseDocStore(useDocStore);
994    return root;
995  }
996
997  /**
998   * Set true if you want to disable lazy loading.
999   * <p>
1000   * That is, once the object graph is returned further lazy loading is disabled.
1001   * </p>
1002   */
1003  public R setDisableLazyLoading(boolean disableLazyLoading) {
1004    query.setDisableLazyLoading(disableLazyLoading);
1005    return root;
1006  }
1007
1008  /**
1009   * Disable read auditing for this query.
1010   * <p>
1011   * This is intended to be used when the query is not a user initiated query and instead
1012   * part of the internal processing in an application to load a cache or document store etc.
1013   * In these cases we don't want the query to be part of read auditing.
1014   * </p>
1015   */
1016  public R setDisableReadAuditing() {
1017    query.setDisableReadAuditing();
1018    return root;
1019  }
1020
1021  /**
1022   * Set this to true to use the query cache.
1023   */
1024  public R setUseQueryCache(boolean useCache) {
1025    query.setUseQueryCache(useCache);
1026    return root;
1027  }
1028
1029  /**
1030   * Set the {@link CacheMode} to use the query for executing this query.
1031   */
1032  public R setUseQueryCache(CacheMode cacheMode) {
1033    query.setUseQueryCache(cacheMode);
1034    return root;
1035  }
1036
1037  /**
1038   * Set a timeout on this query.
1039   * <p>
1040   * This will typically result in a call to setQueryTimeout() on a
1041   * preparedStatement. If the timeout occurs an exception will be thrown - this
1042   * will be a SQLException wrapped up in a PersistenceException.
1043   * </p>
1044   *
1045   * @param secs the query timeout limit in seconds. Zero means there is no limit.
1046   */
1047  public R setTimeout(int secs) {
1048    query.setTimeout(secs);
1049    return root;
1050  }
1051
1052  /**
1053   * Returns the set of properties or paths that are unknown (do not map to known properties or paths).
1054   * <p>
1055   * Validate the query checking the where and orderBy expression paths to confirm if
1056   * they represent valid properties or paths for the given bean type.
1057   * </p>
1058   */
1059  public Set<String> validate() {
1060    return query.validate();
1061  }
1062
1063  /**
1064   * Add raw expression with no parameters.
1065   * <p>
1066   * When properties in the clause are fully qualified as table-column names
1067   * then they are not translated. logical property name names (not fully
1068   * qualified) will still be translated to their physical name.
1069   * </p>
1070   * <p>
1071   * <pre>{@code
1072   *
1073   *   raw("orderQty < shipQty")
1074   *
1075   * }</pre>
1076   *
1077   * <h4>Subquery example:</h4>
1078   * <pre>{@code
1079   *
1080   *   .raw("t0.customer_id in (select customer_id from customer_group where group_id = any(?::uuid[]))", groupIds)
1081   *
1082   * }</pre>
1083   */
1084  public R raw(String rawExpression) {
1085    peekExprList().raw(rawExpression);
1086    return root;
1087  }
1088
1089  /**
1090   * Add raw expression with an array of parameters.
1091   * <p>
1092   * The raw expression should contain the same number of ? as there are
1093   * parameters.
1094   * </p>
1095   * <p>
1096   * When properties in the clause are fully qualified as table-column names
1097   * then they are not translated. logical property name names (not fully
1098   * qualified) will still be translated to their physical name.
1099   * </p>
1100   */
1101  public R raw(String rawExpression, Object... bindValues) {
1102    peekExprList().raw(rawExpression, bindValues);
1103    return root;
1104  }
1105
1106  /**
1107   * Only add the raw expression if the values is not null or empty.
1108   * <p>
1109   * This is a pure convenience expression to make it nicer to deal with the pattern where we use
1110   * raw() expression with a subquery and only want to add the subquery predicate when the collection
1111   * of values is not empty.
1112   * </p>
1113   * <h3>Without inOrEmpty()</h3>
1114   * <pre>{@code
1115   *
1116   *   QCustomer query = new QCustomer() // add some predicates
1117   *     .status.equalTo(Status.NEW);
1118   *
1119   *   // common pattern - we can use rawOrEmpty() instead
1120   *   if (orderIds != null && !orderIds.isEmpty()) {
1121   *     query.raw("t0.customer_id in (select o.customer_id from orders o where o.id in (?1))", orderIds);
1122   *   }
1123   *
1124   *   query.findList();
1125   *
1126   * }</pre>
1127   *
1128   * <h3>Using rawOrEmpty()</h3>
1129   * Note that in the example below we use the <code>?1</code> bind parameter to get  "parameter expansion"
1130   * for each element in the collection.
1131   *
1132   * <pre>{@code
1133   *
1134   *   new QCustomer()
1135   *     .status.equalTo(Status.NEW)
1136   *     // only add the expression if orderIds is not empty
1137   *     .rawOrEmpty("t0.customer_id in (select o.customer_id from orders o where o.id in (?1))", orderIds);
1138   *     .findList();
1139   *
1140   * }</pre>
1141   *
1142   * <h3>Postgres ANY</h3>
1143   * With Postgres we would often use the SQL <code>ANY</code> expression and array parameter binding
1144   * rather than <code>IN</code>.
1145   *
1146   * <pre>{@code
1147   *
1148   *   new QCustomer()
1149   *     .status.equalTo(Status.NEW)
1150   *     .rawOrEmpty("t0.customer_id in (select o.customer_id from orders o where o.id = any(?))", orderIds);
1151   *     .findList();
1152   *
1153   * }</pre>
1154   * <p>
1155   * Note that we need to cast the Postgres array for UUID types like:
1156   * </p>
1157   * <pre>{@code
1158   *
1159   *   " ... = any(?::uuid[])"
1160   *
1161   * }</pre>
1162   *
1163   * @param raw    The raw expression that is typically a subquery
1164   * @param values The values which is typically a list or set of id values.
1165   */
1166  public R rawOrEmpty(String raw, Collection<?> values) {
1167    peekExprList().rawOrEmpty(raw, values);
1168    return root;
1169  }
1170
1171  /**
1172   * Add raw expression with a single parameter.
1173   * <p>
1174   * The raw expression should contain a single ? at the location of the
1175   * parameter.
1176   * </p>
1177   * <p>
1178   * When properties in the clause are fully qualified as table-column names
1179   * then they are not translated. logical property name names (not fully
1180   * qualified) will still be translated to their physical name.
1181   * </p>
1182   * <p>
1183   * <h4>Example:</h4>
1184   * <pre>{@code
1185   *
1186   *   // use a database function
1187   *   raw("add_days(orderDate, 10) < ?", someDate)
1188   *
1189   * }</pre>
1190   *
1191   * <h4>Subquery example:</h4>
1192   * <pre>{@code
1193   *
1194   *   .raw("t0.customer_id in (select customer_id from customer_group where group_id = any(?::uuid[]))", groupIds)
1195   *
1196   * }</pre>
1197   */
1198  public R raw(String rawExpression, Object bindValue) {
1199    peekExprList().raw(rawExpression, bindValue);
1200    return root;
1201  }
1202
1203  /**
1204   * Marker that can be used to indicate that the order by clause is defined after this.
1205   * <p>
1206   * <h2>Example: order by customer name, order date</h2>
1207   * <pre>{@code
1208   *   List<Order> orders =
1209   *          new QOrder()
1210   *            .customer.name.ilike("rob")
1211   *            .orderBy()
1212   *              .customer.name.asc()
1213   *              .orderDate.asc()
1214   *            .findList();
1215   *
1216   * }</pre>
1217   */
1218  public R orderBy() {
1219    // Yes this does not actually do anything! We include it because style wise it makes
1220    // the query nicer to read and suggests that order by definitions are added after this
1221    return root;
1222  }
1223
1224  /**
1225   * Marker that can be used to indicate that the order by clause is defined after this.
1226   * <p>
1227   * <h2>Example: order by customer name, order date</h2>
1228   * <pre>{@code
1229   *   List<Order> orders =
1230   *          new QOrder()
1231   *            .customer.name.ilike("rob")
1232   *            .orderBy()
1233   *              .customer.name.asc()
1234   *              .orderDate.asc()
1235   *            .findList();
1236   *
1237   * }</pre>
1238   */
1239  public R order() {
1240    // Yes this does not actually do anything! We include it because style wise it makes
1241    // the query nicer to read and suggests that order by definitions are added after this
1242    return root;
1243  }
1244
1245  /**
1246   * Set the full raw order by clause replacing the existing order by clause if there is one.
1247   * <p>
1248   * This follows SQL syntax using commas between each property with the
1249   * optional asc and desc keywords representing ascending and descending order
1250   * respectively.
1251   */
1252  public R orderBy(String orderByClause) {
1253    query.orderBy(orderByClause);
1254    return root;
1255  }
1256
1257  /**
1258   * Set the full raw order by clause replacing the existing order by clause if there is one.
1259   * <p>
1260   * This follows SQL syntax using commas between each property with the
1261   * optional asc and desc keywords representing ascending and descending order
1262   * respectively.
1263   */
1264  public R order(String orderByClause) {
1265    query.order(orderByClause);
1266    return root;
1267  }
1268
1269  /**
1270   * Begin a list of expressions added by 'OR'.
1271   * <p>
1272   * Use endOr() or endJunction() to stop added to OR and 'pop' to the parent expression list.
1273   * </p>
1274   * <p>
1275   * <h2>Example</h2>
1276   * <p>
1277   * This example uses an 'OR' expression list with an inner 'AND' expression list.
1278   * </p>
1279   * <pre>{@code
1280   *
1281   *    List<Customer> customers =
1282   *          new QCustomer()
1283   *            .status.equalTo(Customer.Status.GOOD)
1284   *            .or()
1285   *              .id.greaterThan(1000)
1286   *              .and()
1287   *                .name.startsWith("super")
1288   *                .registered.after(fiveDaysAgo)
1289   *              .endAnd()
1290   *            .endOr()
1291   *            .orderBy().id.desc()
1292   *            .findList();
1293   *
1294   * }</pre>
1295   * <h2>Resulting SQL where clause</h2>
1296   * <pre>{@code sql
1297   *
1298   *    where t0.status = ?  and (t0.id > ?  or (t0.name like ?  and t0.registered > ? ) )
1299   *    order by t0.id desc;
1300   *
1301   *    --bind(GOOD,1000,super%,Wed Jul 22 00:00:00 NZST 2015)
1302   *
1303   * }</pre>
1304   */
1305  public R or() {
1306    pushExprList(peekExprList().or());
1307    return root;
1308  }
1309
1310  /**
1311   * Begin a list of expressions added by 'AND'.
1312   * <p>
1313   * Use endAnd() or endJunction() to stop added to AND and 'pop' to the parent expression list.
1314   * </p>
1315   * <p>
1316   * Note that typically the AND expression is only used inside an outer 'OR' expression.
1317   * This is because the top level expression list defaults to an 'AND' expression list.
1318   * </p>
1319   * <h2>Example</h2>
1320   * <p>
1321   * This example uses an 'OR' expression list with an inner 'AND' expression list.
1322   * </p>
1323   * <pre>{@code
1324   *
1325   *    List<Customer> customers =
1326   *          new QCustomer()
1327   *            .status.equalTo(Customer.Status.GOOD)
1328   *            .or() // OUTER 'OR'
1329   *              .id.greaterThan(1000)
1330   *              .and()  // NESTED 'AND' expression list
1331   *                .name.startsWith("super")
1332   *                .registered.after(fiveDaysAgo)
1333   *                .endAnd()
1334   *              .endOr()
1335   *            .orderBy().id.desc()
1336   *            .findList();
1337   *
1338   * }</pre>
1339   * <h2>Resulting SQL where clause</h2>
1340   * <pre>{@code sql
1341   *
1342   *    where t0.status = ?  and (t0.id > ?  or (t0.name like ?  and t0.registered > ? ) )
1343   *    order by t0.id desc;
1344   *
1345   *    --bind(GOOD,1000,super%,Wed Jul 22 00:00:00 NZST 2015)
1346   *
1347   * }</pre>
1348   */
1349  public R and() {
1350    pushExprList(peekExprList().and());
1351    return root;
1352  }
1353
1354  /**
1355   * Begin a list of expressions added by NOT.
1356   * <p>
1357   * Use endNot() or endJunction() to stop added to NOT and 'pop' to the parent expression list.
1358   * </p>
1359   */
1360  public R not() {
1361    pushExprList(peekExprList().not());
1362    return root;
1363  }
1364
1365  /**
1366   * Begin a list of expressions added by MUST.
1367   * <p>
1368   * This automatically makes this query a document store query.
1369   * </p>
1370   * <p>
1371   * Use endJunction() to stop added to MUST and 'pop' to the parent expression list.
1372   * </p>
1373   */
1374  public R must() {
1375    pushExprList(peekExprList().must());
1376    return root;
1377  }
1378
1379  /**
1380   * Begin a list of expressions added by MUST NOT.
1381   * <p>
1382   * This automatically makes this query a document store query.
1383   * </p>
1384   * <p>
1385   * Use endJunction() to stop added to MUST NOT and 'pop' to the parent expression list.
1386   * </p>
1387   */
1388  public R mustNot() {
1389    return pushExprList(peekExprList().mustNot());
1390  }
1391
1392  /**
1393   * Begin a list of expressions added by SHOULD.
1394   * <p>
1395   * This automatically makes this query a document store query.
1396   * </p>
1397   * <p>
1398   * Use endJunction() to stop added to SHOULD and 'pop' to the parent expression list.
1399   * </p>
1400   */
1401  public R should() {
1402    return pushExprList(peekExprList().should());
1403  }
1404
1405  /**
1406   * End a list of expressions added by 'OR'.
1407   */
1408  public R endJunction() {
1409    if (textMode) {
1410      textStack.pop();
1411    } else {
1412      whereStack.pop();
1413    }
1414    return root;
1415  }
1416
1417  /**
1418   * End OR junction - synonym for endJunction().
1419   */
1420  public R endOr() {
1421    return endJunction();
1422  }
1423
1424  /**
1425   * End AND junction - synonym for endJunction().
1426   */
1427  public R endAnd() {
1428    return endJunction();
1429  }
1430
1431  /**
1432   * End NOT junction - synonym for endJunction().
1433   */
1434  public R endNot() {
1435    return endJunction();
1436  }
1437
1438  /**
1439   * Push the expression list onto the appropriate stack.
1440   */
1441  private R pushExprList(ExpressionList<T> list) {
1442    if (textMode) {
1443      textStack.push(list);
1444    } else {
1445      whereStack.push(list);
1446    }
1447    return root;
1448  }
1449
1450  /**
1451   * Add expression after this to the WHERE expression list.
1452   * <p>
1453   * For queries against the normal database (not the doc store) this has no effect.
1454   * </p>
1455   * <p>
1456   * This is intended for use with Document Store / ElasticSearch where expressions can be put into either
1457   * the "query" section or the "filter" section of the query. Full text expressions like MATCH are in the
1458   * "query" section but many expression can be in either - expressions after the where() are put into the
1459   * "filter" section which means that they don't add to the relevance and are also cache-able.
1460   * </p>
1461   */
1462  public R where() {
1463    textMode = false;
1464    return root;
1465  }
1466
1467  /**
1468   * Begin added expressions to the 'Text' expression list.
1469   * <p>
1470   * This automatically makes the query a document store query.
1471   * </p>
1472   * <p>
1473   * For ElasticSearch expressions added to 'text' go into the ElasticSearch 'query context'
1474   * and expressions added to 'where' go into the ElasticSearch 'filter context'.
1475   * </p>
1476   */
1477  public R text() {
1478    textMode = true;
1479    return root;
1480  }
1481
1482  /**
1483   * Add a Text Multi-match expression (document store only).
1484   * <p>
1485   * This automatically makes the query a document store query.
1486   * </p>
1487   */
1488  public R multiMatch(String query, MultiMatch multiMatch) {
1489    peekExprList().multiMatch(query, multiMatch);
1490    return root;
1491  }
1492
1493  /**
1494   * Add a Text Multi-match expression (document store only).
1495   * <p>
1496   * This automatically makes the query a document store query.
1497   * </p>
1498   */
1499  public R multiMatch(String query, String... properties) {
1500    peekExprList().multiMatch(query, properties);
1501    return root;
1502  }
1503
1504  /**
1505   * Add a Text common terms expression (document store only).
1506   * <p>
1507   * This automatically makes the query a document store query.
1508   * </p>
1509   */
1510  public R textCommonTerms(String query, TextCommonTerms options) {
1511    peekExprList().textCommonTerms(query, options);
1512    return root;
1513  }
1514
1515  /**
1516   * Add a Text simple expression (document store only).
1517   * <p>
1518   * This automatically makes the query a document store query.
1519   * </p>
1520   */
1521  public R textSimple(String query, TextSimple options) {
1522    peekExprList().textSimple(query, options);
1523    return root;
1524  }
1525
1526  /**
1527   * Add a Text query string expression (document store only).
1528   * <p>
1529   * This automatically makes the query a document store query.
1530   * </p>
1531   */
1532  public R textQueryString(String query, TextQueryString options) {
1533    peekExprList().textQueryString(query, options);
1534    return root;
1535  }
1536
1537  /**
1538   * Execute the query using the given transaction.
1539   */
1540  public R usingTransaction(Transaction transaction) {
1541    query.usingTransaction(transaction);
1542    return root;
1543  }
1544
1545  /**
1546   * Execute the query using the given connection.
1547   */
1548  public R usingConnection(Connection connection) {
1549    query.usingConnection(connection);
1550    return root;
1551  }
1552
1553  /**
1554   * Execute the query returning true if a row is found.
1555   * <p>
1556   * The query is executed using max rows of 1 and will only select the id property.
1557   * This method is really just a convenient way to optimise a query to perform a
1558   * 'does a row exist in the db' check.
1559   * </p>
1560   *
1561   * <h2>Example using a query bean:</h2>
1562   * <pre>{@code
1563   *
1564   *   boolean userExists =
1565   *     new QContact()
1566   *       .email.equalTo("rob@foo.com")
1567   *       .exists();
1568   *
1569   * }</pre>
1570   *
1571   * <h2>Example:</h2>
1572   * <pre>{@code
1573   *
1574   *   boolean userExists = query()
1575   *     .where().eq("email", "rob@foo.com")
1576   *     .exists();
1577   *
1578   * }</pre>
1579   *
1580   * @return True if the query finds a matching row in the database
1581   */
1582  public boolean exists() {
1583    return query.exists();
1584  }
1585
1586  /**
1587   * Execute the query returning either a single bean or null (if no matching
1588   * bean is found).
1589   * <p>
1590   * If more than 1 row is found for this query then a PersistenceException is
1591   * thrown.
1592   * </p>
1593   * <p>
1594   * This is useful when your predicates dictate that your query should only
1595   * return 0 or 1 results.
1596   * </p>
1597   * <p>
1598   * <pre>{@code
1599   *
1600   * // assuming the sku of products is unique...
1601   * Product product =
1602   *     new QProduct()
1603   *         .sku.equalTo("aa113")
1604   *         .findOne();
1605   * ...
1606   * }</pre>
1607   * <p>
1608   * <p>
1609   * It is also useful with finding objects by their id when you want to specify
1610   * further join information to optimise the query.
1611   * </p>
1612   * <p>
1613   * <pre>{@code
1614   *
1615   * // Fetch order 42 and additionally fetch join its order details...
1616   * Order order =
1617   *     new QOrder()
1618   *         .fetch("details") // eagerly load the order details
1619   *         .id.equalTo(42)
1620   *         .findOne();
1621   *
1622   * // the order details were eagerly loaded
1623   * List<OrderDetail> details = order.getDetails();
1624   * ...
1625   * }</pre>
1626   */
1627  @Nullable
1628  public T findOne() {
1629    return query.findOne();
1630  }
1631
1632  /**
1633   * Execute the query returning an optional bean.
1634   */
1635  @Nonnull
1636  public Optional<T> findOneOrEmpty() {
1637    return query.findOneOrEmpty();
1638  }
1639
1640  /**
1641   * Execute the query returning the list of objects.
1642   * <p>
1643   * This query will execute against the EbeanServer that was used to create it.
1644   * </p>
1645   * <p>
1646   * <pre>{@code
1647   *
1648   * List<Customer> customers =
1649   *     new QCustomer()
1650   *       .name.ilike("rob%")
1651   *       .findList();
1652   *
1653   * }</pre>
1654   *
1655   * @see Query#findList()
1656   */
1657  @Nonnull
1658  public List<T> findList() {
1659    return query.findList();
1660  }
1661
1662  /**
1663   * Execute the query returning the result as a Stream.
1664   * <p>
1665   * Note that this can support very large queries iterating
1666   * any number of results. To do so internally it can use
1667   * multiple persistence contexts.
1668   * </p>
1669   * <pre>{@code
1670   *
1671   *  // use try with resources to ensure Stream is closed
1672   *
1673   *  try (Stream<Customer> stream = query.findStream()) {
1674   *    stream
1675   *    .map(...)
1676   *    .collect(...);
1677   *  }
1678   *
1679   * }</pre>
1680   */
1681  @Nonnull
1682  public Stream<T> findStream() {
1683    return query.findStream();
1684  }
1685
1686  /**
1687   * Deprecated - migrate to findStream().
1688   */
1689  @Deprecated
1690  public Stream<T> findLargeStream() {
1691    return query.findLargeStream();
1692  }
1693
1694  /**
1695   * Execute the query returning the set of objects.
1696   * <p>
1697   * This query will execute against the EbeanServer that was used to create it.
1698   * </p>
1699   * <p>
1700   * <pre>{@code
1701   *
1702   * Set<Customer> customers =
1703   *     new QCustomer()
1704   *       .name.ilike("rob%")
1705   *       .findSet();
1706   *
1707   * }</pre>
1708   *
1709   * @see Query#findSet()
1710   */
1711  @Nonnull
1712  public Set<T> findSet() {
1713    return query.findSet();
1714  }
1715
1716  /**
1717   * Execute the query returning the list of Id's.
1718   * <p>
1719   * This query will execute against the EbeanServer that was used to create it.
1720   * </p>
1721   *
1722   * @see Query#findIds()
1723   */
1724  @Nonnull
1725  public <A> List<A> findIds() {
1726    return query.findIds();
1727  }
1728
1729  /**
1730   * Execute the query returning a map of the objects.
1731   * <p>
1732   * This query will execute against the EbeanServer that was used to create it.
1733   * </p>
1734   * <p>
1735   * You can use setMapKey() or asMapKey() to specify the property to be used as keys
1736   * on the map. If one is not specified then the id property is used.
1737   * </p>
1738   * <p>
1739   * <pre>{@code
1740   *
1741   * Map<String, Product> map =
1742   *   new QProduct()
1743   *     .sku.asMapKey()
1744   *     .findMap();
1745   *
1746   * }</pre>
1747   *
1748   * @see Query#findMap()
1749   */
1750  @Nonnull
1751  public <K> Map<K, T> findMap() {
1752    return query.findMap();
1753  }
1754
1755  /**
1756   * Execute the query iterating over the results.
1757   * <p>
1758   * Note that findIterate (and findEach and findEachWhile) uses a "per graph"
1759   * persistence context scope and adjusts jdbc fetch buffer size for large
1760   * queries. As such it is better to use findList for small queries.
1761   * </p>
1762   * <p>
1763   * Remember that with {@link QueryIterator} you must call {@link QueryIterator#close()}
1764   * when you have finished iterating the results (typically in a finally block).
1765   * </p>
1766   * <p>
1767   * findEach() and findEachWhile() are preferred to findIterate() as they ensure
1768   * the jdbc statement and resultSet are closed at the end of the iteration.
1769   * </p>
1770   * <p>
1771   * This query will execute against the EbeanServer that was used to create it.
1772   * </p>
1773   * <pre>{@code
1774   *
1775   *  Query<Customer> query =
1776   *    new QCustomer()
1777   *     .status.equalTo(Customer.Status.NEW)
1778   *     .orderBy()
1779   *       id.asc()
1780   *     .query();
1781   *
1782   *  try (QueryIterator<Customer> it = query.findIterate()) {
1783   *    while (it.hasNext()) {
1784   *      Customer customer = it.next();
1785   *      // do something with customer ...
1786   *    }
1787   *  }
1788   *
1789   * }</pre>
1790   */
1791  @Nonnull
1792  public QueryIterator<T> findIterate() {
1793    return query.findIterate();
1794  }
1795
1796  /**
1797   * Execute the query returning a list of values for a single property.
1798   * <p>
1799   * <h3>Example</h3>
1800   * <pre>{@code
1801   *
1802   *  List<String> names =
1803   *    new QCustomer()
1804   *      .setDistinct(true)
1805   *      .select(name)
1806   *      .findSingleAttributeList();
1807   *
1808   * }</pre>
1809   *
1810   * @return the list of values for the selected property
1811   */
1812  @Nonnull
1813  public <A> List<A> findSingleAttributeList() {
1814    return query.findSingleAttributeList();
1815  }
1816
1817  /**
1818   * Execute the query returning a single value for a single property.
1819   * <p>
1820   * <h3>Example</h3>
1821   * <pre>{@code
1822   *
1823   *  LocalDate maxDate =
1824   *    new QCustomer()
1825   *      .select("max(startDate)")
1826   *      .findSingleAttribute();
1827   *
1828   * }</pre>
1829   *
1830   * @return the list of values for the selected property
1831   */
1832  public <A> A findSingleAttribute() {
1833    return query.findSingleAttribute();
1834  }
1835
1836  /**
1837   * Execute the query processing the beans one at a time.
1838   * <p>
1839   * This method is appropriate to process very large query results as the
1840   * beans are consumed one at a time and do not need to be held in memory
1841   * (unlike #findList #findSet etc)
1842   * </p>
1843   * <p>
1844   * Note that internally Ebean can inform the JDBC driver that it is expecting larger
1845   * resultSet and specifically for MySQL this hint is required to stop it's JDBC driver
1846   * from buffering the entire resultSet. As such, for smaller resultSets findList() is
1847   * generally preferable.
1848   * </p>
1849   * <p>
1850   * Compared with #findEachWhile this will always process all the beans where as
1851   * #findEachWhile provides a way to stop processing the query result early before
1852   * all the beans have been read.
1853   * </p>
1854   * <p>
1855   * This method is functionally equivalent to findIterate() but instead of using an
1856   * iterator uses the QueryEachConsumer (SAM) interface which is better suited to use
1857   * with Java8 closures.
1858   * </p>
1859   * <p>
1860   * <pre>{@code
1861   *
1862   *  new QCustomer()
1863   *     .status.equalTo(Status.NEW)
1864   *     .orderBy().id.asc()
1865   *     .findEach((Customer customer) -> {
1866   *
1867   *       // do something with customer
1868   *       System.out.println("-- visit " + customer);
1869   *     });
1870   *
1871   * }</pre>
1872   *
1873   * @param consumer the consumer used to process the queried beans.
1874   */
1875  public void findEach(Consumer<T> consumer) {
1876    query.findEach(consumer);
1877  }
1878
1879  /**
1880   * Execute the query using callbacks to a visitor to process the resulting
1881   * beans one at a time.
1882   * <p>
1883   * This method is functionally equivalent to findIterate() but instead of using an
1884   * iterator uses the QueryEachWhileConsumer (SAM) interface which is better suited to use
1885   * with Java8 closures.
1886   * </p>
1887   * <p>
1888   * <p>
1889   * <pre>{@code
1890   *
1891   *  new QCustomer()
1892   *     .status.equalTo(Status.NEW)
1893   *     .orderBy().id.asc()
1894   *     .findEachWhile((Customer customer) -> {
1895   *
1896   *       // do something with customer
1897   *       System.out.println("-- visit " + customer);
1898   *
1899   *       // return true to continue processing or false to stop
1900   *       return (customer.getId() < 40);
1901   *     });
1902   *
1903   * }</pre>
1904   *
1905   * @param consumer the consumer used to process the queried beans.
1906   */
1907  public void findEachWhile(Predicate<T> consumer) {
1908    query.findEachWhile(consumer);
1909  }
1910
1911  /**
1912   * Return versions of a @History entity bean.
1913   * <p>
1914   * Generally this query is expected to be a find by id or unique predicates query.
1915   * It will execute the query against the history returning the versions of the bean.
1916   * </p>
1917   */
1918  @Nonnull
1919  public List<Version<T>> findVersions() {
1920    return query.findVersions();
1921  }
1922
1923  /**
1924   * Return versions of a @History entity bean between a start and end timestamp.
1925   * <p>
1926   * Generally this query is expected to be a find by id or unique predicates query.
1927   * It will execute the query against the history returning the versions of the bean.
1928   * </p>
1929   */
1930  @Nonnull
1931  public List<Version<T>> findVersionsBetween(Timestamp start, Timestamp end) {
1932    return query.findVersionsBetween(start, end);
1933  }
1934
1935  /**
1936   * Return the count of entities this query should return.
1937   * <p>
1938   * This is the number of 'top level' or 'root level' entities.
1939   * </p>
1940   */
1941  @Nonnull
1942  public int findCount() {
1943    return query.findCount();
1944  }
1945
1946  /**
1947   * Execute find row count query in a background thread.
1948   * <p>
1949   * This returns a Future object which can be used to cancel, check the
1950   * execution status (isDone etc) and get the value (with or without a
1951   * timeout).
1952   * </p>
1953   *
1954   * @return a Future object for the row count query
1955   */
1956  @Nonnull
1957  public FutureRowCount<T> findFutureCount() {
1958    return query.findFutureCount();
1959  }
1960
1961  /**
1962   * Execute find Id's query in a background thread.
1963   * <p>
1964   * This returns a Future object which can be used to cancel, check the
1965   * execution status (isDone etc) and get the value (with or without a
1966   * timeout).
1967   * </p>
1968   *
1969   * @return a Future object for the list of Id's
1970   */
1971  @Nonnull
1972  public FutureIds<T> findFutureIds() {
1973    return query.findFutureIds();
1974  }
1975
1976  /**
1977   * Execute find list query in a background thread.
1978   * <p>
1979   * This query will execute in it's own PersistenceContext and using its own transaction.
1980   * What that means is that it will not share any bean instances with other queries.
1981   * </p>
1982   *
1983   * @return a Future object for the list result of the query
1984   */
1985  @Nonnull
1986  public FutureList<T> findFutureList() {
1987    return query.findFutureList();
1988  }
1989
1990  /**
1991   * Return a PagedList for this query using firstRow and maxRows.
1992   * <p>
1993   * The benefit of using this over findList() is that it provides functionality to get the
1994   * total row count etc.
1995   * </p>
1996   * <p>
1997   * If maxRows is not set on the query prior to calling findPagedList() then a
1998   * PersistenceException is thrown.
1999   * </p>
2000   * <p>
2001   * <pre>{@code
2002   *
2003   *  PagedList<Order> pagedList =
2004   *    new QOrder()
2005   *       .setFirstRow(50)
2006   *       .setMaxRows(20)
2007   *       .findPagedList();
2008   *
2009   *       // fetch the total row count in the background
2010   *       pagedList.loadRowCount();
2011   *
2012   *       List<Order> orders = pagedList.getList();
2013   *       int totalRowCount = pagedList.getTotalRowCount();
2014   *
2015   * }</pre>
2016   *
2017   * @return The PagedList
2018   */
2019  @Nonnull
2020  public PagedList<T> findPagedList() {
2021    return query.findPagedList();
2022  }
2023
2024  /**
2025   * Execute as a delete query deleting the 'root level' beans that match the predicates
2026   * in the query.
2027   * <p>
2028   * Note that if the query includes joins then the generated delete statement may not be
2029   * optimal depending on the database platform.
2030   * </p>
2031   *
2032   * @return the number of beans/rows that were deleted.
2033   */
2034  public int delete() {
2035    return query.delete();
2036  }
2037
2038  /**
2039   * Return the sql that was generated for executing this query.
2040   * <p>
2041   * This is only available after the query has been executed and provided only
2042   * for informational purposes.
2043   * </p>
2044   */
2045  public String getGeneratedSql() {
2046    return query.getGeneratedSql();
2047  }
2048
2049  /**
2050   * Return the type of beans being queried.
2051   */
2052  @Nonnull
2053  public Class<T> getBeanType() {
2054    return query.getBeanType();
2055  }
2056
2057  /**
2058   * Return the expression list that has been built for this query.
2059   */
2060  @Nonnull
2061  public ExpressionList<T> getExpressionList() {
2062    return query.where();
2063  }
2064
2065  /**
2066   * Start adding expressions to the having clause when using @Aggregation properties.
2067   *
2068   * <pre>{@code
2069   *
2070   *   new QMachineUse()
2071   *   // where ...
2072   *   .date.inRange(fromDate, toDate)
2073   *
2074   *   .having()
2075   *   .sumHours.greaterThan(1)
2076   *   .findList()
2077   *
2078   *   // The sumHours property uses @Aggregation
2079   *   // e.g. @Aggregation("sum(hours)")
2080   *
2081   * }</pre>
2082   */
2083  public R having() {
2084    if (whereStack == null) {
2085      whereStack = new ArrayStack<>();
2086    }
2087    // effectively putting having expression list onto stack
2088    // such that expression now add to the having clause
2089    whereStack.push(query.having());
2090    return root;
2091  }
2092
2093  /**
2094   * Return the underlying having clause to typically when using dynamic aggregation formula.
2095   * <p>
2096   * Note that after this we no longer have the query bean so typically we use this right
2097   * at the end of the query.
2098   * </p>
2099   *
2100   * <pre>{@code
2101   *
2102   *  // sum(distanceKms) ... is a "dynamic formula"
2103   *  // so we use havingClause() for it like:
2104   *
2105   *  List<MachineUse> machineUse =
2106   *
2107   *    new QMachineUse()
2108   *      .select("machine, sum(fuelUsed), sum(distanceKms)")
2109   *
2110   *      // where ...
2111   *      .date.greaterThan(LocalDate.now().minusDays(7))
2112   *
2113   *      .havingClause()
2114   *        .gt("sum(distanceKms)", 2)
2115   *        .findList();
2116   *
2117   * }</pre>
2118   */
2119  public ExpressionList<T> havingClause() {
2120    return query.having();
2121  }
2122
2123  /**
2124   * Return the current expression list that expressions should be added to.
2125   */
2126  protected ExpressionList<T> peekExprList() {
2127
2128    if (textMode) {
2129      // return the current text expression list
2130      return _peekText();
2131    }
2132
2133    if (whereStack == null) {
2134      whereStack = new ArrayStack<>();
2135      whereStack.push(query.where());
2136    }
2137    // return the current expression list
2138    return whereStack.peek();
2139  }
2140
2141  protected ExpressionList<T> _peekText() {
2142    if (textStack == null) {
2143      textStack = new ArrayStack<>();
2144      // empty so push on the queries base expression list
2145      textStack.push(query.text());
2146    }
2147    // return the current expression list
2148    return textStack.peek();
2149  }
2150}