All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.appengine.api.datastore.QueryRunnerV3 Maven / Gradle / Ivy

Go to download

API for Google App Engine standard environment with some of the dependencies shaded (repackaged)

There is a newer version: 2.0.27
Show newest version
/*
 * Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.appengine.api.datastore;

import com.google.appengine.api.datastore.CompositeIndexManager.IndexComponentsOnlyQuery;
import com.google.appengine.api.datastore.CompositeIndexManager.IndexSource;
import com.google.appengine.api.datastore.ReadPolicy.Consistency;
import com.google.appengine.api.utils.FutureWrapper;
import com.google.apphosting.api.ApiProxy.ApiConfig;
import com.google.apphosting.datastore.DatastoreV3Pb;
import com.google.apphosting.datastore.DatastoreV3Pb.DatastoreService_3.Method;
import com.google.storage.onestore.v3.OnestoreEntity;
import java.util.concurrent.Future;

/**
 * V3 service specific code for constructing and sending queries. This class is threadsafe and has
 * no state.
 */
final class QueryRunnerV3 implements QueryRunner {

  private final DatastoreServiceConfig datastoreServiceConfig;
  private final ApiConfig apiConfig;

  QueryRunnerV3(DatastoreServiceConfig datastoreServiceConfig, ApiConfig apiConfig) {
    this.datastoreServiceConfig = datastoreServiceConfig;
    this.apiConfig = apiConfig;
  }

  @Override
  public QueryResultsSource runQuery(FetchOptions fetchOptions, Query query, Transaction txn) {
    final DatastoreV3Pb.Query queryProto = convertToPb(query, txn, fetchOptions);
    if (datastoreServiceConfig.getReadPolicy().getConsistency() == Consistency.EVENTUAL) {
      queryProto.setFailoverMs(BaseAsyncDatastoreServiceImpl.ARBITRARY_FAILOVER_READ_MS);
      queryProto.setStrong(false); // Allows the datastore to always use READ_CONSISTENT.
    }

    Future result =
        DatastoreApiHelper.makeAsyncCall(
            apiConfig, Method.RunQuery, queryProto, new DatastoreV3Pb.QueryResult());

    // Adding more info to DatastoreNeedIndexException if thrown
    result =
        new FutureWrapper(result) {
          @Override
          protected Throwable convertException(Throwable cause) {
            if (cause instanceof DatastoreNeedIndexException) {
              addMissingIndexData(queryProto, (DatastoreNeedIndexException) cause);
            }
            return cause;
          }

          @Override
          protected DatastoreV3Pb.QueryResult wrap(DatastoreV3Pb.QueryResult result)
              throws Exception {
            return result;
          }
        };

    return new QueryResultsSourceV3(
        datastoreServiceConfig.getDatastoreCallbacks(),
        fetchOptions,
        txn,
        query,
        result,
        apiConfig);
  }

  private void addMissingIndexData(DatastoreV3Pb.Query queryProto, DatastoreNeedIndexException e) {
    IndexComponentsOnlyQuery indexQuery = new IndexComponentsOnlyQuery(queryProto);
    CompositeIndexManager mgr = new CompositeIndexManager();
    OnestoreEntity.Index index = mgr.compositeIndexForQuery(indexQuery);
    if (index != null) {
      String xml = mgr.generateXmlForIndex(index, IndexSource.manual);
      e.setMissingIndexDefinitionXml(xml);
    } else {
      // Prod says we need an index but the index manager says we don't.
      // Probably a bug in the index manager.  DatastoreNeedIndexException
      // will report this in the exception message.
    }
  }

  private DatastoreV3Pb.Query convertToPb(Query q, Transaction txn, FetchOptions fetchOptions) {
    DatastoreV3Pb.Query queryProto = QueryTranslator.convertToPb(q, fetchOptions);
    if (txn != null) {
      TransactionImpl.ensureTxnActive(txn);
      queryProto.setTransaction(InternalTransactionV3.toProto(txn));
    }
    return queryProto;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy