1 // Copyright 2007 Google Inc. All rights reserved.
3 package com
.google
.appengine
.api
.datastore
;
5 import static com
.google
.appengine
.api
.datastore
.FetchOptions
.Builder
.withLimit
;
6 import static com
.google
.common
.base
.Preconditions
.checkArgument
;
8 import java
.util
.Iterator
;
12 * Implements PreparedQuery.
15 class PreparedQueryImpl
extends BasePreparedQuery
{
16 private final Query query
;
17 private final Transaction txn
;
18 private final QueryRunner queryRunner
;
20 public PreparedQueryImpl(Query query
, Transaction txn
, QueryRunner queryRunner
) {
23 this.queryRunner
= queryRunner
;
25 checkArgument(txn
== null || query
.getAncestor() != null,
26 "Only ancestor queries are allowed inside transactions.");
27 TransactionImpl
.ensureTxnActive(txn
);
30 private QueryResultIteratorImpl
runQuery(FetchOptions fetchOptions
) {
31 return new QueryResultIteratorImpl(this, queryRunner
.runQuery(fetchOptions
, query
, txn
),
36 public List
<Entity
> asList(FetchOptions fetchOptions
) {
37 return new LazyList(runQuery(fetchOptions
));
41 public QueryResultList
<Entity
> asQueryResultList(FetchOptions fetchOptions
) {
42 FetchOptions override
= new FetchOptions(fetchOptions
);
43 if (override
.getCompile() == null) {
44 override
.compile(true);
46 LazyList lazyList
= new LazyList(runQuery(override
));
51 public Iterator
<Entity
> asIterator(FetchOptions fetchOptions
) {
52 return runQuery(fetchOptions
);
56 public QueryResultIterator
<Entity
> asQueryResultIterator(FetchOptions fetchOptions
) {
57 if (fetchOptions
.getCompile() == null) {
58 fetchOptions
= new FetchOptions(fetchOptions
).compile(true);
60 return runQuery(fetchOptions
);
64 public Entity
asSingleEntity() throws TooManyResultsException
{
65 List
<Entity
> entities
= asList(withLimit(2));
66 if (entities
.isEmpty()) {
68 } else if (entities
.size() != 1) {
69 throw new TooManyResultsException();
71 return entities
.get(0);
76 * Counts the number of entities in the result set.
78 * This method will run a query that will offset past all results and return
79 * the number of results that have been skipped in the process.
81 * (offset, limit) is converted to (offset + limit, 0) so that no results are
82 * actually returned. The resulting count is max(0, skipped - offset). This
83 * is the number of entities in the range [offset, offset + limit) which is
86 public int countEntities(FetchOptions fetchOptions
) {
87 FetchOptions overrideOptions
= new FetchOptions(fetchOptions
);
89 overrideOptions
.limit(0);
90 if (fetchOptions
.getLimit() != null) {
91 if (fetchOptions
.getOffset() != null) {
92 int offset
= fetchOptions
.getLimit() + fetchOptions
.getOffset();
93 overrideOptions
.offset(offset
>= 0 ? offset
: Integer
.MAX_VALUE
);
95 overrideOptions
.offset(fetchOptions
.getLimit());
98 overrideOptions
.offset(Integer
.MAX_VALUE
);
101 int count
= runQuery(overrideOptions
).getNumSkipped();
102 if (fetchOptions
.getOffset() != null) {
103 if (count
< fetchOptions
.getOffset()) {
106 count
= count
- fetchOptions
.getOffset();
113 public String
toString() {
114 return query
+ (txn
!= null ?
" IN " + txn
: "");