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   * executed the select with "for update" which should lock the record "on read"
690   */
691  public R forUpdate() {
692    query.forUpdate();
693    return root;
694  }
695
696  /**
697   * Execute using "for update" clause with "no wait" option.
698   * <p>
699   * This is typically a Postgres and Oracle only option at this stage.
700   * </p>
701   */
702  public R forUpdateNoWait() {
703    query.forUpdateNoWait();
704    return root;
705  }
706
707  /**
708   * Execute using "for update" clause with "skip locked" option.
709   * <p>
710   * This is typically a Postgres and Oracle only option at this stage.
711   * </p>
712   */
713  public R forUpdateSkipLocked() {
714    query.forUpdateSkipLocked();
715    return root;
716  }
717
718  /**
719   * Return this query as an UpdateQuery.
720   *
721   * <pre>{@code
722   *
723   *   int rows =
724   *     new QCustomer()
725   *     .name.startsWith("Rob")
726   *     .organisation.id.equalTo(42)
727   *     .asUpdate()
728   *       .set("active", false)
729   *       .update()
730   *
731   * }</pre>
732   *
733   * @return This query as an UpdateQuery
734   */
735  public UpdateQuery<T> asUpdate() {
736    return query.asUpdate();
737  }
738
739  /**
740   * Convert the query to a DTO bean query.
741   * <p>
742   * We effectively use the underlying ORM query to build the SQL and then execute
743   * and map it into DTO beans.
744   */
745  public <D> DtoQuery<D> asDto(Class<D> dtoClass) {
746    return query.asDto(dtoClass);
747  }
748
749  /**
750   * Set the Id value to query. This is used with findOne().
751   * <p>
752   * You can use this to have further control over the query. For example adding
753   * fetch joins.
754   * </p>
755   * <p>
756   * <pre>{@code
757   *
758   * Order order =
759   *   new QOrder()
760   *     .setId(1)
761   *     .fetch("details")
762   *     .findOne();
763   *
764   * // the order details were eagerly fetched
765   * List<OrderDetail> details = order.getDetails();
766   *
767   * }</pre>
768   */
769  public R setId(Object id) {
770    query.setId(id);
771    return root;
772  }
773
774  /**
775   * Set a list of Id values to match.
776   * <p>
777   * <pre>{@code
778   *
779   * List<Order> orders =
780   *   new QOrder()
781   *     .setIdIn(42, 43, 44)
782   *     .findList();
783   *
784   * // the order details were eagerly fetched
785   * List<OrderDetail> details = order.getDetails();
786   *
787   * }</pre>
788   */
789  public R setIdIn(Object... ids) {
790    query.where().idIn(ids);
791    return root;
792  }
793
794  /**
795   * Set a label on the query.
796   * <p>
797   * This label can be used to help identify query performance metrics but we can also use
798   * profile location enhancement on Finders so for some that would be a better option.
799   * </p>
800   */
801  public R setLabel(String label) {
802    query.setLabel(label);
803    return root;
804  }
805
806  /**
807   * Set the profile location.
808   * <p>
809   * This is typically set automatically via enhancement when profile location enhancement
810   * is turned on. It is generally not set by application code.
811   * </p>
812   */
813  public R setProfileLocation(ProfileLocation profileLocation) {
814    query.setProfileLocation(profileLocation);
815    return root;
816  }
817
818  /**
819   * Set the default lazy loading batch size to use.
820   * <p>
821   * When lazy loading is invoked on beans loaded by this query then this sets the
822   * batch size used to load those beans.
823   *
824   * @param lazyLoadBatchSize the number of beans to lazy load in a single batch
825   */
826  public R setLazyLoadBatchSize(int lazyLoadBatchSize) {
827    query.setLazyLoadBatchSize(lazyLoadBatchSize);
828    return root;
829  }
830
831  /**
832   * When set to true all the beans from this query are loaded into the bean
833   * cache.
834   */
835  public R setLoadBeanCache(boolean loadBeanCache) {
836    query.setLoadBeanCache(loadBeanCache);
837    return root;
838  }
839
840  /**
841   * Set the property to use as keys for a map.
842   * <p>
843   * If no property is set then the id property is used.
844   * </p>
845   * <p>
846   * <pre>{@code
847   *
848   * // Assuming sku is unique for products...
849   *
850   * Map<String,Product> productMap =
851   *     new QProduct()
852   *     // use sku for keys...
853   *     .setMapKey("sku")
854   *     .findMap();
855   *
856   * }</pre>
857   *
858   * @param mapKey the property to use as keys for a map.
859   */
860  public R setMapKey(String mapKey) {
861    query.setMapKey(mapKey);
862    return root;
863  }
864
865  /**
866   * Specify the PersistenceContextScope to use for this query.
867   * <p>
868   * When this is not set the 'default' configured on {@link io.ebean.config.ServerConfig#setPersistenceContextScope(PersistenceContextScope)}
869   * is used - this value defaults to {@link io.ebean.PersistenceContextScope#TRANSACTION}.
870   * <p>
871   * Note that the same persistence Context is used for subsequent lazy loading and query join queries.
872   * <p>
873   * Note that #findEach uses a 'per object graph' PersistenceContext so this scope is ignored for
874   * queries executed as #findIterate, #findEach, #findEachWhile.
875   *
876   * @param scope The scope to use for this query and subsequent lazy loading.
877   */
878  public R setPersistenceContextScope(PersistenceContextScope scope) {
879    query.setPersistenceContextScope(scope);
880    return root;
881  }
882
883  /**
884   * Set RawSql to use for this query.
885   */
886  public R setRawSql(RawSql rawSql) {
887    query.setRawSql(rawSql);
888    return root;
889  }
890
891  /**
892   * When set to true when you want the returned beans to be read only.
893   */
894  public R setReadOnly(boolean readOnly) {
895    query.setReadOnly(readOnly);
896    return root;
897  }
898
899  /**
900   * Set this to true to use the bean cache.
901   * <p>
902   * If the query result is in cache then by default this same instance is
903   * returned. In this sense it should be treated as a read only object graph.
904   * </p>
905   */
906  public R setUseCache(boolean useCache) {
907    query.setUseCache(useCache);
908    return root;
909  }
910
911
912  /**
913   * Set the mode to use the bean cache when executing this query.
914   * <p>
915   * By default "find by id" and "find by natural key" will use the bean cache
916   * when bean caching is enabled. Setting this to false means that the query
917   * will not use the bean cache and instead hit the database.
918   * </p>
919   * <p>
920   * By default findList() with natural keys will not use the bean cache. In that
921   * case we need to explicitly use the bean cache.
922   * </p>
923   */
924  public R setBeanCacheMode(CacheMode beanCacheMode) {
925    query.setBeanCacheMode(beanCacheMode);
926    return root;
927  }
928
929  /**
930   * Set to true if this query should execute against the doc store.
931   * <p>
932   * When setting this you may also consider disabling lazy loading.
933   * </p>
934   */
935  public R setUseDocStore(boolean useDocStore) {
936    query.setUseDocStore(useDocStore);
937    return root;
938  }
939
940  /**
941   * Set true if you want to disable lazy loading.
942   * <p>
943   * That is, once the object graph is returned further lazy loading is disabled.
944   * </p>
945   */
946  public R setDisableLazyLoading(boolean disableLazyLoading) {
947    query.setDisableLazyLoading(disableLazyLoading);
948    return root;
949  }
950
951  /**
952   * Disable read auditing for this query.
953   * <p>
954   * This is intended to be used when the query is not a user initiated query and instead
955   * part of the internal processing in an application to load a cache or document store etc.
956   * In these cases we don't want the query to be part of read auditing.
957   * </p>
958   */
959  public R setDisableReadAuditing() {
960    query.setDisableReadAuditing();
961    return root;
962  }
963
964  /**
965   * Set this to true to use the query cache.
966   */
967  public R setUseQueryCache(boolean useCache) {
968    query.setUseQueryCache(useCache);
969    return root;
970  }
971
972  /**
973   * Set the {@link CacheMode} to use the query for executing this query.
974   */
975  public R setUseQueryCache(CacheMode cacheMode) {
976    query.setUseQueryCache(cacheMode);
977    return root;
978  }
979
980  /**
981   * Set a timeout on this query.
982   * <p>
983   * This will typically result in a call to setQueryTimeout() on a
984   * preparedStatement. If the timeout occurs an exception will be thrown - this
985   * will be a SQLException wrapped up in a PersistenceException.
986   * </p>
987   *
988   * @param secs the query timeout limit in seconds. Zero means there is no limit.
989   */
990  public R setTimeout(int secs) {
991    query.setTimeout(secs);
992    return root;
993  }
994
995  /**
996   * Returns the set of properties or paths that are unknown (do not map to known properties or paths).
997   * <p>
998   * Validate the query checking the where and orderBy expression paths to confirm if
999   * they represent valid properties or paths for the given bean type.
1000   * </p>
1001   */
1002  public Set<String> validate() {
1003    return query.validate();
1004  }
1005
1006  /**
1007   * Add raw expression with no parameters.
1008   * <p>
1009   * When properties in the clause are fully qualified as table-column names
1010   * then they are not translated. logical property name names (not fully
1011   * qualified) will still be translated to their physical name.
1012   * </p>
1013   * <p>
1014   * <pre>{@code
1015   *
1016   *   raw("orderQty < shipQty")
1017   *
1018   * }</pre>
1019   *
1020   * <h4>Subquery example:</h4>
1021   * <pre>{@code
1022   *
1023   *   .raw("t0.customer_id in (select customer_id from customer_group where group_id = any(?::uuid[]))", groupIds)
1024   *
1025   * }</pre>
1026   */
1027  public R raw(String rawExpression) {
1028    peekExprList().raw(rawExpression);
1029    return root;
1030  }
1031
1032  /**
1033   * Add raw expression with an array of parameters.
1034   * <p>
1035   * The raw expression should contain the same number of ? as there are
1036   * parameters.
1037   * </p>
1038   * <p>
1039   * When properties in the clause are fully qualified as table-column names
1040   * then they are not translated. logical property name names (not fully
1041   * qualified) will still be translated to their physical name.
1042   * </p>
1043   */
1044  public R raw(String rawExpression, Object... bindValues) {
1045    peekExprList().raw(rawExpression, bindValues);
1046    return root;
1047  }
1048
1049  /**
1050   * Only add the raw expression if the values is not null or empty.
1051   * <p>
1052   * This is a pure convenience expression to make it nicer to deal with the pattern where we use
1053   * raw() expression with a subquery and only want to add the subquery predicate when the collection
1054   * of values is not empty.
1055   * </p>
1056   * <h3>Without inOrEmpty()</h3>
1057   * <pre>{@code
1058   *
1059   *   QCustomer query = new QCustomer() // add some predicates
1060   *     .status.equalTo(Status.NEW);
1061   *
1062   *   // common pattern - we can use rawOrEmpty() instead
1063   *   if (orderIds != null && !orderIds.isEmpty()) {
1064   *     query.raw("t0.customer_id in (select o.customer_id from orders o where o.id in (?1))", orderIds);
1065   *   }
1066   *
1067   *   query.findList();
1068   *
1069   * }</pre>
1070   *
1071   * <h3>Using rawOrEmpty()</h3>
1072   * Note that in the example below we use the <code>?1</code> bind parameter to get  "parameter expansion"
1073   * for each element in the collection.
1074   *
1075   * <pre>{@code
1076   *
1077   *   new QCustomer()
1078   *     .status.equalTo(Status.NEW)
1079   *     // only add the expression if orderIds is not empty
1080   *     .rawOrEmpty("t0.customer_id in (select o.customer_id from orders o where o.id in (?1))", orderIds);
1081   *     .findList();
1082   *
1083   * }</pre>
1084   *
1085   * <h3>Postgres ANY</h3>
1086   * With Postgres we would often use the SQL <code>ANY</code> expression and array parameter binding
1087   * rather than <code>IN</code>.
1088   *
1089   * <pre>{@code
1090   *
1091   *   new QCustomer()
1092   *     .status.equalTo(Status.NEW)
1093   *     .rawOrEmpty("t0.customer_id in (select o.customer_id from orders o where o.id = any(?))", orderIds);
1094   *     .findList();
1095   *
1096   * }</pre>
1097   * <p>
1098   * Note that we need to cast the Postgres array for UUID types like:
1099   * </p>
1100   * <pre>{@code
1101   *
1102   *   " ... = any(?::uuid[])"
1103   *
1104   * }</pre>
1105   *
1106   * @param raw    The raw expression that is typically a subquery
1107   * @param values The values which is typically a list or set of id values.
1108   */
1109  public R rawOrEmpty(String raw, Collection<?> values) {
1110    peekExprList().rawOrEmpty(raw, values);
1111    return root;
1112  }
1113
1114  /**
1115   * Add raw expression with a single parameter.
1116   * <p>
1117   * The raw expression should contain a single ? at the location of the
1118   * parameter.
1119   * </p>
1120   * <p>
1121   * When properties in the clause are fully qualified as table-column names
1122   * then they are not translated. logical property name names (not fully
1123   * qualified) will still be translated to their physical name.
1124   * </p>
1125   * <p>
1126   * <h4>Example:</h4>
1127   * <pre>{@code
1128   *
1129   *   // use a database function
1130   *   raw("add_days(orderDate, 10) < ?", someDate)
1131   *
1132   * }</pre>
1133   *
1134   * <h4>Subquery example:</h4>
1135   * <pre>{@code
1136   *
1137   *   .raw("t0.customer_id in (select customer_id from customer_group where group_id = any(?::uuid[]))", groupIds)
1138   *
1139   * }</pre>
1140   */
1141  public R raw(String rawExpression, Object bindValue) {
1142    peekExprList().raw(rawExpression, bindValue);
1143    return root;
1144  }
1145
1146  /**
1147   * Deprecated migrate to order().
1148   */
1149  @Deprecated
1150  public R orderBy() {
1151    // Yes this does not actually do anything! We include it because style wise it makes
1152    // the query nicer to read and suggests that order by definitions are added after this
1153    return root;
1154  }
1155
1156  /**
1157   * Marker that can be used to indicate that the order by clause is defined after this.
1158   * <p>
1159   * <h2>Example: order by customer name, order date</h2>
1160   * <pre>{@code
1161   *   List<Order> orders =
1162   *          new QOrder()
1163   *            .customer.name.ilike("rob")
1164   *            .order()
1165   *              .customer.name.asc()
1166   *              .orderDate.asc()
1167   *            .findList();
1168   *
1169   * }</pre>
1170   */
1171  public R order() {
1172    // Yes this does not actually do anything! We include it because style wise it makes
1173    // the query nicer to read and suggests that order by definitions are added after this
1174    return root;
1175  }
1176
1177
1178  /**
1179   * Deprecated migrate to {@link #order(String)}.
1180   */
1181  @Deprecated
1182  public R orderBy(String orderByClause) {
1183    query.orderBy(orderByClause);
1184    return root;
1185  }
1186
1187  /**
1188   * Set the full raw order by clause replacing the existing order by clause if there is one.
1189   * <p>
1190   * This follows SQL syntax using commas between each property with the
1191   * optional asc and desc keywords representing ascending and descending order
1192   * respectively.
1193   */
1194  public R order(String orderByClause) {
1195    query.order(orderByClause);
1196    return root;
1197  }
1198
1199  /**
1200   * Begin a list of expressions added by 'OR'.
1201   * <p>
1202   * Use endOr() or endJunction() to stop added to OR and 'pop' to the parent expression list.
1203   * </p>
1204   * <p>
1205   * <h2>Example</h2>
1206   * <p>
1207   * This example uses an 'OR' expression list with an inner 'AND' expression list.
1208   * </p>
1209   * <pre>{@code
1210   *
1211   *    List<Customer> customers =
1212   *          new QCustomer()
1213   *            .status.equalTo(Customer.Status.GOOD)
1214   *            .or()
1215   *              .id.greaterThan(1000)
1216   *              .and()
1217   *                .name.startsWith("super")
1218   *                .registered.after(fiveDaysAgo)
1219   *              .endAnd()
1220   *            .endOr()
1221   *            .orderBy().id.desc()
1222   *            .findList();
1223   *
1224   * }</pre>
1225   * <h2>Resulting SQL where clause</h2>
1226   * <pre>{@code sql
1227   *
1228   *    where t0.status = ?  and (t0.id > ?  or (t0.name like ?  and t0.registered > ? ) )
1229   *    order by t0.id desc;
1230   *
1231   *    --bind(GOOD,1000,super%,Wed Jul 22 00:00:00 NZST 2015)
1232   *
1233   * }</pre>
1234   */
1235  public R or() {
1236    pushExprList(peekExprList().or());
1237    return root;
1238  }
1239
1240  /**
1241   * Begin a list of expressions added by 'AND'.
1242   * <p>
1243   * Use endAnd() or endJunction() to stop added to AND and 'pop' to the parent expression list.
1244   * </p>
1245   * <p>
1246   * Note that typically the AND expression is only used inside an outer 'OR' expression.
1247   * This is because the top level expression list defaults to an 'AND' expression list.
1248   * </p>
1249   * <h2>Example</h2>
1250   * <p>
1251   * This example uses an 'OR' expression list with an inner 'AND' expression list.
1252   * </p>
1253   * <pre>{@code
1254   *
1255   *    List<Customer> customers =
1256   *          new QCustomer()
1257   *            .status.equalTo(Customer.Status.GOOD)
1258   *            .or() // OUTER 'OR'
1259   *              .id.greaterThan(1000)
1260   *              .and()  // NESTED 'AND' expression list
1261   *                .name.startsWith("super")
1262   *                .registered.after(fiveDaysAgo)
1263   *                .endAnd()
1264   *              .endOr()
1265   *            .orderBy().id.desc()
1266   *            .findList();
1267   *
1268   * }</pre>
1269   * <h2>Resulting SQL where clause</h2>
1270   * <pre>{@code sql
1271   *
1272   *    where t0.status = ?  and (t0.id > ?  or (t0.name like ?  and t0.registered > ? ) )
1273   *    order by t0.id desc;
1274   *
1275   *    --bind(GOOD,1000,super%,Wed Jul 22 00:00:00 NZST 2015)
1276   *
1277   * }</pre>
1278   */
1279  public R and() {
1280    pushExprList(peekExprList().and());
1281    return root;
1282  }
1283
1284  /**
1285   * Begin a list of expressions added by NOT.
1286   * <p>
1287   * Use endNot() or endJunction() to stop added to NOT and 'pop' to the parent expression list.
1288   * </p>
1289   */
1290  public R not() {
1291    pushExprList(peekExprList().not());
1292    return root;
1293  }
1294
1295  /**
1296   * Begin a list of expressions added by MUST.
1297   * <p>
1298   * This automatically makes this query a document store query.
1299   * </p>
1300   * <p>
1301   * Use endJunction() to stop added to MUST and 'pop' to the parent expression list.
1302   * </p>
1303   */
1304  public R must() {
1305    pushExprList(peekExprList().must());
1306    return root;
1307  }
1308
1309  /**
1310   * Begin a list of expressions added by MUST NOT.
1311   * <p>
1312   * This automatically makes this query a document store query.
1313   * </p>
1314   * <p>
1315   * Use endJunction() to stop added to MUST NOT and 'pop' to the parent expression list.
1316   * </p>
1317   */
1318  public R mustNot() {
1319    return pushExprList(peekExprList().mustNot());
1320  }
1321
1322  /**
1323   * Begin a list of expressions added by SHOULD.
1324   * <p>
1325   * This automatically makes this query a document store query.
1326   * </p>
1327   * <p>
1328   * Use endJunction() to stop added to SHOULD and 'pop' to the parent expression list.
1329   * </p>
1330   */
1331  public R should() {
1332    return pushExprList(peekExprList().should());
1333  }
1334
1335  /**
1336   * End a list of expressions added by 'OR'.
1337   */
1338  public R endJunction() {
1339    if (textMode) {
1340      textStack.pop();
1341    } else {
1342      whereStack.pop();
1343    }
1344    return root;
1345  }
1346
1347  /**
1348   * End OR junction - synonym for endJunction().
1349   */
1350  public R endOr() {
1351    return endJunction();
1352  }
1353
1354  /**
1355   * End AND junction - synonym for endJunction().
1356   */
1357  public R endAnd() {
1358    return endJunction();
1359  }
1360
1361  /**
1362   * End NOT junction - synonym for endJunction().
1363   */
1364  public R endNot() {
1365    return endJunction();
1366  }
1367
1368  /**
1369   * Push the expression list onto the appropriate stack.
1370   */
1371  private R pushExprList(ExpressionList<T> list) {
1372    if (textMode) {
1373      textStack.push(list);
1374    } else {
1375      whereStack.push(list);
1376    }
1377    return root;
1378  }
1379
1380  /**
1381   * Add expression after this to the WHERE expression list.
1382   * <p>
1383   * For queries against the normal database (not the doc store) this has no effect.
1384   * </p>
1385   * <p>
1386   * This is intended for use with Document Store / ElasticSearch where expressions can be put into either
1387   * the "query" section or the "filter" section of the query. Full text expressions like MATCH are in the
1388   * "query" section but many expression can be in either - expressions after the where() are put into the
1389   * "filter" section which means that they don't add to the relevance and are also cache-able.
1390   * </p>
1391   */
1392  public R where() {
1393    textMode = false;
1394    return root;
1395  }
1396
1397  /**
1398   * Begin added expressions to the 'Text' expression list.
1399   * <p>
1400   * This automatically makes the query a document store query.
1401   * </p>
1402   * <p>
1403   * For ElasticSearch expressions added to 'text' go into the ElasticSearch 'query context'
1404   * and expressions added to 'where' go into the ElasticSearch 'filter context'.
1405   * </p>
1406   */
1407  public R text() {
1408    textMode = true;
1409    return root;
1410  }
1411
1412  /**
1413   * Add a Text Multi-match expression (document store only).
1414   * <p>
1415   * This automatically makes the query a document store query.
1416   * </p>
1417   */
1418  public R multiMatch(String query, MultiMatch multiMatch) {
1419    peekExprList().multiMatch(query, multiMatch);
1420    return root;
1421  }
1422
1423  /**
1424   * Add a Text Multi-match expression (document store only).
1425   * <p>
1426   * This automatically makes the query a document store query.
1427   * </p>
1428   */
1429  public R multiMatch(String query, String... properties) {
1430    peekExprList().multiMatch(query, properties);
1431    return root;
1432  }
1433
1434  /**
1435   * Add a Text common terms expression (document store only).
1436   * <p>
1437   * This automatically makes the query a document store query.
1438   * </p>
1439   */
1440  public R textCommonTerms(String query, TextCommonTerms options) {
1441    peekExprList().textCommonTerms(query, options);
1442    return root;
1443  }
1444
1445  /**
1446   * Add a Text simple expression (document store only).
1447   * <p>
1448   * This automatically makes the query a document store query.
1449   * </p>
1450   */
1451  public R textSimple(String query, TextSimple options) {
1452    peekExprList().textSimple(query, options);
1453    return root;
1454  }
1455
1456  /**
1457   * Add a Text query string expression (document store only).
1458   * <p>
1459   * This automatically makes the query a document store query.
1460   * </p>
1461   */
1462  public R textQueryString(String query, TextQueryString options) {
1463    peekExprList().textQueryString(query, options);
1464    return root;
1465  }
1466
1467  /**
1468   * Execute the query using the given transaction.
1469   */
1470  public R usingTransaction(Transaction transaction) {
1471    query.usingTransaction(transaction);
1472    return root;
1473  }
1474
1475  /**
1476   * Execute the query using the given connection.
1477   */
1478  public R usingConnection(Connection connection) {
1479    query.usingConnection(connection);
1480    return root;
1481  }
1482
1483  /**
1484   * Execute the query returning true if a row is found.
1485   * <p>
1486   * The query is executed using max rows of 1 and will only select the id property.
1487   * This method is really just a convenient way to optimise a query to perform a
1488   * 'does a row exist in the db' check.
1489   * </p>
1490   *
1491   * <h2>Example using a query bean:</h2>
1492   * <pre>{@code
1493   *
1494   *   boolean userExists =
1495   *     new QContact()
1496   *       .email.equalTo("rob@foo.com")
1497   *       .exists();
1498   *
1499   * }</pre>
1500   *
1501   * <h2>Example:</h2>
1502   * <pre>{@code
1503   *
1504   *   boolean userExists = query()
1505   *     .where().eq("email", "rob@foo.com")
1506   *     .exists();
1507   *
1508   * }</pre>
1509   *
1510   * @return True if the query finds a matching row in the database
1511   */
1512  public boolean exists() {
1513    return query.exists();
1514  }
1515
1516  /**
1517   * Execute the query returning either a single bean or null (if no matching
1518   * bean is found).
1519   * <p>
1520   * If more than 1 row is found for this query then a PersistenceException is
1521   * thrown.
1522   * </p>
1523   * <p>
1524   * This is useful when your predicates dictate that your query should only
1525   * return 0 or 1 results.
1526   * </p>
1527   * <p>
1528   * <pre>{@code
1529   *
1530   * // assuming the sku of products is unique...
1531   * Product product =
1532   *     new QProduct()
1533   *         .sku.equalTo("aa113")
1534   *         .findOne();
1535   * ...
1536   * }</pre>
1537   * <p>
1538   * <p>
1539   * It is also useful with finding objects by their id when you want to specify
1540   * further join information to optimise the query.
1541   * </p>
1542   * <p>
1543   * <pre>{@code
1544   *
1545   * // Fetch order 42 and additionally fetch join its order details...
1546   * Order order =
1547   *     new QOrder()
1548   *         .fetch("details") // eagerly load the order details
1549   *         .id.equalTo(42)
1550   *         .findOne();
1551   *
1552   * // the order details were eagerly loaded
1553   * List<OrderDetail> details = order.getDetails();
1554   * ...
1555   * }</pre>
1556   */
1557  @Nullable
1558  public T findOne() {
1559    return query.findOne();
1560  }
1561
1562  /**
1563   * Execute the query returning an optional bean.
1564   */
1565  @Nonnull
1566  public Optional<T> findOneOrEmpty() {
1567    return query.findOneOrEmpty();
1568  }
1569
1570  /**
1571   * Execute the query returning the list of objects.
1572   * <p>
1573   * This query will execute against the EbeanServer that was used to create it.
1574   * </p>
1575   * <p>
1576   * <pre>{@code
1577   *
1578   * List<Customer> customers =
1579   *     new QCustomer()
1580   *       .name.ilike("rob%")
1581   *       .findList();
1582   *
1583   * }</pre>
1584   *
1585   * @see Query#findList()
1586   */
1587  @Nonnull
1588  public List<T> findList() {
1589    return query.findList();
1590  }
1591
1592  /**
1593   * Execute the query returning the result as a Stream.
1594   * <p>
1595   * Note that this will hold all resulting beans in memory using a single
1596   * persistence context. Use findLargeStream() for queries that expect to
1597   * return a large number of results.
1598   * </p>
1599   * <pre>{@code
1600   *
1601   *  // use try with resources to ensure Stream is closed
1602   *
1603   *  try (Stream<Customer> stream = query.findStream()) {
1604   *    stream
1605   *    .map(...)
1606   *    .collect(...);
1607   *  }
1608   *
1609   * }</pre>
1610   */
1611  @Nonnull
1612  public Stream<T> findSteam() {
1613    return query.findStream();
1614  }
1615
1616  /**
1617   * Execute the query returning the result as a Stream.
1618   * <p>
1619   * Note that this uses multiple persistence contexts such that we can use
1620   * it with a large number of results.
1621   * </p>
1622   * <pre>{@code
1623   *
1624   *  // use try with resources to ensure Stream is closed
1625   *
1626   *  try (Stream<Customer> stream = query.findLargeStream()) {
1627   *    stream
1628   *    .map(...)
1629   *    .collect(...);
1630   *  }
1631   *
1632   * }</pre>
1633   */
1634  public Stream<T> findLargeStream() {
1635    return query.findLargeStream();
1636  }
1637
1638  /**
1639   * Execute the query returning the set of objects.
1640   * <p>
1641   * This query will execute against the EbeanServer that was used to create it.
1642   * </p>
1643   * <p>
1644   * <pre>{@code
1645   *
1646   * Set<Customer> customers =
1647   *     new QCustomer()
1648   *       .name.ilike("rob%")
1649   *       .findSet();
1650   *
1651   * }</pre>
1652   *
1653   * @see Query#findSet()
1654   */
1655  @Nonnull
1656  public Set<T> findSet() {
1657    return query.findSet();
1658  }
1659
1660  /**
1661   * Execute the query returning the list of Id's.
1662   * <p>
1663   * This query will execute against the EbeanServer that was used to create it.
1664   * </p>
1665   *
1666   * @see Query#findIds()
1667   */
1668  @Nonnull
1669  public <A> List<A> findIds() {
1670    return query.findIds();
1671  }
1672
1673  /**
1674   * Execute the query returning a map of the objects.
1675   * <p>
1676   * This query will execute against the EbeanServer that was used to create it.
1677   * </p>
1678   * <p>
1679   * You can use setMapKey() or asMapKey() to specify the property to be used as keys
1680   * on the map. If one is not specified then the id property is used.
1681   * </p>
1682   * <p>
1683   * <pre>{@code
1684   *
1685   * Map<String, Product> map =
1686   *   new QProduct()
1687   *     .sku.asMapKey()
1688   *     .findMap();
1689   *
1690   * }</pre>
1691   *
1692   * @see Query#findMap()
1693   */
1694  @Nonnull
1695  public <K> Map<K, T> findMap() {
1696    return query.findMap();
1697  }
1698
1699  /**
1700   * Execute the query iterating over the results.
1701   * <p>
1702   * Note that findIterate (and findEach and findEachWhile) uses a "per graph"
1703   * persistence context scope and adjusts jdbc fetch buffer size for large
1704   * queries. As such it is better to use findList for small queries.
1705   * </p>
1706   * <p>
1707   * Remember that with {@link QueryIterator} you must call {@link QueryIterator#close()}
1708   * when you have finished iterating the results (typically in a finally block).
1709   * </p>
1710   * <p>
1711   * findEach() and findEachWhile() are preferred to findIterate() as they ensure
1712   * the jdbc statement and resultSet are closed at the end of the iteration.
1713   * </p>
1714   * <p>
1715   * This query will execute against the EbeanServer that was used to create it.
1716   * </p>
1717   * <pre>{@code
1718   *
1719   *  Query<Customer> query =
1720   *    new QCustomer()
1721   *     .status.equalTo(Customer.Status.NEW)
1722   *     .order()
1723   *       id.asc()
1724   *     .query();
1725   *
1726   *  try (QueryIterator<Customer> it = query.findIterate()) {
1727   *    while (it.hasNext()) {
1728   *      Customer customer = it.next();
1729   *      // do something with customer ...
1730   *    }
1731   *  }
1732   *
1733   * }</pre>
1734   */
1735  @Nonnull
1736  public QueryIterator<T> findIterate() {
1737    return query.findIterate();
1738  }
1739
1740  /**
1741   * Execute the query returning a list of values for a single property.
1742   * <p>
1743   * <h3>Example</h3>
1744   * <pre>{@code
1745   *
1746   *  List<String> names =
1747   *    new QCustomer()
1748   *      .setDistinct(true)
1749   *      .select(name)
1750   *      .findSingleAttributeList();
1751   *
1752   * }</pre>
1753   *
1754   * @return the list of values for the selected property
1755   */
1756  @Nonnull
1757  public <A> List<A> findSingleAttributeList() {
1758    return query.findSingleAttributeList();
1759  }
1760
1761  /**
1762   * Execute the query returning a single value for a single property.
1763   * <p>
1764   * <h3>Example</h3>
1765   * <pre>{@code
1766   *
1767   *  LocalDate maxDate =
1768   *    new QCustomer()
1769   *      .select("max(startDate)")
1770   *      .findSingleAttribute();
1771   *
1772   * }</pre>
1773   *
1774   * @return the list of values for the selected property
1775   */
1776  public <A> A findSingleAttribute() {
1777    return query.findSingleAttribute();
1778  }
1779
1780  /**
1781   * Execute the query processing the beans one at a time.
1782   * <p>
1783   * This method is appropriate to process very large query results as the
1784   * beans are consumed one at a time and do not need to be held in memory
1785   * (unlike #findList #findSet etc)
1786   * </p>
1787   * <p>
1788   * Note that internally Ebean can inform the JDBC driver that it is expecting larger
1789   * resultSet and specifically for MySQL this hint is required to stop it's JDBC driver
1790   * from buffering the entire resultSet. As such, for smaller resultSets findList() is
1791   * generally preferable.
1792   * </p>
1793   * <p>
1794   * Compared with #findEachWhile this will always process all the beans where as
1795   * #findEachWhile provides a way to stop processing the query result early before
1796   * all the beans have been read.
1797   * </p>
1798   * <p>
1799   * This method is functionally equivalent to findIterate() but instead of using an
1800   * iterator uses the QueryEachConsumer (SAM) interface which is better suited to use
1801   * with Java8 closures.
1802   * </p>
1803   * <p>
1804   * <pre>{@code
1805   *
1806   *  new QCustomer()
1807   *     .status.equalTo(Status.NEW)
1808   *     .orderBy().id.asc()
1809   *     .findEach((Customer customer) -> {
1810   *
1811   *       // do something with customer
1812   *       System.out.println("-- visit " + customer);
1813   *     });
1814   *
1815   * }</pre>
1816   *
1817   * @param consumer the consumer used to process the queried beans.
1818   */
1819  public void findEach(Consumer<T> consumer) {
1820    query.findEach(consumer);
1821  }
1822
1823  /**
1824   * Execute the query using callbacks to a visitor to process the resulting
1825   * beans one at a time.
1826   * <p>
1827   * This method is functionally equivalent to findIterate() but instead of using an
1828   * iterator uses the QueryEachWhileConsumer (SAM) interface which is better suited to use
1829   * with Java8 closures.
1830   * </p>
1831   * <p>
1832   * <p>
1833   * <pre>{@code
1834   *
1835   *  new QCustomer()
1836   *     .status.equalTo(Status.NEW)
1837   *     .order().id.asc()
1838   *     .findEachWhile((Customer customer) -> {
1839   *
1840   *       // do something with customer
1841   *       System.out.println("-- visit " + customer);
1842   *
1843   *       // return true to continue processing or false to stop
1844   *       return (customer.getId() < 40);
1845   *     });
1846   *
1847   * }</pre>
1848   *
1849   * @param consumer the consumer used to process the queried beans.
1850   */
1851  public void findEachWhile(Predicate<T> consumer) {
1852    query.findEachWhile(consumer);
1853  }
1854
1855  /**
1856   * Return versions of a @History entity bean.
1857   * <p>
1858   * Generally this query is expected to be a find by id or unique predicates query.
1859   * It will execute the query against the history returning the versions of the bean.
1860   * </p>
1861   */
1862  @Nonnull
1863  public List<Version<T>> findVersions() {
1864    return query.findVersions();
1865  }
1866
1867  /**
1868   * Return versions of a @History entity bean between a start and end timestamp.
1869   * <p>
1870   * Generally this query is expected to be a find by id or unique predicates query.
1871   * It will execute the query against the history returning the versions of the bean.
1872   * </p>
1873   */
1874  @Nonnull
1875  public List<Version<T>> findVersionsBetween(Timestamp start, Timestamp end) {
1876    return query.findVersionsBetween(start, end);
1877  }
1878
1879  /**
1880   * Return the count of entities this query should return.
1881   * <p>
1882   * This is the number of 'top level' or 'root level' entities.
1883   * </p>
1884   */
1885  @Nonnull
1886  public int findCount() {
1887    return query.findCount();
1888  }
1889
1890  /**
1891   * Execute find row count query in a background thread.
1892   * <p>
1893   * This returns a Future object which can be used to cancel, check the
1894   * execution status (isDone etc) and get the value (with or without a
1895   * timeout).
1896   * </p>
1897   *
1898   * @return a Future object for the row count query
1899   */
1900  @Nonnull
1901  public FutureRowCount<T> findFutureCount() {
1902    return query.findFutureCount();
1903  }
1904
1905  /**
1906   * Execute find Id's query in a background thread.
1907   * <p>
1908   * This returns a Future object which can be used to cancel, check the
1909   * execution status (isDone etc) and get the value (with or without a
1910   * timeout).
1911   * </p>
1912   *
1913   * @return a Future object for the list of Id's
1914   */
1915  @Nonnull
1916  public FutureIds<T> findFutureIds() {
1917    return query.findFutureIds();
1918  }
1919
1920  /**
1921   * Execute find list query in a background thread.
1922   * <p>
1923   * This query will execute in it's own PersistenceContext and using its own transaction.
1924   * What that means is that it will not share any bean instances with other queries.
1925   * </p>
1926   *
1927   * @return a Future object for the list result of the query
1928   */
1929  @Nonnull
1930  public FutureList<T> findFutureList() {
1931    return query.findFutureList();
1932  }
1933
1934  /**
1935   * Return a PagedList for this query using firstRow and maxRows.
1936   * <p>
1937   * The benefit of using this over findList() is that it provides functionality to get the
1938   * total row count etc.
1939   * </p>
1940   * <p>
1941   * If maxRows is not set on the query prior to calling findPagedList() then a
1942   * PersistenceException is thrown.
1943   * </p>
1944   * <p>
1945   * <pre>{@code
1946   *
1947   *  PagedList<Order> pagedList =
1948   *    new QOrder()
1949   *       .setFirstRow(50)
1950   *       .setMaxRows(20)
1951   *       .findPagedList();
1952   *
1953   *       // fetch the total row count in the background
1954   *       pagedList.loadRowCount();
1955   *
1956   *       List<Order> orders = pagedList.getList();
1957   *       int totalRowCount = pagedList.getTotalRowCount();
1958   *
1959   * }</pre>
1960   *
1961   * @return The PagedList
1962   */
1963  @Nonnull
1964  public PagedList<T> findPagedList() {
1965    return query.findPagedList();
1966  }
1967
1968  /**
1969   * Execute as a delete query deleting the 'root level' beans that match the predicates
1970   * in the query.
1971   * <p>
1972   * Note that if the query includes joins then the generated delete statement may not be
1973   * optimal depending on the database platform.
1974   * </p>
1975   *
1976   * @return the number of beans/rows that were deleted.
1977   */
1978  public int delete() {
1979    return query.delete();
1980  }
1981
1982  /**
1983   * Return the sql that was generated for executing this query.
1984   * <p>
1985   * This is only available after the query has been executed and provided only
1986   * for informational purposes.
1987   * </p>
1988   */
1989  public String getGeneratedSql() {
1990    return query.getGeneratedSql();
1991  }
1992
1993  /**
1994   * Return the type of beans being queried.
1995   */
1996  @Nonnull
1997  public Class<T> getBeanType() {
1998    return query.getBeanType();
1999  }
2000
2001  /**
2002   * Return the expression list that has been built for this query.
2003   */
2004  @Nonnull
2005  public ExpressionList<T> getExpressionList() {
2006    return query.where();
2007  }
2008
2009  /**
2010   * Start adding expressions to the having clause when using @Aggregation properties.
2011   *
2012   * <pre>{@code
2013   *
2014   *   new QMachineUse()
2015   *   // where ...
2016   *   .date.inRange(fromDate, toDate)
2017   *
2018   *   .having()
2019   *   .sumHours.greaterThan(1)
2020   *   .findList()
2021   *
2022   *   // The sumHours property uses @Aggregation
2023   *   // e.g. @Aggregation("sum(hours)")
2024   *
2025   * }</pre>
2026   */
2027  public R having() {
2028    if (whereStack == null) {
2029      whereStack = new ArrayStack<>();
2030    }
2031    // effectively putting having expression list onto stack
2032    // such that expression now add to the having clause
2033    whereStack.push(query.having());
2034    return root;
2035  }
2036
2037  /**
2038   * Return the underlying having clause to typically when using dynamic aggregation formula.
2039   * <p>
2040   * Note that after this we no longer have the query bean so typically we use this right
2041   * at the end of the query.
2042   * </p>
2043   *
2044   * <pre>{@code
2045   *
2046   *  // sum(distanceKms) ... is a "dynamic formula"
2047   *  // so we use havingClause() for it like:
2048   *
2049   *  List<MachineUse> machineUse =
2050   *
2051   *    new QMachineUse()
2052   *      .select("machine, sum(fuelUsed), sum(distanceKms)")
2053   *
2054   *      // where ...
2055   *      .date.greaterThan(LocalDate.now().minusDays(7))
2056   *
2057   *      .havingClause()
2058   *        .gt("sum(distanceKms)", 2)
2059   *        .findList();
2060   *
2061   * }</pre>
2062   */
2063  public ExpressionList<T> havingClause() {
2064    return query.having();
2065  }
2066
2067  /**
2068   * Return the current expression list that expressions should be added to.
2069   */
2070  protected ExpressionList<T> peekExprList() {
2071
2072    if (textMode) {
2073      // return the current text expression list
2074      return _peekText();
2075    }
2076
2077    if (whereStack == null) {
2078      whereStack = new ArrayStack<>();
2079      whereStack.push(query.where());
2080    }
2081    // return the current expression list
2082    return whereStack.peek();
2083  }
2084
2085  protected ExpressionList<T> _peekText() {
2086    if (textStack == null) {
2087      textStack = new ArrayStack<>();
2088      // empty so push on the queries base expression list
2089      textStack.push(query.text());
2090    }
2091    // return the current expression list
2092    return textStack.peek();
2093  }
2094}