private Object executeQuery(QueryData qd, long fromInclNo, long toExclNo) {
processInFilters(qd);
DatastoreService ds = DatastoreServiceFactoryInternal.getDatastoreService();
// Txns don't get started until you allocate a connection, so allocate a
// connection before we do anything that might require a txn.
ManagedConnection mconn = getStoreManager().getConnection(getObjectManager());
try {
if (qd.batchGetKeys != null &&
qd.primaryDatastoreQuery.getFilterPredicates().size() == 1 &&
qd.primaryDatastoreQuery.getSortPredicates().isEmpty()) {
// only execute a batch get if there aren't any other
// filters or sorts
return fulfillBatchGetQuery(ds, qd, mconn);
} else if (qd.joinQuery != null) {
FetchOptions opts = buildFetchOptions(fromInclNo, toExclNo);
JoinHelper joinHelper = new JoinHelper();
return wrapEntityQueryResult(
joinHelper.executeJoinQuery(qd, this, ds, opts),
qd.resultTransformer, ds, mconn, null);
} else {
latestDatastoreQuery = qd.primaryDatastoreQuery;
Transaction txn = null;
Map extensions = query.getExtensions();
// give users a chance to opt-out of having their query execute in a txn
if (extensions == null ||
!extensions.containsKey(DatastoreManager.EXCLUDE_QUERY_FROM_TXN) ||
!(Boolean)extensions.get(DatastoreManager.EXCLUDE_QUERY_FROM_TXN)) {
// If this is an ancestor query, execute it in the current transaction
txn = qd.primaryDatastoreQuery.getAncestor() != null ? ds.getCurrentTransaction(null) : null;
}
PreparedQuery preparedQuery = ds.prepare(txn, qd.primaryDatastoreQuery);
FetchOptions opts = buildFetchOptions(fromInclNo, toExclNo);
if (qd.resultType == ResultType.COUNT) {
return fulfillCountQuery(preparedQuery, opts);
} else {
if (qd.resultType == ResultType.KEYS_ONLY || isBulkDelete()) {
qd.primaryDatastoreQuery.setKeysOnly();
}
return fulfillEntityQuery(preparedQuery, opts, qd.resultTransformer, ds, mconn);
}
}
} finally {
mconn.release();
}
}