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