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   * Marker that can be used to indicate that the order by clause is defined after this.
1148   * <p>
1149   * <h2>Example: order by customer name, order date</h2>
1150   * <pre>{@code
1151   *   List<Order> orders =
1152   *          new QOrder()
1153   *            .customer.name.ilike("rob")
1154   *            .orderBy()
1155   *              .customer.name.asc()
1156   *              .orderDate.asc()
1157   *            .findList();
1158   *
1159   * }</pre>
1160   */
1161  public R orderBy() {
1162    // Yes this does not actually do anything! We include it because style wise it makes
1163    // the query nicer to read and suggests that order by definitions are added after this
1164    return root;
1165  }
1166
1167  /**
1168   * Marker that can be used to indicate that the order by clause is defined after this.
1169   * <p>
1170   * <h2>Example: order by customer name, order date</h2>
1171   * <pre>{@code
1172   *   List<Order> orders =
1173   *          new QOrder()
1174   *            .customer.name.ilike("rob")
1175   *            .orderBy()
1176   *              .customer.name.asc()
1177   *              .orderDate.asc()
1178   *            .findList();
1179   *
1180   * }</pre>
1181   */
1182  public R order() {
1183    // Yes this does not actually do anything! We include it because style wise it makes
1184    // the query nicer to read and suggests that order by definitions are added after this
1185    return root;
1186  }
1187
1188  /**
1189   * Set the full raw order by clause replacing the existing order by clause if there is one.
1190   * <p>
1191   * This follows SQL syntax using commas between each property with the
1192   * optional asc and desc keywords representing ascending and descending order
1193   * respectively.
1194   */
1195  public R orderBy(String orderByClause) {
1196    query.orderBy(orderByClause);
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 order(String orderByClause) {
1208    query.order(orderByClause);
1209    return root;
1210  }
1211
1212  /**
1213   * Begin a list of expressions added by 'OR'.
1214   * <p>
1215   * Use endOr() or endJunction() to stop added to OR and 'pop' to the parent expression list.
1216   * </p>
1217   * <p>
1218   * <h2>Example</h2>
1219   * <p>
1220   * This example uses an 'OR' expression list with an inner 'AND' expression list.
1221   * </p>
1222   * <pre>{@code
1223   *
1224   *    List<Customer> customers =
1225   *          new QCustomer()
1226   *            .status.equalTo(Customer.Status.GOOD)
1227   *            .or()
1228   *              .id.greaterThan(1000)
1229   *              .and()
1230   *                .name.startsWith("super")
1231   *                .registered.after(fiveDaysAgo)
1232   *              .endAnd()
1233   *            .endOr()
1234   *            .orderBy().id.desc()
1235   *            .findList();
1236   *
1237   * }</pre>
1238   * <h2>Resulting SQL where clause</h2>
1239   * <pre>{@code sql
1240   *
1241   *    where t0.status = ?  and (t0.id > ?  or (t0.name like ?  and t0.registered > ? ) )
1242   *    order by t0.id desc;
1243   *
1244   *    --bind(GOOD,1000,super%,Wed Jul 22 00:00:00 NZST 2015)
1245   *
1246   * }</pre>
1247   */
1248  public R or() {
1249    pushExprList(peekExprList().or());
1250    return root;
1251  }
1252
1253  /**
1254   * Begin a list of expressions added by 'AND'.
1255   * <p>
1256   * Use endAnd() or endJunction() to stop added to AND and 'pop' to the parent expression list.
1257   * </p>
1258   * <p>
1259   * Note that typically the AND expression is only used inside an outer 'OR' expression.
1260   * This is because the top level expression list defaults to an 'AND' expression list.
1261   * </p>
1262   * <h2>Example</h2>
1263   * <p>
1264   * This example uses an 'OR' expression list with an inner 'AND' expression list.
1265   * </p>
1266   * <pre>{@code
1267   *
1268   *    List<Customer> customers =
1269   *          new QCustomer()
1270   *            .status.equalTo(Customer.Status.GOOD)
1271   *            .or() // OUTER 'OR'
1272   *              .id.greaterThan(1000)
1273   *              .and()  // NESTED 'AND' expression list
1274   *                .name.startsWith("super")
1275   *                .registered.after(fiveDaysAgo)
1276   *                .endAnd()
1277   *              .endOr()
1278   *            .orderBy().id.desc()
1279   *            .findList();
1280   *
1281   * }</pre>
1282   * <h2>Resulting SQL where clause</h2>
1283   * <pre>{@code sql
1284   *
1285   *    where t0.status = ?  and (t0.id > ?  or (t0.name like ?  and t0.registered > ? ) )
1286   *    order by t0.id desc;
1287   *
1288   *    --bind(GOOD,1000,super%,Wed Jul 22 00:00:00 NZST 2015)
1289   *
1290   * }</pre>
1291   */
1292  public R and() {
1293    pushExprList(peekExprList().and());
1294    return root;
1295  }
1296
1297  /**
1298   * Begin a list of expressions added by NOT.
1299   * <p>
1300   * Use endNot() or endJunction() to stop added to NOT and 'pop' to the parent expression list.
1301   * </p>
1302   */
1303  public R not() {
1304    pushExprList(peekExprList().not());
1305    return root;
1306  }
1307
1308  /**
1309   * Begin a list of expressions added by MUST.
1310   * <p>
1311   * This automatically makes this query a document store query.
1312   * </p>
1313   * <p>
1314   * Use endJunction() to stop added to MUST and 'pop' to the parent expression list.
1315   * </p>
1316   */
1317  public R must() {
1318    pushExprList(peekExprList().must());
1319    return root;
1320  }
1321
1322  /**
1323   * Begin a list of expressions added by MUST NOT.
1324   * <p>
1325   * This automatically makes this query a document store query.
1326   * </p>
1327   * <p>
1328   * Use endJunction() to stop added to MUST NOT and 'pop' to the parent expression list.
1329   * </p>
1330   */
1331  public R mustNot() {
1332    return pushExprList(peekExprList().mustNot());
1333  }
1334
1335  /**
1336   * Begin a list of expressions added by SHOULD.
1337   * <p>
1338   * This automatically makes this query a document store query.
1339   * </p>
1340   * <p>
1341   * Use endJunction() to stop added to SHOULD and 'pop' to the parent expression list.
1342   * </p>
1343   */
1344  public R should() {
1345    return pushExprList(peekExprList().should());
1346  }
1347
1348  /**
1349   * End a list of expressions added by 'OR'.
1350   */
1351  public R endJunction() {
1352    if (textMode) {
1353      textStack.pop();
1354    } else {
1355      whereStack.pop();
1356    }
1357    return root;
1358  }
1359
1360  /**
1361   * End OR junction - synonym for endJunction().
1362   */
1363  public R endOr() {
1364    return endJunction();
1365  }
1366
1367  /**
1368   * End AND junction - synonym for endJunction().
1369   */
1370  public R endAnd() {
1371    return endJunction();
1372  }
1373
1374  /**
1375   * End NOT junction - synonym for endJunction().
1376   */
1377  public R endNot() {
1378    return endJunction();
1379  }
1380
1381  /**
1382   * Push the expression list onto the appropriate stack.
1383   */
1384  private R pushExprList(ExpressionList<T> list) {
1385    if (textMode) {
1386      textStack.push(list);
1387    } else {
1388      whereStack.push(list);
1389    }
1390    return root;
1391  }
1392
1393  /**
1394   * Add expression after this to the WHERE expression list.
1395   * <p>
1396   * For queries against the normal database (not the doc store) this has no effect.
1397   * </p>
1398   * <p>
1399   * This is intended for use with Document Store / ElasticSearch where expressions can be put into either
1400   * the "query" section or the "filter" section of the query. Full text expressions like MATCH are in the
1401   * "query" section but many expression can be in either - expressions after the where() are put into the
1402   * "filter" section which means that they don't add to the relevance and are also cache-able.
1403   * </p>
1404   */
1405  public R where() {
1406    textMode = false;
1407    return root;
1408  }
1409
1410  /**
1411   * Begin added expressions to the 'Text' expression list.
1412   * <p>
1413   * This automatically makes the query a document store query.
1414   * </p>
1415   * <p>
1416   * For ElasticSearch expressions added to 'text' go into the ElasticSearch 'query context'
1417   * and expressions added to 'where' go into the ElasticSearch 'filter context'.
1418   * </p>
1419   */
1420  public R text() {
1421    textMode = true;
1422    return root;
1423  }
1424
1425  /**
1426   * Add a Text Multi-match expression (document store only).
1427   * <p>
1428   * This automatically makes the query a document store query.
1429   * </p>
1430   */
1431  public R multiMatch(String query, MultiMatch multiMatch) {
1432    peekExprList().multiMatch(query, multiMatch);
1433    return root;
1434  }
1435
1436  /**
1437   * Add a Text Multi-match expression (document store only).
1438   * <p>
1439   * This automatically makes the query a document store query.
1440   * </p>
1441   */
1442  public R multiMatch(String query, String... properties) {
1443    peekExprList().multiMatch(query, properties);
1444    return root;
1445  }
1446
1447  /**
1448   * Add a Text common terms expression (document store only).
1449   * <p>
1450   * This automatically makes the query a document store query.
1451   * </p>
1452   */
1453  public R textCommonTerms(String query, TextCommonTerms options) {
1454    peekExprList().textCommonTerms(query, options);
1455    return root;
1456  }
1457
1458  /**
1459   * Add a Text simple expression (document store only).
1460   * <p>
1461   * This automatically makes the query a document store query.
1462   * </p>
1463   */
1464  public R textSimple(String query, TextSimple options) {
1465    peekExprList().textSimple(query, options);
1466    return root;
1467  }
1468
1469  /**
1470   * Add a Text query string expression (document store only).
1471   * <p>
1472   * This automatically makes the query a document store query.
1473   * </p>
1474   */
1475  public R textQueryString(String query, TextQueryString options) {
1476    peekExprList().textQueryString(query, options);
1477    return root;
1478  }
1479
1480  /**
1481   * Execute the query using the given transaction.
1482   */
1483  public R usingTransaction(Transaction transaction) {
1484    query.usingTransaction(transaction);
1485    return root;
1486  }
1487
1488  /**
1489   * Execute the query using the given connection.
1490   */
1491  public R usingConnection(Connection connection) {
1492    query.usingConnection(connection);
1493    return root;
1494  }
1495
1496  /**
1497   * Execute the query returning true if a row is found.
1498   * <p>
1499   * The query is executed using max rows of 1 and will only select the id property.
1500   * This method is really just a convenient way to optimise a query to perform a
1501   * 'does a row exist in the db' check.
1502   * </p>
1503   *
1504   * <h2>Example using a query bean:</h2>
1505   * <pre>{@code
1506   *
1507   *   boolean userExists =
1508   *     new QContact()
1509   *       .email.equalTo("rob@foo.com")
1510   *       .exists();
1511   *
1512   * }</pre>
1513   *
1514   * <h2>Example:</h2>
1515   * <pre>{@code
1516   *
1517   *   boolean userExists = query()
1518   *     .where().eq("email", "rob@foo.com")
1519   *     .exists();
1520   *
1521   * }</pre>
1522   *
1523   * @return True if the query finds a matching row in the database
1524   */
1525  public boolean exists() {
1526    return query.exists();
1527  }
1528
1529  /**
1530   * Execute the query returning either a single bean or null (if no matching
1531   * bean is found).
1532   * <p>
1533   * If more than 1 row is found for this query then a PersistenceException is
1534   * thrown.
1535   * </p>
1536   * <p>
1537   * This is useful when your predicates dictate that your query should only
1538   * return 0 or 1 results.
1539   * </p>
1540   * <p>
1541   * <pre>{@code
1542   *
1543   * // assuming the sku of products is unique...
1544   * Product product =
1545   *     new QProduct()
1546   *         .sku.equalTo("aa113")
1547   *         .findOne();
1548   * ...
1549   * }</pre>
1550   * <p>
1551   * <p>
1552   * It is also useful with finding objects by their id when you want to specify
1553   * further join information to optimise the query.
1554   * </p>
1555   * <p>
1556   * <pre>{@code
1557   *
1558   * // Fetch order 42 and additionally fetch join its order details...
1559   * Order order =
1560   *     new QOrder()
1561   *         .fetch("details") // eagerly load the order details
1562   *         .id.equalTo(42)
1563   *         .findOne();
1564   *
1565   * // the order details were eagerly loaded
1566   * List<OrderDetail> details = order.getDetails();
1567   * ...
1568   * }</pre>
1569   */
1570  @Nullable
1571  public T findOne() {
1572    return query.findOne();
1573  }
1574
1575  /**
1576   * Execute the query returning an optional bean.
1577   */
1578  @Nonnull
1579  public Optional<T> findOneOrEmpty() {
1580    return query.findOneOrEmpty();
1581  }
1582
1583  /**
1584   * Execute the query returning the list of objects.
1585   * <p>
1586   * This query will execute against the EbeanServer that was used to create it.
1587   * </p>
1588   * <p>
1589   * <pre>{@code
1590   *
1591   * List<Customer> customers =
1592   *     new QCustomer()
1593   *       .name.ilike("rob%")
1594   *       .findList();
1595   *
1596   * }</pre>
1597   *
1598   * @see Query#findList()
1599   */
1600  @Nonnull
1601  public List<T> findList() {
1602    return query.findList();
1603  }
1604
1605  /**
1606   * Execute the query returning the result as a Stream.
1607   * <p>
1608   * Note that this can support very large queries iterating
1609   * any number of results. To do so internally it can use
1610   * multiple persistence contexts.
1611   * </p>
1612   * <pre>{@code
1613   *
1614   *  // use try with resources to ensure Stream is closed
1615   *
1616   *  try (Stream<Customer> stream = query.findStream()) {
1617   *    stream
1618   *    .map(...)
1619   *    .collect(...);
1620   *  }
1621   *
1622   * }</pre>
1623   */
1624  @Nonnull
1625  public Stream<T> findStream() {
1626    return query.findStream();
1627  }
1628
1629  /**
1630   * Deprecated - migrate to findStream().
1631   */
1632  @Deprecated
1633  public Stream<T> findLargeStream() {
1634    return query.findLargeStream();
1635  }
1636
1637  /**
1638   * Execute the query returning the set of objects.
1639   * <p>
1640   * This query will execute against the EbeanServer that was used to create it.
1641   * </p>
1642   * <p>
1643   * <pre>{@code
1644   *
1645   * Set<Customer> customers =
1646   *     new QCustomer()
1647   *       .name.ilike("rob%")
1648   *       .findSet();
1649   *
1650   * }</pre>
1651   *
1652   * @see Query#findSet()
1653   */
1654  @Nonnull
1655  public Set<T> findSet() {
1656    return query.findSet();
1657  }
1658
1659  /**
1660   * Execute the query returning the list of Id's.
1661   * <p>
1662   * This query will execute against the EbeanServer that was used to create it.
1663   * </p>
1664   *
1665   * @see Query#findIds()
1666   */
1667  @Nonnull
1668  public <A> List<A> findIds() {
1669    return query.findIds();
1670  }
1671
1672  /**
1673   * Execute the query returning a map of the objects.
1674   * <p>
1675   * This query will execute against the EbeanServer that was used to create it.
1676   * </p>
1677   * <p>
1678   * You can use setMapKey() or asMapKey() to specify the property to be used as keys
1679   * on the map. If one is not specified then the id property is used.
1680   * </p>
1681   * <p>
1682   * <pre>{@code
1683   *
1684   * Map<String, Product> map =
1685   *   new QProduct()
1686   *     .sku.asMapKey()
1687   *     .findMap();
1688   *
1689   * }</pre>
1690   *
1691   * @see Query#findMap()
1692   */
1693  @Nonnull
1694  public <K> Map<K, T> findMap() {
1695    return query.findMap();
1696  }
1697
1698  /**
1699   * Execute the query iterating over the results.
1700   * <p>
1701   * Note that findIterate (and findEach and findEachWhile) uses a "per graph"
1702   * persistence context scope and adjusts jdbc fetch buffer size for large
1703   * queries. As such it is better to use findList for small queries.
1704   * </p>
1705   * <p>
1706   * Remember that with {@link QueryIterator} you must call {@link QueryIterator#close()}
1707   * when you have finished iterating the results (typically in a finally block).
1708   * </p>
1709   * <p>
1710   * findEach() and findEachWhile() are preferred to findIterate() as they ensure
1711   * the jdbc statement and resultSet are closed at the end of the iteration.
1712   * </p>
1713   * <p>
1714   * This query will execute against the EbeanServer that was used to create it.
1715   * </p>
1716   * <pre>{@code
1717   *
1718   *  Query<Customer> query =
1719   *    new QCustomer()
1720   *     .status.equalTo(Customer.Status.NEW)
1721   *     .orderBy()
1722   *       id.asc()
1723   *     .query();
1724   *
1725   *  try (QueryIterator<Customer> it = query.findIterate()) {
1726   *    while (it.hasNext()) {
1727   *      Customer customer = it.next();
1728   *      // do something with customer ...
1729   *    }
1730   *  }
1731   *
1732   * }</pre>
1733   */
1734  @Nonnull
1735  public QueryIterator<T> findIterate() {
1736    return query.findIterate();
1737  }
1738
1739  /**
1740   * Execute the query returning a list of values for a single property.
1741   * <p>
1742   * <h3>Example</h3>
1743   * <pre>{@code
1744   *
1745   *  List<String> names =
1746   *    new QCustomer()
1747   *      .setDistinct(true)
1748   *      .select(name)
1749   *      .findSingleAttributeList();
1750   *
1751   * }</pre>
1752   *
1753   * @return the list of values for the selected property
1754   */
1755  @Nonnull
1756  public <A> List<A> findSingleAttributeList() {
1757    return query.findSingleAttributeList();
1758  }
1759
1760  /**
1761   * Execute the query returning a single value for a single property.
1762   * <p>
1763   * <h3>Example</h3>
1764   * <pre>{@code
1765   *
1766   *  LocalDate maxDate =
1767   *    new QCustomer()
1768   *      .select("max(startDate)")
1769   *      .findSingleAttribute();
1770   *
1771   * }</pre>
1772   *
1773   * @return the list of values for the selected property
1774   */
1775  public <A> A findSingleAttribute() {
1776    return query.findSingleAttribute();
1777  }
1778
1779  /**
1780   * Execute the query processing the beans one at a time.
1781   * <p>
1782   * This method is appropriate to process very large query results as the
1783   * beans are consumed one at a time and do not need to be held in memory
1784   * (unlike #findList #findSet etc)
1785   * </p>
1786   * <p>
1787   * Note that internally Ebean can inform the JDBC driver that it is expecting larger
1788   * resultSet and specifically for MySQL this hint is required to stop it's JDBC driver
1789   * from buffering the entire resultSet. As such, for smaller resultSets findList() is
1790   * generally preferable.
1791   * </p>
1792   * <p>
1793   * Compared with #findEachWhile this will always process all the beans where as
1794   * #findEachWhile provides a way to stop processing the query result early before
1795   * all the beans have been read.
1796   * </p>
1797   * <p>
1798   * This method is functionally equivalent to findIterate() but instead of using an
1799   * iterator uses the QueryEachConsumer (SAM) interface which is better suited to use
1800   * with Java8 closures.
1801   * </p>
1802   * <p>
1803   * <pre>{@code
1804   *
1805   *  new QCustomer()
1806   *     .status.equalTo(Status.NEW)
1807   *     .orderBy().id.asc()
1808   *     .findEach((Customer customer) -> {
1809   *
1810   *       // do something with customer
1811   *       System.out.println("-- visit " + customer);
1812   *     });
1813   *
1814   * }</pre>
1815   *
1816   * @param consumer the consumer used to process the queried beans.
1817   */
1818  public void findEach(Consumer<T> consumer) {
1819    query.findEach(consumer);
1820  }
1821
1822  /**
1823   * Execute the query using callbacks to a visitor to process the resulting
1824   * beans one at a time.
1825   * <p>
1826   * This method is functionally equivalent to findIterate() but instead of using an
1827   * iterator uses the QueryEachWhileConsumer (SAM) interface which is better suited to use
1828   * with Java8 closures.
1829   * </p>
1830   * <p>
1831   * <p>
1832   * <pre>{@code
1833   *
1834   *  new QCustomer()
1835   *     .status.equalTo(Status.NEW)
1836   *     .orderBy().id.asc()
1837   *     .findEachWhile((Customer customer) -> {
1838   *
1839   *       // do something with customer
1840   *       System.out.println("-- visit " + customer);
1841   *
1842   *       // return true to continue processing or false to stop
1843   *       return (customer.getId() < 40);
1844   *     });
1845   *
1846   * }</pre>
1847   *
1848   * @param consumer the consumer used to process the queried beans.
1849   */
1850  public void findEachWhile(Predicate<T> consumer) {
1851    query.findEachWhile(consumer);
1852  }
1853
1854  /**
1855   * Return versions of a @History entity bean.
1856   * <p>
1857   * Generally this query is expected to be a find by id or unique predicates query.
1858   * It will execute the query against the history returning the versions of the bean.
1859   * </p>
1860   */
1861  @Nonnull
1862  public List<Version<T>> findVersions() {
1863    return query.findVersions();
1864  }
1865
1866  /**
1867   * Return versions of a @History entity bean between a start and end timestamp.
1868   * <p>
1869   * Generally this query is expected to be a find by id or unique predicates query.
1870   * It will execute the query against the history returning the versions of the bean.
1871   * </p>
1872   */
1873  @Nonnull
1874  public List<Version<T>> findVersionsBetween(Timestamp start, Timestamp end) {
1875    return query.findVersionsBetween(start, end);
1876  }
1877
1878  /**
1879   * Return the count of entities this query should return.
1880   * <p>
1881   * This is the number of 'top level' or 'root level' entities.
1882   * </p>
1883   */
1884  @Nonnull
1885  public int findCount() {
1886    return query.findCount();
1887  }
1888
1889  /**
1890   * Execute find row count query in a background thread.
1891   * <p>
1892   * This returns a Future object which can be used to cancel, check the
1893   * execution status (isDone etc) and get the value (with or without a
1894   * timeout).
1895   * </p>
1896   *
1897   * @return a Future object for the row count query
1898   */
1899  @Nonnull
1900  public FutureRowCount<T> findFutureCount() {
1901    return query.findFutureCount();
1902  }
1903
1904  /**
1905   * Execute find Id's query in a background thread.
1906   * <p>
1907   * This returns a Future object which can be used to cancel, check the
1908   * execution status (isDone etc) and get the value (with or without a
1909   * timeout).
1910   * </p>
1911   *
1912   * @return a Future object for the list of Id's
1913   */
1914  @Nonnull
1915  public FutureIds<T> findFutureIds() {
1916    return query.findFutureIds();
1917  }
1918
1919  /**
1920   * Execute find list query in a background thread.
1921   * <p>
1922   * This query will execute in it's own PersistenceContext and using its own transaction.
1923   * What that means is that it will not share any bean instances with other queries.
1924   * </p>
1925   *
1926   * @return a Future object for the list result of the query
1927   */
1928  @Nonnull
1929  public FutureList<T> findFutureList() {
1930    return query.findFutureList();
1931  }
1932
1933  /**
1934   * Return a PagedList for this query using firstRow and maxRows.
1935   * <p>
1936   * The benefit of using this over findList() is that it provides functionality to get the
1937   * total row count etc.
1938   * </p>
1939   * <p>
1940   * If maxRows is not set on the query prior to calling findPagedList() then a
1941   * PersistenceException is thrown.
1942   * </p>
1943   * <p>
1944   * <pre>{@code
1945   *
1946   *  PagedList<Order> pagedList =
1947   *    new QOrder()
1948   *       .setFirstRow(50)
1949   *       .setMaxRows(20)
1950   *       .findPagedList();
1951   *
1952   *       // fetch the total row count in the background
1953   *       pagedList.loadRowCount();
1954   *
1955   *       List<Order> orders = pagedList.getList();
1956   *       int totalRowCount = pagedList.getTotalRowCount();
1957   *
1958   * }</pre>
1959   *
1960   * @return The PagedList
1961   */
1962  @Nonnull
1963  public PagedList<T> findPagedList() {
1964    return query.findPagedList();
1965  }
1966
1967  /**
1968   * Execute as a delete query deleting the 'root level' beans that match the predicates
1969   * in the query.
1970   * <p>
1971   * Note that if the query includes joins then the generated delete statement may not be
1972   * optimal depending on the database platform.
1973   * </p>
1974   *
1975   * @return the number of beans/rows that were deleted.
1976   */
1977  public int delete() {
1978    return query.delete();
1979  }
1980
1981  /**
1982   * Return the sql that was generated for executing this query.
1983   * <p>
1984   * This is only available after the query has been executed and provided only
1985   * for informational purposes.
1986   * </p>
1987   */
1988  public String getGeneratedSql() {
1989    return query.getGeneratedSql();
1990  }
1991
1992  /**
1993   * Return the type of beans being queried.
1994   */
1995  @Nonnull
1996  public Class<T> getBeanType() {
1997    return query.getBeanType();
1998  }
1999
2000  /**
2001   * Return the expression list that has been built for this query.
2002   */
2003  @Nonnull
2004  public ExpressionList<T> getExpressionList() {
2005    return query.where();
2006  }
2007
2008  /**
2009   * Start adding expressions to the having clause when using @Aggregation properties.
2010   *
2011   * <pre>{@code
2012   *
2013   *   new QMachineUse()
2014   *   // where ...
2015   *   .date.inRange(fromDate, toDate)
2016   *
2017   *   .having()
2018   *   .sumHours.greaterThan(1)
2019   *   .findList()
2020   *
2021   *   // The sumHours property uses @Aggregation
2022   *   // e.g. @Aggregation("sum(hours)")
2023   *
2024   * }</pre>
2025   */
2026  public R having() {
2027    if (whereStack == null) {
2028      whereStack = new ArrayStack<>();
2029    }
2030    // effectively putting having expression list onto stack
2031    // such that expression now add to the having clause
2032    whereStack.push(query.having());
2033    return root;
2034  }
2035
2036  /**
2037   * Return the underlying having clause to typically when using dynamic aggregation formula.
2038   * <p>
2039   * Note that after this we no longer have the query bean so typically we use this right
2040   * at the end of the query.
2041   * </p>
2042   *
2043   * <pre>{@code
2044   *
2045   *  // sum(distanceKms) ... is a "dynamic formula"
2046   *  // so we use havingClause() for it like:
2047   *
2048   *  List<MachineUse> machineUse =
2049   *
2050   *    new QMachineUse()
2051   *      .select("machine, sum(fuelUsed), sum(distanceKms)")
2052   *
2053   *      // where ...
2054   *      .date.greaterThan(LocalDate.now().minusDays(7))
2055   *
2056   *      .havingClause()
2057   *        .gt("sum(distanceKms)", 2)
2058   *        .findList();
2059   *
2060   * }</pre>
2061   */
2062  public ExpressionList<T> havingClause() {
2063    return query.having();
2064  }
2065
2066  /**
2067   * Return the current expression list that expressions should be added to.
2068   */
2069  protected ExpressionList<T> peekExprList() {
2070
2071    if (textMode) {
2072      // return the current text expression list
2073      return _peekText();
2074    }
2075
2076    if (whereStack == null) {
2077      whereStack = new ArrayStack<>();
2078      whereStack.push(query.where());
2079    }
2080    // return the current expression list
2081    return whereStack.peek();
2082  }
2083
2084  protected ExpressionList<T> _peekText() {
2085    if (textStack == null) {
2086      textStack = new ArrayStack<>();
2087      // empty so push on the queries base expression list
2088      textStack.push(query.text());
2089    }
2090    // return the current expression list
2091    return textStack.peek();
2092  }
2093}